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

Bug Fix: Script Resolution fix #3394

Open
wants to merge 4 commits into
base: 2.x
Choose a base branch
from
Open

Bug Fix: Script Resolution fix #3394

wants to merge 4 commits into from

Conversation

Suvrat1629
Copy link

#3336
Refactored the ScriptFilter class to enhance script resolution and error handling. This update ensures that ScriptRef scripts are resolved properly using the ScriptManager. Improved logging for scenarios where scripts fail to execute or resolve.

Checklist

  • .Base your changes on 2.xbranch if you are targeting Log4j 2; usemain` otherwise
  • ./mvnw verify succeeds (if it fails due to code formatting issues reported by Spotless, simply run ./mvnw spotless:apply and retry)
  • Non-trivial changes contain an entry file in the src/changelog/.2.x.x directory
  • Tests for the changes are provided
  • Commits are signed (optional, but highly recommended)

Copy link
Contributor

@ppkarwasz ppkarwasz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Suvrat1629,

Thank you for the PR.

Unfortunately it does not solve #3336, since we have a lot of elements that use scripting (ScriptFilter was just an example):

To fix the resolution of scripts in all of these, I think we should take a different approach: we could alter the order in which the children of a <Configuration> element are processed. Right now we process them in order of appearance, with a single exception: the <Properties> element must be processed first to allow the values of the remaining elements to be properly interpolated:

for (final Node node : rootNode.getChildren()) {
if ("Properties".equalsIgnoreCase(node.getName())) {
hasProperties = true;
createConfiguration(node, null);
if (node.getObject() != null) {
final StrLookup lookup = node.getObject();
runtimeStrSubstitutor.setVariableResolver(lookup);
configurationStrSubstitutor.setVariableResolver(lookup);
}
break;
}
}
if (!hasProperties) {
final Map<String, String> map = this.getComponent(CONTEXT_PROPERTIES);
final StrLookup lookup = map == null ? null : new PropertiesLookup(map);
final Interpolator interpolator = new Interpolator(lookup, pluginPackages);
interpolator.setConfiguration(this);
interpolator.setLoggerContext(loggerContext.get());
runtimeStrSubstitutor.setVariableResolver(interpolator);
configurationStrSubstitutor.setVariableResolver(interpolator);
}

We should probably process the <Scripts> element just after <Properties>.

Note: the ScriptArbiter should probably be processed differently. Arbiters are special plugins that modify the structure of the configuration file before it is processed. Therefore the ScriptArbiter should probably just signal an ERROR (or throw), if it contains a ScriptRef. At the stage, when the arbiter is used, the Scripts element is not yet processed.

Comment on lines +21 to +27
<PatternLayout pattern="[%-5level] %c{1.} %msg%n"/>[suvrat@suvrat logging-log4j2]$ git push
Username for 'https://github.com': suvrat1629
Password for 'https://[email protected]':
remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Suvrat1629/logging-log4j2.git/'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did this end up here? 😉

[In the mean time I am checking if I didn't leave any :x or :wq in the code 😛 ]

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well i just shifted to arch and was trying to push to code from intellij and this log ended up here after i pushed the code and i realised it just after :D

Comment on lines +61 to +76
public void start() {
super.start();
if (script instanceof ScriptRef) {
AbstractScript resolvedScript = configuration.getScriptManager().getScript(script.getName());
if (resolvedScript == null) {
LOGGER.error("No script with name {} has been declared.", script.getName());
// Optionally: mark the filter as unusable or handle failure gracefully
return;
}
this.script = resolvedScript; // Update to resolved script
} else {
if (!configuration.getScriptManager().addScript(script)) {
LOGGER.error("Failed to add script {} to the ScriptManager.", script.getName());
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can not use the same code as in the createFilter factory method: if the script variable is null it will create problems further down in the call hierarchy.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so should i just revert back the changes i made to the ScriptFilter.java file and and make changes to the processRootNode method in the AbstractConfiguration and update the logic?
The logic would be:
1.Process first, as it currently does.
2.Process script-related components (ScriptPatternSelector, Routes, ScriptFilter, etc.) after to ensure their dependencies are resolved.
3.Process all remaining components afterward.

is this how i should keep my approach?

Also thanks for your patience and guidance :)

@ppkarwasz
Copy link
Contributor

so should i just revert back the changes i made to the ScriptFilter.java file and and make changes to the processRootNode method in the AbstractConfiguration and update the logic?

The AbstractConfiguration.doConfigure() method seems to be a better choice.

The logic would be:

  1. Process first, as it currently does.
  2. Process script-related components (ScriptPatternSelector, Routes, ScriptFilter, etc.) after to ensure their dependencies are resolved.
  3. Process all remaining components afterward.

It is hard to identify the script-related components. It is easier to make sure that the Scripts container is processed at the beginning, so that the scripts are already registered, when ScriptFilter and company are instantiated. This means:

  1. Process the nodes of type Arbiter to modify the configuration tree. This is what doConfigure() already does.
  2. Process the "Properties" plugin first, as the current code does. If the "Properties" plugin is not present, the current code uses something else to initialize the interpolator.
  3. Process the "Scripts" plugin next, to register all the scripts.
  4. Process the remaining components (skipping "Properties" and "Scripts").

is this how i should keep my approach?

It is one of the possible approaches, probably the easiest to implement.

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.

2 participants