Issue Type: New Feature New Feature
Affects Versions: 1.0.13
Assignee: Logback dev list
Components: logback-classic
Created: 23/Jan/14 10:39 AM
Description:

Add a %match converter:

import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.pattern.ClassicConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.boolex.EvaluationException;
import ch.qos.logback.core.boolex.EventEvaluator;
import ch.qos.logback.core.status.ErrorStatus;

import javax.annotation.Nonnull;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static ch.qos.logback.core.CoreConstants.EVALUATOR_MAP;
import static java.util.Collections.emptyMap;

/**

  • {@code MarkedConverter}

    provides alternate conversions based on conditions. Enable with:

  • <pre>
  • <conversionRule
  • conversionWord="match"
  • converterClass="mbl.laboratory.util.logging.osi.MatchConverter"/></pre> Use as:
  • <pre>
  • <pattern>%match {cond1,patt1,...,fallback}

    </pattern></pre> Example:

  • <pre>
  • <evaluator name="WITH_MARKER">
  • <expression>null != marker &mp;&mp; "ALERT".equals(marker.getName())</expression>
  • </evaluator>
  • <pattern>%match(WITH_MARKER,%marker/%level,%level)</pattern></pre> will log
  • "ALERT/ERROR" when marker is "ALERT" and level is "ERROR", otherwise just "ERROR".
    *
  • @author <a href="mailto:Brian.Oxley@macquarie.com">Brian Oxley</a>
  • @todo Fix error reporting - logback swallows
    */
    public final class MatchConverter
    extends ClassicConverter {
    private static final int MAX_ERROR_COUNT = 4;
    private Map<String, String> conditions;
    private String unmatched;
    private Map<String, EventEvaluator<ILoggingEvent>> evaluators;
    private int errors;

@Override
public void start() {
final List<String> options = getOptionList();
if (null == options || 2 > options.size())

{ addError("Missing options for %match - " + Objects.toString(options)); conditions = emptyMap(); unmatched = ""; return; }

conditions = new LinkedHashMap<>();
for (int i = 0; i < options.size() - 1; i += 2)
conditions.put(options.get, options.get(i + 1));
unmatched = 0 == options.size() % 2 ? "" : options.get(options.size() - 1);

evaluators = (Map<String, EventEvaluator<ILoggingEvent>>) getContext()
.getObject(EVALUATOR_MAP);

super.start();
}

@Nonnull
@Override
public String convert(@Nonnull final ILoggingEvent event)

{ for (final Map.Entry<String, String> entry : conditions.entrySet()) if (evaluate(entry.getKey(), event)) return relayout(entry.getValue(), event); return relayout(unmatched, event); }

private boolean evaluate(final String name, final ILoggingEvent event) {
final EventEvaluator<ILoggingEvent> evaluator = evaluators.get(name);
try

{ return null != evaluator && evaluator.evaluate(event); }

catch (final EvaluationException e) {
errors++;
if (errors < MAX_ERROR_COUNT)

{ addError("Exception thrown for evaluator named [" + evaluator.getName() + "]", e); }

else if (errors == MAX_ERROR_COUNT)

{ ErrorStatus errorStatus = new ErrorStatus( "Exception thrown for evaluator named [" + evaluator.getName() + "].", this, e); errorStatus.add(new ErrorStatus( "This was the last warning about this evaluator's errors." + "We don't want the StatusManager to get flooded.", this)); addStatus(errorStatus); }

return false;
}
}

private String relayout(final String pattern, final ILoggingEvent event)

{ final PatternLayout layout = new PatternLayout(); layout.setContext(getContext()); layout.setPattern(pattern); layout.start(); return layout.doLayout(event); }

}

Project: logback
Priority: Major Major
Reporter: B. K. Oxley (binkley)
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira