-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Load pre-loaded lookups via SPI, rather than hard-code in Interpolator. #396
Conversation
test custom lookup fix support custom lookup
What's wrong with the CI? The change should have nothing to do with the error. :) |
No worries about the Travis check. The GitHub Actions checks are the important ones. We need to disable our old Travis checks. |
The only concern I have with this is the overhead of ServiceLoader during startup. I recently had to make ServiceLoader run asynchronously during startup while loading Custom ThreadContextDataProviders. This will likely cause the same problem. We should make that more generic so that components such as them can register their service for asynchronous initialization. But that would be done in a different PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might make more sense being named something like ServiceLookup as it specifically queries service providers. Custom sounds too generic.
@jvz I dislike ServiceLookup as it is describing its implementation method, not its purpose, which is to allow a way for users to hook into a Lookup that is configured to run before any standard plugins have been processed. Perhaps that is an indication that the mechanism provided here is incorrect. Perhaps the service loader should be looking for Lookup Plugins that are also declared as services. We could replace the way all these lookups are loaded if we do that. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my previous comment. The more I think about this the more it seems all the pre-loaded Lookups should be loaded via ServiceLoader. So custom Lookups that want to be included in this list would just register themselves as services.
@rgoers Agree! This PR is intended to do that as you proposed. Hope this could be supported ASAP :) . Have a nice day. |
@rgoers Do you mean all the pre-loaded Lookups should be loaded via ServiceLoader? I am glad to contribute to this part if you do not mind. :) |
Yes, that is exactly what I mean. Feel free to modify this PR to do that. In essence, StrLookup would become the service interface and every plugin to be pre-loaded would be listed in the services file instead of hard coded in Interpolator. |
@rgoers ok. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes are reviewed by Tommy.Tesla.
// JNDI check | ||
try { | ||
// [LOG4J2-703] We might be on Android | ||
Loader.newCheckedInstanceOf("org.apache.logging.log4j.core.lookup.JndiLookup", StrLookup.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is trying to load itself here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hah, my fault. Your r right. How about just removing them? It is not necessary in terms of SPI mode.
|
||
try { | ||
// docker check. | ||
Loader.newCheckedInstanceOf("org.apache.logging.log4j.docker.DockerLookup", StrLookup.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These checks are attempting to load the class they're in. They won't load properly when SystemLoader.load()
tries to load the class itself due to the static references to optional classpath code. This check you've added is only useful for code outside this exact file. The same goes for the other classes you've added these to.
} | ||
|
||
KubernetesLookup(Pod pod, Namespace namespace, URL masterUrl) { | ||
this.pod = pod; | ||
this.namespace = namespace; | ||
this.masterUrl = masterUrl; | ||
|
||
try { | ||
Loader.newCheckedInstanceOf("org.apache.logging.log4j.kubernetes.KubernetesLookup", StrLookup.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
@@ -40,9 +40,21 @@ | |||
private static final Pattern DEFAULT_PATTERN = Pattern.compile(DEFAULT + PATTERN); | |||
|
|||
public SpringLookup() { | |||
try { | |||
//Spring check. | |||
Loader.newCheckedInstanceOf("org.apache.logging.log4j.spring.cloud.config.client.SpringLookup", StrLookup.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
super(); | ||
if (Constants.IS_WEB_APP) { | ||
try { | ||
Loader.newCheckedInstanceOf("org.apache.logging.log4j.web.WebLookup", StrLookup.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
// JMX check | ||
try { | ||
// We might be on Android | ||
Loader.newCheckedInstanceOf("org.apache.logging.log4j.core.lookup.JmxRuntimeInputArgumentsLookup", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
/* | ||
* Comparator for ordering pure StrLookup instances by priority. | ||
*/ | ||
new Comparator<AbstractPureLookup>(){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should use a lambda.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rogar that.
import java.util.List; | ||
import java.util.Locale; | ||
import java.util.Map; | ||
import java.util.*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No star imports please!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rogar that. Get your point! It is an auto action did by IDEA, I've turn up the count. Thanks.
import org.apache.logging.log4j.core.lookup.MapLookup; | ||
import org.apache.logging.log4j.core.lookup.StrLookup; | ||
import org.apache.logging.log4j.core.lookup.StrSubstitutor; | ||
import org.apache.logging.log4j.core.lookup.*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No star imports please!
* | ||
* Use to resolve those variables without prefix. | ||
* | ||
* @author tommy.tesla |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't use the @author
tag in javadoc.
* @author tommy.testla | ||
* @since 3.0.0 | ||
*/ | ||
public interface BuiltInLookupCategory { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two things about this:
- We do not use interfaces for holding string constants; we use a
public final class
withpublic static final
constants and a private constructor. Using interfaces this way is an anti-pattern. - Due to how you've refactored these to be dynamically looked up via services, these constants are only referenced in their respective classes now. There's no reason to factor out the constants at this point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, got it.
These changes are not what I expected. All the Lookups should remain plugins. You should have only had to modify Interpolator to load the required lookups via ServiceLoader and then added the Lookups you wanted to load to the file used by ServiceLoader. The Lookups would be loaded again as normal as Plugins during configuration. |
@rgoers I propably misunderstood your opinion: In essence, StrLookup would become the service interface and every plugin to be pre-loaded would be listed in the services file instead of hard coded in Interpolator. I guess following is what you want:
Is it right ? |
d3be33b
to
b033210
Compare
@rgoers Hi, rgoers. After debuging and reading the log4j2 codes, I realize that the public Interpolator(final Map<String, String> properties) is called several times during factory creation stage. Is that reasonable to create so many StrLookup instances with the same type? |
fd6a377
to
0e8b8a0
Compare
Well, the Interpolator constructor that has the hard-coded list of lookups is initializing the lookups that could be using while constructing the configuration. The other lookups would be used at runtime. There is no reason that I can think of that all the Lookups couldn't be initialized once via ServiceLoader except that it would break compatibility with users who have created their own Lookups as plugins. We could possibly load the serviceloader Lookups once and then add the ones defined as plugins later. |
This was closed automatically by Github because we renamed the |
issue link: Provide a way to add customized StrLookUps in Interpolator initialization.