Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import of LogstashLayout as JsonTemplateLayout #335

Merged
merged 70 commits into from
May 25, 2020
Merged

Import of LogstashLayout as JsonTemplateLayout #335

merged 70 commits into from
May 25, 2020

Conversation

vy
Copy link
Member

@vy vy commented Jan 28, 2020

This is the very first draft of my work on contributing log4j2-logstash-layout into Log4j core. Please note that this is still a work in progress. I want to have your feedback and support on the following issues which I will share below.

Goals

Below is the list of goals I plan to deliver in order:

  • Update manual
  • Replace Uris with LoaderUtils
  • Add directive for "nanos of epoch millis", "millis of epoch seconds", etc.
  • Move pattern, timeZone, locale parameters into timestamp key level.
  • Add benchmark to log4j-perf
  • Rename log4j-layout-jackson-json-template to log4j-layout-json-template
  • Replace TLAs with a user-provided 3-way caching strategy

I will update this list upon progress.

Module and package name

I chose JsonTemplateLayout as the new module name, which clearly communicates the intent. I am not totally convinced with the package name o.a.l.log4j.jackson.json.template.layout though. I have my doubts about whether we can remove Jackson dependency in the future or not. This ambition does look neither feasible, nor practical in the short-term. That said, from an API perspective, why shall an internal detail like jackson get exposed in the package name? I am considering to place it under o.a.l.log4j.layout.json.template. Any ideas?

Documentation

LogstashLayout has quite some configuration knobs which renders it inconvenient to explain it in /src/site/asciidoc/manual/layouts.adoc. I have skimmed through the source code with the hope of finding a similar documentation pattern, but failed to do so. Would somebody mind shedding some light onto the convention I should follow here, please?

MapMessage#getFormattedMessage() JSON encoding bug

As reported in LOG4J2-2703, MapMessage#getFormattedMessage() is incorrectly formatting Objects for JSON. As a workaround in LogstashLayout, I had a LogstashLayout.Builder#mapMessageFormatterIgnored property, which I have dragged into JsonTemplateLayout.Builder too. The property instructs the layout to ignore MapMessage#getFormattedMessage() and do its own magic to properly encode the MapMessage into JSON. Shall I keep this ad-hoc fix or rather resolve LOG4J2-2703 first?

Performance tests

I have some test utility classes that I want to leverage in performance tests, but test classpath of log4j-jackson-json-template module is not accessible by log4j-perf module. What is the work around here?

What to do with JsonLayout?

I do not intend to implement JsonLayout by leveraging JsonTemplateLayout, at least, not now. I would rather just leave it be and get deprecated eventually. Put another way, is this PR the right place to address this issue?

Missing features compared to JsonLayout

You might have noticed that JsonTemplateLayout misses certain features (e.g., compact, complete, header, footer, etc.) compared to JsonLayout. This is a deliberate decision of mine. If you have any objections, please chime in.

Thread locals

Even though the existing TLA usage of LogstashLayout is dragged in, I am going to replace it with an object pool. I have spotted ThreadLocalVsPoolBenchmark and will start from there.

@jvz
Copy link
Member

jvz commented Jan 28, 2020

I chose JsonTemplateLayout as the new module name, which clearly communicates the intent. I am not totally convinced with the package name o.a.l.log4j.jackson.json.template.layout though. I have my doubts about whether we can remove Jackson dependency in the future or not. This ambition does look neither feasible, nor practical in the short-term. That said, from an API perspective, why shall an internal detail like jackson get exposed in the package name? I am considering to place it under o.a.l.log4j.layout.json.template. Any ideas?

No need to put jackson in early like that I think. The package was moved around for modularization in 3.x which makes me think we can still rename things.

LogstashLayout has quite some configuration knobs which renders it inconvenient to explain it in /src/site/asciidoc/manual/layouts.adoc. I have skimmed through the source code with the hope of finding a similar documentation pattern, but failed to do so. Would somebody mind shedding some light onto the convention I should follow here, please?

You can use other formats if that makes it easier, though we may have to get creative.

I have some test utility classes that I want to leverage in performance tests, but test classpath of log4j-jackson-json-template module is not accessible by log4j-perf module. What is the work around here?

You can add the tests jar as a dependency to log4j-perf.

I do not intend to implement JsonLayout by leveraging JsonTemplateLayout, at least, not now. I would rather just leave it be and get deprecated eventually. Put another way, is this PR the right place to address this issue?

Can likely be done as a follow up.

@vy
Copy link
Member Author

vy commented Jan 29, 2020

I chose JsonTemplateLayout as the new module name, which clearly communicates the intent. I am not totally convinced with the package name o.a.l.log4j.jackson.json.template.layout though. I have my doubts about whether we can remove Jackson dependency in the future or not. This ambition does look neither feasible, nor practical in the short-term. That said, from an API perspective, why shall an internal detail like jackson get exposed in the package name? I am considering to place it under o.a.l.log4j.layout.json.template. Any ideas?

No need to put jackson in early like that I think. The package was moved around for modularization in 3.x which makes me think we can still rename things.

👍 I will rename the package to o.a.l.log4j.layout.json.template once the dust settles down. I don't want to introduce such a big change right now and corrupt the conversation history.

LogstashLayout has quite some configuration knobs which renders it inconvenient to explain it in /src/site/asciidoc/manual/layouts.adoc. I have skimmed through the source code with the hope of finding a similar documentation pattern, but failed to do so. Would somebody mind shedding some light onto the convention I should follow here, please?

You can use other formats if that makes it easier, though we may have to get creative.

I am okay with AsciiDoc, my point was, shall I create a dedicated page (e.g., json-template.adoc) just for JsonTemplateLayout, given the rest of the Layouts are briefly summarized in layouts.adoc. Anyway... I will go toward this direction -- better to ask for excuse, rather than waiting permission. 😉

I have some test utility classes that I want to leverage in performance tests, but test classpath of log4j-jackson-json-template module is not accessible by log4j-perf module. What is the work around here?

You can add the tests jar as a dependency to log4j-perf.

Hrm... I didn't know that was possible. I will investigate how I can do that. If you happen to feel like helping, hints are welcome.

I do not intend to implement JsonLayout by leveraging JsonTemplateLayout, at least, not now. I would rather just leave it be and get deprecated eventually. Put another way, is this PR the right place to address this issue?

Can likely be done as a follow up.

👍

@vy
Copy link
Member Author

vy commented Jan 29, 2020

@remkop, please note the revamp in ed1dda4. The results on my machine are as follows:

$ uname -a
Linux tahta 4.15.0-70-generic #79-Ubuntu SMP Tue Nov 12 10:36:11 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

$ grep "model name" /proc/cpuinfo | head -n 1
model name      : Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz

$ cat /proc/cpuinfo | grep processor | wc -l
8

$ java -version
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.2+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.2+9, mixed mode)

$ java -jar log4j-perf/target/benchmarks.jar ".*ThreadLocalVsPool.*" -f 1 -wi 10 -i 20 -tu ns -bm sample -t 4

                            sample  27754662      492.377 ± 6.634  ns/op
NoOp·p0.00                  sample                263.000          ns/op
NoOp·p0.50                  sample                353.000          ns/op
NoOp·p0.90                  sample                610.000          ns/op
NoOp·p0.95                  sample                746.000          ns/op
NoOp·p0.99                  sample               1516.000          ns/op
NoOp·p0.999                 sample              10800.000          ns/op
NoOp·p0.9999                sample              26240.000          ns/op
NoOp·p1.00                  sample            9797632.000          ns/op
                            sample  20835106      352.366 ± 0.354  ns/op
ThreadLocal·p0.00           sample                251.000          ns/op
ThreadLocal·p0.50           sample                324.000          ns/op
ThreadLocal·p0.90           sample                331.000          ns/op
ThreadLocal·p0.95           sample                573.000          ns/op
ThreadLocal·p0.99           sample                785.000          ns/op
ThreadLocal·p0.999          sample               2384.000          ns/op
ThreadLocal·p0.9999         sample              15232.000          ns/op
ThreadLocal·p1.00           sample            1386496.000          ns/op
                            sample  20989233      599.494 ± 0.432  ns/op
RightProvisionedJc·p0.00    sample                265.000          ns/op
RightProvisionedJc·p0.50    sample                523.000          ns/op
RightProvisionedJc·p0.90    sample                841.000          ns/op
RightProvisionedJc·p0.95    sample                942.000          ns/op
RightProvisionedJc·p0.99    sample               1194.000          ns/op
RightProvisionedJc·p0.999   sample               5032.000          ns/op
RightProvisionedJc·p0.9999  sample              18976.000          ns/op
RightProvisionedJc·p1.00    sample            1038336.000          ns/op
                            sample  20839035      624.378 ± 3.719  ns/op
UnderProvisionedJc·p0.00    sample                267.000          ns/op
UnderProvisionedJc·p0.50    sample                547.000          ns/op
UnderProvisionedJc·p0.90    sample                776.000          ns/op
UnderProvisionedJc·p0.95    sample                931.000          ns/op
UnderProvisionedJc·p0.99    sample               1466.000          ns/op
UnderProvisionedJc·p0.999   sample               5928.000          ns/op
UnderProvisionedJc·p0.9999  sample              19008.000          ns/op
UnderProvisionedJc·p1.00    sample            9011200.000          ns/op

Either I am missing something big or G1 in JDK 11 is creating miracles. I would appreciate some insight here.

@remkop
Copy link
Contributor

remkop commented Jan 29, 2020

I’ll take a look but it will take me some time.

@jvz
Copy link
Member

jvz commented Jan 29, 2020

To add a test jar as a dependency, add <type>test-jar</type> to the <dependency> definition. See for example log4j-core-its/pom.xml.

@vy
Copy link
Member Author

vy commented Jan 29, 2020

To add a test jar as a dependency, add <type>test-jar</type> to the <dependency> definition. See for example log4j-core-its/pom.xml.

Yep, indeed there are plenty of examples, found it, thanks.

@remkop
Copy link
Contributor

remkop commented Jan 30, 2020

Showing only the average in ns/operation:

NoOp                        sample  27754662      492.377 ± 6.634  ns/op
ThreadLocal                 sample  20835106      352.366 ± 0.354  ns/op
RightProvisionedJc          sample  20989233      599.494 ± 0.432  ns/op
UnderProvisionedJc          sample  20839035      624.378 ± 3.719  ns/op

What do these numbers mean?

It is the number of nanoseconds it takes on average to serialize a log event into a StringBuilder using the %d %5p [%t] %c{1} %X{transactionId} - %m%n PatternFormat. (Note that the log event has no context data, so the %X{transactionId} formatter is skipped.)

What can we conclude from these numbers?

The NoOp benchmark should be renamed Allocate, because it creates a new StringBuilder(1024) every invocation. Allocation does not seem too expensive here. Perhaps you have a lot of memory and the benchmark finishes before GC kicks in?

The ThreadLocal benchmark shows it is a bit faster to reuse an existing StringBuilder instance cached in a ThreadLocal.

The Jc benchmarks use the org.jctools.queues.MpmcArrayQueue data structure which seems a bit slower than a simple ThreadLocal.

@vy Does that answer your question?

@remkop
Copy link
Contributor

remkop commented Jan 30, 2020

If you wonder why the MpmcArrayQueue benchmark numbers are higher than simple allocation, I am not sure either.

My first guess would be lock contention. With 4 threads that could be significant. I don't believe that MpmcArrayQueue is lock-free (but it has been a while, I could be wrong).

@vy
Copy link
Member Author

vy commented Jan 30, 2020

The NoOp benchmark should be renamed Allocate

Check.

I don't believe that MpmcArrayQueue is lock-free

The definition of what is lock-free is quite a debate on its own. But according to README, MPMC is lock-less (what ever that means) and bounded.

I am just baffled by the fact how come AllocatePool can yield such a miraculous performance that is almost on par with ThreadLocalPool. I have shared this question with @richardstartin and he kindly gave the following feedback:

I think that the G1 write barrier is the cost in the MPMC case (I haven't run the benchmark though) and I would be interested to know the marginal cost of G1 in this case. The most interesting metric is MPMC/G1 vs MPMC/other GC

I will experiment with smaller heap sizes, bigger StringBuilder capacities, and different GCs.

@richardstartin
Copy link
Member

To be clear, that’s just a hunch. I haven’t run the benchmarks let alone profiled them.

@vy
Copy link
Member Author

vy commented Jan 30, 2020

And the following question still stands open: Given TLA results constitute the baseline, what is the pool implied maximum performance degradation we are okay with? With a rough look, MPMC performs 2.5x worse compared to TLAs on 4 cores. I will dig further... Comments are welcome.

@remkop
Copy link
Contributor

remkop commented Jan 30, 2020

Well, what is the trade off? What benefits do we gain in return of this worse performance?

@remkop
Copy link
Contributor

remkop commented Jan 30, 2020

I would be interested to know the marginal cost of G1 in this case. The most interesting metric is MPMC/G1 vs MPMC/other GC

I don’t think we’re measuring the cost of GC anywhere, are we?

@richardstartin
Copy link
Member

I don’t think we’re measuring the cost of GC anywhere, are we?

At this scale, there are so many confounding factors which can explain a difference, and you won't get an explanation without profiling the benchmark. One quite big factor at this scale is the choice of garbage collector, and not because of the time it spends collecting garbage.

I just guessed (in what I thought was a private conversation) that the cost might be explained by the little bit of machine code the JIT compiler inserts into reference assignments to track inter-region references (the write barrier). In my experience, this can really show up in microbenchmarks running G1, especially with some concurrency. My advice was simply to run the benchmark with a different garbage collector and see how much it affects the numbers.

Since I was tagged here, my advice would be to think twice about optimising this, and think about the future. If someone imports this library, they may well never upgrade it, but stack allocation which might be implemented in the JIT compiler would:

  • remove the garbage (benefit vs heap allocation)
  • avoid any contention (benefit vs pooling)
  • avoid an increase in the number of GC roots (benefit vs thread local)

Applications would benefit automatically when they upgrade the JVM, but not if you optimise this now.

@vy
Copy link
Member Author

vy commented Jan 30, 2020

Triggered by @richardstartin's observation, why don't we allow all 3 co-exist in the code base? After all, the call site doesn't care about the caching mechanics. We can let the user decide via a configuration knob ala cache=<none|thread-local|queueClassName,capacity>.

@remkop
Copy link
Contributor

remkop commented Jan 30, 2020

Not sure I agree... What is the trade-off? What do users gain when they select something other than ThreadLocal?

@vy
Copy link
Member Author

vy commented Jan 30, 2020

Not sure I agree... What is the trade-off? What do users gain when they select something other than ThreadLocal?

If you'd recall, we had this discussion in the mailing list in December and January. There the raised concern was TLAs, in particular, in the domain of web applications where there is a proliferation of threads and AbstractStringLayout, used by many String-emitting layouts, is not taking log4j2.enableThreadlocals flag into account, etc.

As described in this ticket, JsonTemplateLayout has a memory footprint which can be summarized with the following rough formula:

threadCount * (
    (stackTraceEnabled ? 1 : 0) * maxByteCount +    // for stacktraces
    maxByteCount +    // for JSON
    epsilon    // for the rest (<100 bytes)
)

While this is a perfectly affordable footprint where the thread count matches the available CPU cores, it is not something desirable in a (web) application container. My suggestion is to leave this decision to user (granted we incorporate sane defaults) and support each strategy. Is this a slick Netty/gRPC app? Stick to TLAs. Is this an app running on Tomcat? Stick to pooling. Is this an embedded app with relatively low load? Stick to allocation.

@remkop
Copy link
Contributor

remkop commented Jan 31, 2020

@vy Understood. That makes sense to me.

@vy
Copy link
Member Author

vy commented Feb 13, 2020

@jvz, I could not get the test-jar thing working. I have pushed my progress: 7084934. I will be so glad if you can spare some time to help me with figuring out the missing piece.

@jvz
Copy link
Member

jvz commented Feb 13, 2020

It's possible that there's a corresponding configuration to enable for the test jar to make it available as a dependency like in log4j-core:test-jar.

@vy
Copy link
Member Author

vy commented Feb 13, 2020

@jvz, I have the cloned maven-jar-plugin configuration in /log4j-layout-json-template/pom.xml and I can see both log4j-layout-json-template-3.0.0-SNAPSHOT.jar and log4j-layout-json-template-3.0.0-SNAPSHOT-tests.jar in /log4j-layout-json-template/target directory. But still Maven falls over its face:

[ERROR] Failed to execute goal on project log4j-perf: Could not resolve dependencies for project org.apache.logging.log4j:log4j-perf:jar:3.0.0-SNAPSHOT: Could not find artifact org.apache.logging.log4j:log4j-layout-json-template:jar:tests:3.0.0-SNAPSHOT

I will really appreciate some more help, please.

@jvz
Copy link
Member

jvz commented Feb 13, 2020

I'm not really sure what else there is to configure. I can't get it working at the moment myself.

@vy
Copy link
Member Author

vy commented Feb 20, 2020

@remkop, in case you are interested in, dae3be0 introduces the abstraction for different caching strategies we have discussed: dummy, thread-local, and queue.

@vy
Copy link
Member Author

vy commented Feb 20, 2020

For the records, I am done. The only missing bit is getting test-jar working for log4j-perf module.

@rgoers
Copy link
Member

rgoers commented Feb 20, 2020 via email

vy added a commit that referenced this pull request Jun 18, 2020
vy added a commit that referenced this pull request Jun 24, 2020
vy added a commit that referenced this pull request Jun 24, 2020
vy added a commit that referenced this pull request Jun 24, 2020
vy added a commit that referenced this pull request Jul 11, 2020
vy added a commit that referenced this pull request Jul 11, 2020
vy added a commit that referenced this pull request Aug 20, 2020
vy added a commit that referenced this pull request Aug 20, 2020
vy added a commit that referenced this pull request Aug 25, 2020
vy added a commit that referenced this pull request Aug 25, 2020
vy added a commit that referenced this pull request Aug 25, 2020
vy added a commit that referenced this pull request Aug 26, 2020
@ramazanpolat
Copy link

Hi, do you have a documentation for JsonTemplateLayout?

@vy
Copy link
Member Author

vy commented Aug 26, 2020

@ramazanpolat, you can access the latest version of the manual here. Due to .vm (Velocity template) suffix, GitHub is not able to render the AsciiDoc properly. You can copy the content and either paste it into asciidocLive or use your own IDE (IDEA, Eclipse, etc.) for the rendered view.

The changes are landed both on master and release-2.x branches. With the upcoming Log4j 2.x release (which I am trying to steer the rest of the Log4j maintainers toward as of this writing) the layout will be available in log4j-layout-template-json artifact ID and the website will be updated accordingly.

@ramazanpolat
Copy link

Thank you @vy
I think you made a great addition to log4j2 with this work.

@ramazanpolat
Copy link

ramazanpolat commented Aug 28, 2020

@vy One quick question: Will JsonTemplateLayout have the ability to jsonify the message object passed to Logger?

e.g: Currently with using JsonLayout, this code:

  logger.info("This is an info message");

produces something like this:

{
  "timeMillis" : 1598613343782,
  "thread" : "main",
  "level" : "INFO",
  "loggerName" : "com.example.Test",
  "message" : "This is an info message",
  "endOfBatch" : false,
  "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
  "contextMap" : { },
  "threadId" : 1,
  "threadPriority" : 5
}

But if we pass an object to the logger like this (considering the object constructor is MyDummyEventBean(String msg, String user, String ip):

  logger.error(new MyDummyEventBean("Something bad happened", "john", "10.1.2.3");

JsonLayout gets appends .toString() result of the MyDummyEventBean and produces this:

{
  "timeMillis" : 1598613343782,
  "thread" : "main",
  "level" : "INFO",
  "loggerName" : "com.example.Test",
  "message" : "{\"message\":\"Something bad happened\",\"userId\":\"john\",\"ip\":\"10.1.2.3\"}",
  "endOfBatch" : false,
  "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
  "contextMap" : { },
  "threadId" : 1,
  "threadPriority" : 5
}

@vy
Copy link
Member Author

vy commented Sep 1, 2020

@ramazanpolat, yes, JsonTemplateLayout can do that. You just need to set stringified to false (the default) as follows:

{
  "$resolver": "message",
  "stringified": false
}

Further, LogstashLayout can also do that. In LogstashLayout, you just need to use ${json:message:json} directive rather than ${json:message}.

HTH.

@ramazanpolat
Copy link

@vy Sorry but LogstashLayout spits my object's as toString() output:

{
  "line" : 123,
  "class" : "tr.gov.sgk.logclient.DAO",
  "message" : "MyLogBean2{message='LogBean Message', userId='LogBean userId', ip='LogBean IP'}",
  "level" : "ERROR",
  "method" : "errorWithExceptionLogstash1",
  "logger" : "logstashLogger"
}

Maybe I'm doing something wrong. My LogstashJsonEventLayoutV1.son file:

{
  "line": "${json:source:lineNumber}",
  "class": "${json:source:className}",
  "message": "${json:message:json}",
  "level": "${json:level}",
  "method": "${json:source:methodName}",
  "logger": "${json:logger:name}"
}

My LogstashLayout in log4j2.xml:

<LogstashLayout eventTemplateUri="classpath:LogstashJsonEventLayoutV1.json"
                prettyPrintEnabled="true"
                locationInfoEnabled="true"
                stackTraceEnabled="true" />

The class I want to be printed as Json(maybe this class needs to implement an interface?):

public class MyLogBean2 {
    private String message;
    private String userId;
    private String ip;

    public MyLogBean2() {    }

    public MyLogBean2(String message, String userId, String ip) {
        this.message = message; this.userId = userId; this.ip = ip;
    }

    public String getMessage() { return message;}

    public void setMessage(String message) {this.message = message;}

    public String getUserId() {return userId;}

    public void setUserId(String userId) {this.userId = userId;}

    public String getIp() {return ip;}

    public void setIp(String ip) {this.ip = ip;}

    @Override
    public String toString() {
        return "MyLogBean2{" +
                "message='" + message + '\'' +
                ", userId='" + userId + '\'' +
                ", ip='" + ip + '\'' +
                '}';
    }
   
}

@vy
Copy link
Member Author

vy commented Sep 2, 2020

@ramazanpolat,

  1. Unless there is a reason to do so, I would avoid custom classes to represent the logging structure. In your case a simple logger.info(new MapMessage(Map.of("message", message, "userId", userId, "ip", ip))) fits the bill.
  2. You should have either used logger.info(new ObjectMessage(customLogBean)) or implement Message interface in the CustomLogBean class.

@diepet
Copy link

diepet commented Sep 26, 2020

Hi, I was aware of this new exciting feature only after open this Jira issue: LOG4J2-2936

Please, could you tell me:

  1. When will be the JsonTemplateLayout released?

  2. Is there someway to resolve the message parameters? As explained in the Jira issue linked above, I would like to isolate and to render the message parameters in a different JSON section.

  3. If one of the additional fields configured under <EventTemplateAdditionalField> resolves an empty value, the relative JSON field will be rendered with an empty string as value or not rendered at all?

Thanks in advance and congrats for your work!

@vy
Copy link
Member Author

vy commented Sep 28, 2020

Let me try to answer your questions @diepet:

  1. When will be the JsonTemplateLayout released?

Next Log4j 2.x release (2.14.0?) will contain the JsonTemplateLayout. @rgoers is busy with rolling the release out.

  1. Is there someway to resolve the message parameters? As explained in the Jira issue linked above, I would like to isolate and to render the message parameters in a different JSON section.

JsonTemplateLayout doesn't provide a built-in resolver for message parameters. (AFAIK, neither PatternLayout does.) That said, I question this approach. (I will comment more about this in the linked Jira issue.)

  1. If one of the additional fields configured under <EventTemplateAdditionalField> resolves an empty value, the relative JSON field will be rendered with an empty string as value or not rendered at all?

Yes, it will be rendered as is. If it is null, "", or "\t\n", etc. whatever, it will be rendered intact. JsonTemplateLayout doesn't employ any blank value elimination.

@diepet
Copy link

diepet commented Sep 28, 2020

Thanks @vy for the feedbacks!

Ok, so let's move the discussions for the point 2 in the Jira issue.

Could be possible, in the future, to plan a new <EventTemplateAdditionalField> boolean attribute for disabling the rendering of these kind of fields in case of empty/null values?

I am looking forward to download the new log4j2 release!

@vy
Copy link
Member Author

vy commented Oct 8, 2020

[Sorry for the late reply, I am pretty much swamped with my day job nowadays.]

@diepet, I have deliberately left out blank value elimination in JsonTemplateLayout (while I was the one who has introduced it in LogstashLayout) mostly due to the following reasons:

  • It incurs an extra runtime cost.
  • Most of the time you don't care. You persist logs in a storage system, e.g., ELK stack, and there null value elimination is provided out of the box by the storage engine in the most efficient way.

If you have a use case which necessitates such a feature, I would like to hear more about it.

@diepet
Copy link

diepet commented Oct 9, 2020

Ehy @vy, better a late reply than a null reply!

Thanks, your points are clear and understandable.

I am looking forward to using the message parameters resolver discussed in Jira!

@vy
Copy link
Member Author

vy commented Oct 9, 2020

Thanks for the feedback @diepet, keep 'em coming!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants