Open SnobbyVirus1973 opened 4 months ago
[FYI: You are not using ConfigurationBuilder
, which always returns a complete configuration. You are modifying the existing configuration using the internal builders of Log4j Core. Using these internal builders is more complex and more susceptible to breaking changes in Log4j Core]
@SnobbyVirus1973,
The map
lookup always returns null
, unless it is evaluated in the context of a log event (i.e. using StrLookup.lookup(LogEvent, String)
is used instead of StrLookup.lookup(String)
).
Currently this only happens:
pattern
attribute of PatternLayout
,JsonTemplateLayout
,pattern
attribute of the Routes
element (used in the Routing
Appender).Therefore lookups like map
, sd
and event
will not work in the additionalFields
configuration property.
Although I believe that additionalFields
should use a log event context instead of the global one to evaluate runtime lookups, I am not certain which is the best way to do it:
LogEvent
parameter to the StrSubstitutor
call. This will allow $${map:...}
to work.PatternConverter
patterns, which will allow both $${map:...}
and %K{...}
to work. The latter provides a better performance.@vy and @garydgregory: what do you think?
@SnobbyVirus1973, first of all, (as @ppkarwasz indicated) you are not using ConfigurationBuilder
, but instead programmatically creating components using their builders. This approach we strongly discourage and you should be using ConfigurationBuilder
instead – we have documented this explicitly in the staging website, which will be available in the next Log4j release.
@SnobbyVirus1973, NoSqlAppender
doesn't support lookups in the additional fields. Hence, what you want is not really possible at this stage "out of the box" – that is, you can make it work (by creating your own NoSqlAppender
, etc.), but you really would not want to do that, and it should ideally fixed by Log4j.
@ppkarwasz, I am in favor of keeping PatternLayout
out of the picture and instead simply allowing lookups in the additional fields of NoSqlAppender
. Plugging in PatternLayout
drags along a myriad of other complications.
@SnobbyVirus1973,
NoSqlAppender
doesn't support lookups in the additional fields. Hence, what you want is not really possible at this stage "out of the box" – that is, you can make it work (by creating your ownNoSqlAppender
, etc.), but you really would not want to do that, and it should ideally fixed by Log4j.
Yes it does support runtime lookups (see Runtime evaluation of attributes I recently revamped). It just does not pass the log event as argument to StrSubstitutor
, so some lookups don't work.
@ppkarwasz, I am in favor of keeping
PatternLayout
out of the picture and instead simply allowing lookups in the additional fields ofNoSqlAppender
. Plugging inPatternLayout
drags along a myriad of other complications.
After auditing the lookup code, I came to the conclusion that StrLookup
might be one of those abstractions we should consider dropping:
PropertiesUtil
. I doubt users employ at the same time ${sys:MY_VALUE}
and ${env:MY_VALUE}
. The namespacing of lookups is often source of confusion. ${MY_VALUE}
would be simpler.PatternConverter
.See my recent thread on dev@logging
.
I agree that PatternParser
is heavier than StrSubstitutor
, but PatternParser
parses an expression only once. StrSubstitutor
parses a value each time it is called.
Yes it does support runtime lookups (see Runtime evaluation of attributes I recently revamped). It just does not pass the log event as argument to
StrSubstitutor
, so some lookups don't work.
Right. Can't we simply receive the LogEvent
in NoSqlDatabaseManager#setAdditionalFields()
and be done with it?
After auditing the lookup code, I came to the conclusion that
StrLookup
might be one of those abstractions we should consider dropping
I don't think this is the right place to discuss this.
I agree that
PatternParser
is heavier thanStrSubstitutor
, butPatternParser
parses an expression only once.StrSubstitutor
parses a value each time it is called.
Hrm... You have a point there. Given this, I am fine with both approaches, I don't have a strong preference.
The reason I code like MongoDb4Provider.newBuilder()
is I found something like on Log4j2 Manual.
In my program, I want to implement the following functions:
log4j2.xml
configuration file in the resource directory, or it can have none. If there is no configuration file, I will generate a default log configuration. If a configuration file is written, I will add the configuration in the configuration file to the default configuration.My current implementation is:
Plugin
is written@Plugin(name = "ConfigurationFactory", category = ConfigurationFactory.CATEGORY)
getSupportedTypes
method of this Plugin
returns [".xml", "*"]
getConfiguration
method of this Plugin
will create an inner class that inherits XmlConfiguration
doConfigure
method. If it is log4j2.xml
in the resource directory of the project, super.doConfigure()
will be called, otherwise it will not be called.LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
// Append MongoDB's Appender
ctx.updateLoggers();
I handed it to Spring for initialization because I wanted to configure the connection address of MongoDB in the application.yml
file.
Is there a better way to implement it? Please tell me☺️
Forgive my poor English, English is not my native language.
@SnobbyVirus1973, @ppkarwasz, what about the following instead?
log4j2-main.xml
in the core projectlog4j2-supplement.xml
in the JAR packageConfigurationFactory
such that
Configuration
instances using log4j2-main.xml
, log4j2-supplement.xml
, and log4j2.xml
files (if they are present):
ConfigurationFactory.getInstance().getConfiguration(null, ConfigurationSource.fromUri("..."))
new CompositeConfiguration(availConfigs)
Note that above programmatic approach is identical to the following JVM argument:
-Dlog4j2.configurationFile=log4j2-main.xml,log4j2-supplement.xml,log4j2.xml
If you can influence the JVM arguments while applications get deployed, you can prefer for this log4j2.configurationFile
approach too.
@SnobbyVirus1973,
What @vy suggests is already implemented in Spring Boot through the logging.log4j2.config.override
Spring Boot property.
Regarding the best approach to log to a database in Spring Boot, I have created the discussion #2807. I think we should continue there.
I am removing the waiting-*
labels, since I believe we have all the information to deal with the initially reported problem: we evaluate $${...}
runtime lookups in the wrong context (global instead of log event) almost everywhere.
Description
I want to use ConfigurationBuilder to config a NoSqlAppender, but I can`t set additionalFields, My code is:
I lookup the source code, and I find NoSqlAppender.Builder class has a private field called "additionalFields", but is has not setter method;
So I use java reflect to set the value, My code is:
It works. But Map Lookup doesn`t work, My do log code is:
I expect ${map:some_key} can be resolved to some_value, but I get ${map:some_key} in MongoDB`s field. I tried ${map:some_key} $${map:some_key} %K{some_key} %map{some_key} %MAP{some_key} and none of them worked;
Configuration
Version: 2.23.1
Operating system: Windows 11
JDK: JDK-17-oracle
Forgive my poor English, English is not my native language.