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

KAFKA-9366: Upgrade log4j to log4j2 #17373

Open
wants to merge 62 commits into
base: trunk
Choose a base branch
from

Conversation

frankvicky
Copy link
Contributor

JIRA: KAFKA-9366

Committer Checklist (excluded from commit message)

  • Verify design and implementation
  • Verify test coverage and CI build status
  • Verify documentation (including upgrade notes)

@github-actions github-actions bot added streams core Kafka Broker tools connect kraft mirror-maker-2 storage Pull requests that target the storage module build Gradle build or GitHub Actions docker Official Docker image clients labels Oct 4, 2024
@frankvicky frankvicky marked this pull request as ready for review October 4, 2024 16:42
@frankvicky
Copy link
Contributor Author

This is the initial version. I'd like to run it on CI first.

@frankvicky frankvicky added the do-not-merge PRs that are only open temporarily and should not be merged label Oct 4, 2024
Copy link
Contributor

@mumrah mumrah left a comment

Choose a reason for hiding this comment

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

Thanks for tackling this @frankvicky.

Is it really necessary to rename the log4j config files? The KIP mentions a system property that allows us to load log4j.properties files https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=158870552#KIP653:Upgradelog4jtolog4j2-Compatibility,Deprecation,andMigrationPlan

I could understand migrating our internal log4j configs for tests and such, but I think we should avoid forcing a change in our production configs.

I also see that this page mentions a log4j to log4j2 bridge https://logging.apache.org/log4j/2.x/migrate-from-log4j1.html. Would that help us at all?

build.gradle Outdated
Comment on lines 2540 to 2544
testRuntimeOnly libs.slf4jLog4j2
testRuntimeOnly libs.junitPlatformLanucher
Copy link
Contributor

Choose a reason for hiding this comment

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

These (and other similar testRuntimeOnly) should be put into the runtimeTestLibs definition

build.gradle Outdated
@@ -2596,6 +2626,7 @@ project(':streams') {
implementation libs.slf4jApi
implementation libs.jacksonAnnotations
implementation libs.jacksonDatabind
implementation libs.bndlib
Copy link
Contributor

Choose a reason for hiding this comment

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

What's this dependency for?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi @mumrah
I add this to fix the warning during build:

/home/frankvicky/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-api/2.24.1/7ebeb12c20606373005af4232cd0ecca72613dda/log4j-api-2.24.1.jar(/org/apache/logging/log4j/Level.class): warning: Cannot find annotation method 'value()' in type 'BaselineIgnore': class file for aQute.bnd.annotation.baseline.BaselineIgnore not found

Copy link
Member

Choose a reason for hiding this comment

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

I'm not convinced we need that dependency. Also it seems to complain about an annotation so at least we should not need it at runtime, so we should not include it in our distribution package. Currently it's included in the artifact generated by releaseTarGz.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fair enough, I will try to solve this one.

Choose a reason for hiding this comment

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

The BND annotations are intentionally in the provided Maven scope of all Log4j artifacts, so that these annotations with CLASS retention do not end up in the runtime classpath. You can do the same and add them as compileOnly in Gradle.

The compiler warnings should disappear once JDK-8342833 is fixed.
Untile then we will remove the outdated ones (see apache/logging-log4j2#3133) in the next Log4j release, which should remove the warning on Level.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the information.
I have already changed its scope to compile time.
PTAL 😄

@@ -22,7 +22,7 @@ fi
base_dir=$(dirname $0)

if [ "x$KAFKA_LOG4J_OPTS" = "x" ]; then
export KAFKA_LOG4J_OPTS="-Dlog4j.configuration=file:$base_dir/../config/log4j.properties"
Copy link
Contributor

Choose a reason for hiding this comment

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

This could break some existing Kafka installations. If users are extracting in place or copying previous config files to a new installation directory, they will be expecting the log4j.properties to still work.

Choose a reason for hiding this comment

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

The switch from the legacy to the new configuration format can be based on the presence of specific files:

if [ -f "$base_dir/../config/log4j.properties" ]; then
    echo DEPRECATED: Using Log4j 1.x configuration file \$KAFKA_HOME/config/log4j.properties >&2
    echo To use a Log4j 2.x configuration, create a \$KAFKA_HOME/config/log4j2.xml file and remove the Log4j 1.x configration. >&2
    echo See https://logging.apache.org/log4j/2.x/migrate-from-log4j1.html#Log4j2ConfigurationFormat for details about Log4j configuration file migration. >&2
    export KAFKA_LOG4J_OPTS="-Dlog4j.configuration=file:$base_dir/../config/log4j.properties"
elif [ -f "$base_dir/../config/log4j2.xml" ]; then
    export KAFKA_LOG4J_OPTS="-Dlog4j2.configurationFile=$base_dir/../config/log4j2.xml"
fi

@frankvicky frankvicky marked this pull request as draft October 6, 2024 03:19
@frankvicky
Copy link
Contributor Author

Hello @mumrah
Thanks for your feedback. Unfortunately, I barely missed the KIP for some reason, but I'll take a look and adjust the PR accordingly. 😺

@frankvicky frankvicky marked this pull request as ready for review October 11, 2024 11:54
revert unnecessary change
@chia7712
Copy link
Contributor

When you merge this PR, please don't omit mentioning my credit. 🙇‍♂️

will roger that :)

Copy link
Contributor

@chia7712 chia7712 left a comment

Choose a reason for hiding this comment

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

@frankvicky thanks for this patch. please check my latest comments to fix e2e

@@ -364,7 +364,7 @@ def start_node(self, node, **kwargs):
if self.external_config_template_func:
node.account.create_file(self.EXTERNAL_CONFIGS_FILE, self.external_config_template_func(node))
node.account.create_file(self.CONFIG_FILE, self.config_template_func(node))
node.account.create_file(self.LOG4J_CONFIG_FILE, self.render('connect_log4j.properties', log_file=self.LOG_FILE))
node.account.create_file(self.LOG4J_CONFIG_FILE, self.render('connect_log4j2.properties', log_file=self.LOG_FILE))
Copy link
Contributor

Choose a reason for hiding this comment

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

in the e2e we could run kafak on different version, so we must check the version before applying the config file.

Copy link
Contributor

Choose a reason for hiding this comment

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

it seems connect e2e does not run different version for workers, so you can just change them to connect_log4j2.yaml. However, please change the -Dlog4j.configuration to -Dlog4j2.configurationFile

@@ -421,7 +421,7 @@ def start_node(self, node, **kwargs):
if self.external_config_template_func:
node.account.create_file(self.EXTERNAL_CONFIGS_FILE, self.external_config_template_func(node))
node.account.create_file(self.CONFIG_FILE, self.config_template_func(node))
node.account.create_file(self.LOG4J_CONFIG_FILE, self.render('connect_log4j.properties', log_file=self.LOG_FILE))
node.account.create_file(self.LOG4J_CONFIG_FILE, self.render('connect_log4j2.properties', log_file=self.LOG_FILE))
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto

@@ -874,7 +874,7 @@ def start_node(self, node, timeout_sec=60, **kwargs):
self.logger.info("kafka.properties:")
self.logger.info(prop_file)
node.account.create_file(KafkaService.CONFIG_FILE, prop_file)
node.account.create_file(self.LOG4J_CONFIG, self.render('log4j.properties', log_dir=KafkaService.OPERATIONAL_LOG_DIR))
node.account.create_file(self.LOG4J_CONFIG, self.render('log4j2.properties', log_dir=KafkaService.OPERATIONAL_LOG_DIR))
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto

Copy link
Contributor

Choose a reason for hiding this comment

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

Please noted that the previous version should use -Dlog4j.configuration and trunk version should use -Dlog4j2.configurationFile

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It seems that tons of code needs to apply this change.
I will prepare it asap.

@mimaison
Copy link
Member

When you merge this PR, please don't omit mentioning my credit. 🙇‍♂️

Yes you totally deserve being marked as a co-author. Thanks!

@mimaison
Copy link
Member

mimaison commented Nov 20, 2024

I'm having issues with the latest code (f3a68e1).

$ bin/kafka-server-start.sh config/kraft/reconfig-server.properties
[0.002s][error][logging] Error opening log file '/Users/mickael/github/kafka/core/build/distributions/kafka_2.13-4.0.0-SNAPSHOT/bin/../logs/kafkaServer-gc.log': No such file or directory
[0.002s][error][logging] Initialization of output 'file=/Users/mickael/github/kafka/core/build/distributions/kafka_2.13-4.0.0-SNAPSHOT/bin/../logs/kafkaServer-gc.log' using options 'filecount=10,filesize=100M' failed.
Invalid -Xlog option '-Xlog:gc*:file=/Users/mickael/github/kafka/core/build/distributions/kafka_2.13-4.0.0-SNAPSHOT/bin/../logs/kafkaServer-gc.log:time,tags:filecount=10,filesize=100M', see error log for details.
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

Running trunk the logs folder is automatically created. If I create the folder manually, then it seems to log at WARN level by default and I only get a single log line printed while my broker is running:

$ bin/kafka-server-start.sh config/kraft/reconfig-server.properties
[2024-11-20 14:33:39,425] WARN [QuorumController id=1] Performing controller activation. The metadata log appears to be empty. Appending 2 bootstrap record(s) in metadata transaction at metadata.version 4.0-IV0 from bootstrap source 'the binary bootstrap metadata file: /tmp/kraft-combined-logs/bootstrap.checkpoint'. Setting the ZK migration state to NONE since this is a de-novo KRaft cluster. (org.apache.kafka.controller.QuorumController)

Copy link
Contributor

@chia7712 chia7712 left a comment

Choose a reason for hiding this comment

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

@frankvicky please double check the yaml format. I leave some comments about the incorrect format.

immediateFlush: true
PatternLayout:
pattern: "${logPattern}"
TimeBasedTriggeringPolicy:
Copy link
Contributor

Choose a reason for hiding this comment

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

        Policies:
          TimeBasedTriggeringPolicy:
            modulate: true
            interval: 1


RollingFile:
- name: FILE
fileName: {{ log_file }}
Copy link
Contributor

Choose a reason for hiding this comment

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

please add filePattern

Comment on lines 41 to 44
Polices:
TimeBasedTriggeringPolicy:
modulate: true
interval: 1

Choose a reason for hiding this comment

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

Since there is only one triggering policy, there is no need to wrap it in a Policies wrapper.

BTW: there is a typo in the plugin name: it should be Policies, instead of Polices.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for information 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
build Gradle build or GitHub Actions ci-approved clients connect consumer core Kafka Broker docker Official Docker image kraft mirror-maker-2 storage Pull requests that target the storage module streams tools
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants