Skip to content

Instantly share code, notes, and snippets.

@kdgregory
Last active Feb 24, 2022
Embed
What would you like to do?
AutoMDC: manage the SLF4J mapped diagnostic context using try-with-resources
// This code has been placed in the public domain by the author.
//
// You may use, modify, and redistribute without restriction.
//
// Use of this software is on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied.
package com.kdgregory.example;
import java.util.HashSet;
import java.util.Set;
import org.slf4j.MDC;
/**
* This class leverages the try-with-resources feature of Java 1.7 and later to
* manage the SLF4J mapped diagnostic context.
*/
public final class AutoMDC
implements AutoCloseable
{
private Set<String> keys;
/**
* Default constructor; call the {@link #put} method to add keys and values.
*/
public AutoMDC()
{
keys = new HashSet<>();
}
/**
* Convenience constructor, for when you have a single key/value pair.
*/
public AutoMDC(String key, Object value)
{
this();
put(key, value);
}
/**
* Adds a key/value pair to the MDC.
*/
public AutoMDC put(String key, Object value)
{
keys.add(key);
MDC.put(key, String.valueOf(value));
return this;
}
@Override
public void close() throws Exception
{
for (String key : keys)
{
MDC.remove(key);
}
}
}
<configuration debug="false">
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{ISO8601} %-5level [%thread] %logger{24} - %mdc - %msg%n</pattern>
</encoder>
</appender>
<root level="warn">
<appender-ref ref="CONSOLE" />
</root>
<logger name="com.kdgregory" level="debug"/>
</configuration>
// This code has been placed in the public domain by the author.
//
// You may use, modify, and redistribute without restriction.
//
// Use of this software is on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied.
package com.kdgregory.example;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Uses the AutoMDC class to update the MDC.
*/
public class Main
{
private static Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] argv)
throws Exception
{
logger.info("program starting");
File file = new File(argv[0]);
try (AutoMDC mdc = new AutoMDC("outputFile", file.getAbsolutePath());
FileOutputStream fos = new FileOutputStream(file);
OutputStreamWriter osr = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
BufferedWriter out = new BufferedWriter(osr))
{
logger.info("starting to write");
out.write("hello, world");
out.newLine();
logger.info("finished writing");
}
logger.info("program finished");
}
}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kdgregory.example</groupId>
<artifactId>automdc</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>AutoMDC</name>
<description>
Example of using AutoCloseable to manage the MDC
</description>
<properties>
<jdk.version>1.8</jdk.version>
<!-- build configuration props, because Maven can't pick a sensible default -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<logback.version>1.2.3</logback.version>
<plugin.compiler.version>3.1</plugin.compiler.version>
<plugin.shade.version>3.1.1</plugin.shade.version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${plugin.compiler.version}</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
<debug>true</debug>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>${plugin.shade.version}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.kdgregory.example.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
// This code has been placed in the public domain by the author.
//
// You may use, modify, and redistribute without restriction.
//
// Use of this software is on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied.
package com.kdgregory.example;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
/**
* Demonstrates "traditional" use of the MDC.
*/
public class TradMain
{
private static Logger logger = LoggerFactory.getLogger(TradMain.class);
public static void main(String[] argv)
throws Exception
{
logger.info("program starting");
File file = new File(argv[0]);
MDC.put("outputFile", file.getAbsolutePath());
try (FileOutputStream fos = new FileOutputStream(file);
OutputStreamWriter osr = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
BufferedWriter out = new BufferedWriter(osr))
{
logger.info("starting to write");
out.write("hello, world");
out.newLine();
logger.info("finished writing");
}
MDC.remove("outputFile");
logger.info("program finished");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment