Uploaded image for project: 'logback'
  1. logback
  2. LOGBACK-1505

HTMLLayout - Performance Issue

    XMLWordPrintable

Details

    • Icon: Improvement Improvement
    • Resolution: Unresolved
    • Icon: Major Major
    • None
    • 1.1.8, 1.3.0-alpha5
    • logback-core
    • Issue is not limited to any OS & hardware combination.

       

    Description

      I observed this performance issue in 1.1.8 onward and even in latest 1.3.0-alpha5, same issue is present.

       

      =============================================

      Problem statement:

      =============================================

      We had configured SMTPAppender to generate error emails using HTMLLayout using default pattern.

      In production env, our process end up generating logger.error with 27MB of message which also had data (I know that at first place our system should not have generated 27MB of error message but that want happened and we observed this performance issue.)

      Here logback HTMLLayout was running for 70mins just to process that 27MB of data.

      I know you might think I am stupid, but was able to trace root cause.

      Performance issue is present in 

      ch.qos.logback.core.helpers.Transformer::escapeTags(final StringBuffer buf) method.

      They way it is replacing and encoding html characters is not efficient, each replace is doing System.arraycopy which was issue, here our payload had some one million single quotes due to json data which was getting printed in log.

       

      Much better and correct way can be found in Log4j implementation of escapeTags

      as shown below. this only taken approx 280millis to process same 27MB vs 70mins taken by logback implementation. 

      public static String escapeHtmlTags(String input) {
      if (Strings.isEmpty(input) || input.indexOf(34) == -1 && input.indexOf(38) == -1 && input.indexOf(60) == -1 && input.indexOf(62) == -1 && input.indexOf(39) == -1 ) {
      return input;
      } else {
      StringBuilder buf = new StringBuilder(input.length() + 6);
      int len = input.length();

      for (int i = 0; i < len; ++i) {
      char ch = input.charAt;
      if (ch > '>') {
      buf.append(ch);
      } else if (ch == '<') {
      buf.append("<");
      } else if (ch == '>') {
      buf.append(">");
      } else if (ch == '&') {
      buf.append("&");
      } else if (ch == '"') {
      buf.append(""");
      } else if (ch == '\'') {
      buf.append("'");
      } else {
      buf.append(ch);
      }
      }

      return buf.toString();
      }
      }

       

      Attachments

        Activity

          People

            logback-dev Logback dev list
            Kapilpatil84 Kapil Patil
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated: