Skip to content

DefaultMergeStrategy - problem merging filters #3173

@JWT007

Description

@JWT007

DefaultMergeStrategy (Log4j 2.24.1)

In DefaultMergeStrategy#updateFilterNode I think there is a problem when merging two configurations with filters and the target does not yet contain a CompositeFilter. (in the code below this is the elsecase).

private void updateFilterNode(
        final Node target,
        final Node targetChildNode,
        final Node sourceChildNode,
        final PluginManager pluginManager) {
    if (CompositeFilter.class.isAssignableFrom(targetChildNode.getType().getPluginClass())) {
        final Node node = new Node(targetChildNode, sourceChildNode.getName(), sourceChildNode.getType());
        node.getChildren().addAll(sourceChildNode.getChildren());
        node.getAttributes().putAll(sourceChildNode.getAttributes());
        targetChildNode.getChildren().add(node);
    } else {
        final PluginType pluginType = pluginManager.getPluginType(FILTERS);
        final Node filtersNode = new Node(targetChildNode, FILTERS, pluginType);
        final Node node = new Node(filtersNode, sourceChildNode.getName(), sourceChildNode.getType());
        node.getAttributes().putAll(sourceChildNode.getAttributes());
        final List<Node> children = filtersNode.getChildren();
        children.add(targetChildNode);
        children.add(node);
        final List<Node> nodes = target.getChildren();
        nodes.remove(targetChildNode);
        nodes.add(filtersNode);
    }
}

If I am not mistaken, there is a step missing to add the children of the 'sourceChildNode' to the new node.

I think it should be (see line commented with "<==== ADDED").

else {
        final PluginType pluginType = pluginManager.getPluginType(FILTERS);
        final Node filtersNode = new Node(targetChildNode, FILTERS, pluginType);
        final Node node = new Node(filtersNode, sourceChildNode.getName(), sourceChildNode.getType());
        node.getChildren().addAll(sourceChildeNode.getChildren());   // <==== ADDED
        node.getAttributes().putAll(sourceChildNode.getAttributes());
        final List<Node> children = filtersNode.getChildren();
        children.add(targetChildNode);
        children.add(node);
        final List<Node> nodes = target.getChildren();
        nodes.remove(targetChildNode);
        nodes.add(filtersNode);
    }
}

For example if merging a secondary configuration (source) containing the following filter to a base configuration (target) when the target contains a filter (but not a CompositeFilter):

<Configuration>
  <DynamicThresholdFilter key="loginId" defaultThreshold="ERROR"> 
    <KeyValuePair key="alice" value="DEBUG"/> 
    <KeyValuePair key="bob" value="INFO"/> 
  </DynamicThresholdFilter>
</Configuration>

I believe all the KeyValuePair children would be dropped during merge with the current code.

In addition, the current code does not account for the possibilty of the sourceChildNode being a CompositeFilter which would result in nested composite-filters. (this applies to both the ifand elsebranches of the original code.

<Configuration>
  <CompositeFilter>
     <Filter1/>
     <Filter2/>
  </CompositeFilter>
</Configuration>
<Configuration>
  <CompositeFilter>
     <Filter3/>
     <Filter4/>
  </CompositeFilter>
</Configuration>

Would result in:

<Configuration>
  <CompositeFilter>
     <Filter1/>
     <Filter2/>
     <CompositeFilter>
       <Filter3/>
       <Filter4/>
    </CompositeFilter>
  </CompositeFilter>
</Configuration>

But should probably be:

<Configuration>
  <CompositeFilter>
     <Filter1/>
     <Filter2/>
     <Filter3/>
     <Filter4/>
  </CompositeFilter>
</Configuration>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    To triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions