docs: public String format(Thread thread, String formatString) {
        final StringBuilder builder = new StringBuilder(formatString.length() * 5);
        final ThreadGroup group = thread.getThreadGroup();
        final Matcher matcher = searchPattern.matcher(formatString);
        while (matcher.find()) {
           if (matcher.group(1) != null) {
              builder.append(matcher.group());
           } else {
              switch (matcher.group().charAt(1)) {
                 case '%': builder.append('%'); break;
                 case 't': builder.append(perFactoryThreadSequenceNum); break;
                 case 'g': builder.append(globalThreadSequenceNum); break;
                 case 'f': builder.append(factorySequenceNum); break;
                 case 'p': if (group != null) appendGroupPath(group, builder); break;
                 case 'i': builder.append(thread.getId()); break;
                 case 'G': if (group != null) builder.append(group.getName()); break;
                 case 'n': if (node != null) builder.append(node); break;
                 case 'c': if (component != null) builder.append(component); break;
              }
           }
        }
        return builder.toString();
     }