Skip to content

Instantly share code, notes, and snippets.

@chrsan
Created September 27, 2012 13:14
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrsan/3793920 to your computer and use it in GitHub Desktop.
Save chrsan/3793920 to your computer and use it in GitHub Desktop.
A logback discriminator for the akkaSource MDC value.
package se.fishtank;
import java.net.URI;
import java.util.Map;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.sift.Discriminator;
import ch.qos.logback.core.spi.ContextAwareBase;
public class AkkaSourceDiscriminator extends ContextAwareBase implements Discriminator<ILoggingEvent> {
private String key;
private String defaultValue;
private String actorPathContains;
private boolean onlyUseActorName = true;
private boolean started = false;
@Override
public String getDiscriminatingValue(ILoggingEvent event) {
Map<String, String> mdc = event.getMDCPropertyMap();
if (mdc == null) return defaultValue;
String value = mdc.get("akkaSource");
if (value == null || !value.contains(actorPathContains)) return defaultValue;
String path = getPath(value);
if (path == null || "/".equals(path)) return defaultValue;
if (onlyUseActorName) {
int idx = path.lastIndexOf('/');
if (idx == -1) return defaultValue;
return path.substring(idx + 1);
} else {
if (path.charAt(0) == '/')
path = path.substring(1);
return path.replace('/', '-');
}
}
@Override
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
public void setActorPathContains(String actorPathContains) {
this.actorPathContains = actorPathContains;
}
public void setOnlyUseActorName(String value) {
if (value != null) {
if ("true".equals(value)) {
onlyUseActorName = true;
} else if ("false".equals(value)) {
onlyUseActorName = false;
} else {
throw new IllegalArgumentException("Expected \"true\" or \"false\" for property \"OnlyUseActorName\"");
}
}
}
@Override
public void start() {
started = isValid("Key", key)
&& isValid("DefaultValue", defaultValue)
&& isValid("ActorPathContains", actorPathContains);
}
@Override
public void stop() {
started = false;
}
@Override
public boolean isStarted() {
return started;
}
private String getPath(String akkaSource) {
try {
return new URI(akkaSource).getPath();
} catch (Exception e) {
return null;
}
}
private boolean isValid(String property, String value) {
if (value == null || value.isEmpty()) {
addError("The \"" + property + "\" property must be set");
return false;
}
return true;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false" debug="false">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{ISO8601} %-5level %logger{36} %X{akkaSource} %X{sourceThread} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE_DEBUG" class="ch.qos.logback.core.FileAppender">
<file>/tmp/debug.log</file>
<encoder>
<pattern>%date{ISO8601} %-5level %logger{36} %X{akkaSource} %X{sourceThread} - %msg%n</pattern>
</encoder>
</appender>
<appender name="SIFT_ACTOR1" class="ch.qos.logback.classic.sift.SiftingAppender">
<discriminator class="se.fishtank.AkkaSourceDiscriminator">
<key>actor</key>
<defaultValue>unknown</defaultValue>
<!-- What the actor path should contain to consider this a match. -->
<actorPathContains>actor1</actorPathContains>
<!-- Uncomment the stuff below to use the full actor path as the filename. -->
<!--
<onlyUseActorName>false</onlyUseActorName>
-->
</discriminator>
<sift>
<appender name="FILE_ACTOR_${actor}" class="ch.qos.logback.core.FileAppender">
<file>/tmp/${actor}.log</file>
<encoder>
<pattern>%date{ISO8601} %-5level %logger{36} %X{akkaSource} %X{sourceThread} - %msg%n</pattern>
</encoder>
</appender>
</sift>
</appender>
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE_DEBUG"/>
<appender-ref ref="SIFT_ACTOR1"/>
</root>
</configuration>
@chrsan
Copy link
Author

chrsan commented Sep 27, 2012

When setting <onlyUseActorName>false</onlyUseActorName> the full actor path will be used as the filename prefix. I.e. if the path is /user/foo/bar the filename prefix will be user-foo-bar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment