code: public RateLimitedLogWithPattern get(final String message) {
          // fast path: hopefully we can do this without creating a Supplier object
          RateLimitedLogWithPattern got = knownPatterns.get(message);
          if (got != null) {
              return got;
          }
  
          // before we create another one, check cache capacity first
          if (knownPatterns.size() > MAX_PATTERNS_PER_LOG) {
              outOfCacheCapacity();
          }
  
          // slow path: create a RateLimitedLogWithPattern
          RateLimitedLogWithPattern newValue = new RateLimitedLogWithPattern(message, rateAndPeriod, registry, stats, stopwatch, logger);
          RateLimitedLogWithPattern oldValue = knownPatterns.putIfAbsent(message, newValue);
          if (oldValue != null) {
              return oldValue;
          } else {
              return newValue;
          }
      }
docs: @return a RateLimitedLogWithPattern object for the supplied @param message.  This can be cached and
  reused by callers in performance-sensitive cases to avoid performing a ConcurrentHashMap lookup.
  
  Note that the string is the sole key used, so the same string cannot be reused with differing period
  settings; any periods which differ from the first one used are ignored.
  
  @throws IllegalStateException if we exceed the limit on number of RateLimitedLogWithPattern objects
  in any one period; if this happens, it's probable that an already-interpolated string is
  accidentally being used as a log pattern.