Structured logging where logger argument not wanted in message

3.2k views Asked by At

I'm using structured logging in a Spring Boot app using logstash and sometimes I want to include key values in the log that I don't want to be used in the message of the log. Is there a StructuredArgument or similar that allows for this?

An example of what I am doing currently is something like this:

// import lombok.extern.slf4j.Slf4j;
// import static net.logstash.logback.argument.StructuredArguments.kv;
// import static net.logstash.logback.argument.StructuredArguments.v;

log.info(
  "My message with one arg {}", 
  v("key1":"arg I want to include value in place of placeholder in message and in json as key/value"), 
  kv("key2", "arg I only want in the json and not in the message"))

Everything works as I intended, by which I mean the log includes both key value pairs and the message only includes the first value in place of the placeholder. The issue is that I get a warning from the compiler which is flagged by intellij (PlaceholderCountMatchesArgumentCount) about the second structured argument and I would like to avoid this without resorting to suppressing/ignoring it

3

There are 3 answers

0
art On

You can use Markers and pass it before your logging message - more details on github.

logger.info(append("key2", "only json"), 
               "My message with one arg {}", 
               v("key1":"arg in msg and json"));

I personally don't like this because markers have different purpose, so if structured argument works for you, just ignore warning in IDE.

Anyway, all this json/structured implementations are workarounds for SLF4J 1.*, which has not built for that. There was SLF4J 2.0.0-alpha1 release almost a yeah ago, but it is still in alpha and I haven't used it. But it's API should be ready for key-values that are crusial in nowadays distributed log management systems.

0
Albin On

You can make the log message as a constant String, then the code quality checks will not warn this

0
JurajO On

You can make the structured argument print nothing into the formatted message:

  • (1) include the second placeholder {} inside the message
  • (2) use keyValue() instead of kv()
  • (3) provide the optional messageFormatPattern parameter (JavaDoc) equal to ""

Adjusting your example:

log.info(
  "My message with one arg {}{}", //note (1)
  v("key1":"arg I want to include value in place of placeholder in message and in json as key/value"), 
  keyValue("key2", "arg I only want in the json and not in the message", "")) //note (2) + (3)

This will effectively replace the second placeholder with an empty string.