未验证 提交 06bec028 编写于 作者: Z zifeihan 提交者: GitHub

Fix application start duration log "Failed to load class...

Fix application start duration log "Failed to load class org.slf4j.impl.StaticLoggerBinder." (#5678)

* Fix application start duration log "Failed to load class "org.slf4j.impl.StaticLoggerBinder"." when use kafka reporter. because kafka reporter use slf4j-api, but no implementor for slf4j.

* Polishing.

* Adapter slf4j Logger of agent used to skywalking agent Logger.

* Make the comments more accurate.
Co-authored-by: wu-sheng's avatar吴晟 Wu Sheng <wu.sheng@foxmail.com>
上级 98968122
......@@ -48,7 +48,10 @@
<shade.io.opencensus.target>${shade.package}.${shade.io.opencensus.source}</shade.io.opencensus.target>
<shade.io.perfmark.source>io.perfmark</shade.io.perfmark.source>
<shade.io.perfmark.target>${shade.package}.${shade.io.perfmark.source}</shade.io.perfmark.target>
<shade.org.slf4j.source>org.slf4j</shade.org.slf4j.source>
<shade.org.slf4j.target>${shade.package}.${shade.org.slf4j.source}</shade.org.slf4j.target>
<ststem-rules.version>1.18.0</ststem-rules.version>
<slf4j.version>1.7.25</slf4j.version>
</properties>
<dependencies>
......@@ -113,6 +116,11 @@
<artifactId>jmh-generator-annprocess</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
......@@ -179,6 +187,10 @@
<pattern>${shade.io.perfmark.source}</pattern>
<shadedPattern>${shade.io.perfmark.target}</shadedPattern>
</relocation>
<relocation>
<pattern>${shade.org.slf4j.source}</pattern>
<shadedPattern>${shade.org.slf4j.target}</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
......
......@@ -27,6 +27,8 @@ public interface ILog {
void info(String format, Object... arguments);
void info(Throwable t, String format, Object... arguments);
void warn(String format, Object... arguments);
void warn(Throwable e, String format, Object... arguments);
......@@ -43,6 +45,8 @@ public interface ILog {
boolean isErrorEnable();
boolean isTraceEnabled();
void debug(String format);
void debug(String format, Object... arguments);
......@@ -50,4 +54,10 @@ public interface ILog {
void debug(Throwable t, String format, Object... arguments);
void error(String format);
void trace(String format);
void trace(String format, Object... arguments);
void trace(Throwable t, String format, Object... arguments);
}
......@@ -35,6 +35,11 @@ public enum NoopLogger implements ILog {
}
@Override
public void info(final Throwable t, final String format, final Object... arguments) {
}
@Override
public void warn(String format, Object... arguments) {
......@@ -65,6 +70,11 @@ public enum NoopLogger implements ILog {
return false;
}
@Override
public boolean isTraceEnabled() {
return false;
}
@Override
public void debug(String format) {
......@@ -85,6 +95,21 @@ public enum NoopLogger implements ILog {
}
@Override
public void trace(final String format) {
}
@Override
public void trace(final String format, final Object... arguments) {
}
@Override
public void trace(final Throwable t, final String format, final Object... arguments) {
}
@Override
public void error(Throwable e, String format, Object... arguments) {
......
......@@ -73,6 +73,13 @@ public abstract class AbstractLogger implements ILog {
}
}
@Override
public void info(final Throwable throwable, final String message, final Object... objects) {
if (this.isInfoEnable()) {
this.logger(LogLevel.INFO, replaceParam(message, objects), throwable);
}
}
@Override
public void warn(String message, Object... objects) {
if (this.isWarnEnable()) {
......@@ -129,22 +136,52 @@ public abstract class AbstractLogger implements ILog {
}
}
@Override
public boolean isDebugEnable() {
return LogLevel.DEBUG.compareTo(Config.Logging.LEVEL) >= 0;
}
@Override
public boolean isInfoEnable() {
return LogLevel.INFO.compareTo(Config.Logging.LEVEL) >= 0;
}
@Override
public boolean isWarnEnable() {
return LogLevel.WARN.compareTo(Config.Logging.LEVEL) >= 0;
}
@Override
public boolean isErrorEnable() {
return LogLevel.ERROR.compareTo(Config.Logging.LEVEL) >= 0;
}
@Override
public boolean isTraceEnabled() {
return LogLevel.TRACE.compareTo(Config.Logging.LEVEL) >= 0;
}
@Override
public void trace(final String message) {
if (this.isTraceEnabled()) {
this.logger(LogLevel.TRACE, message, null);
}
}
@Override
public void trace(final String message, final Object... objects) {
if (this.isTraceEnabled()) {
this.logger(LogLevel.TRACE, replaceParam(message, objects), null);
}
}
@Override
public void trace(final Throwable throwable, final String message, final Object... objects) {
if (this.isTraceEnabled()) {
this.logger(LogLevel.TRACE, replaceParam(message, objects), throwable);
}
}
protected String replaceParam(String message, Object... parameters) {
if (message == null) {
return message;
......
......@@ -19,5 +19,5 @@
package org.apache.skywalking.apm.agent.core.logging.core;
public enum LogLevel {
DEBUG, INFO, WARN, ERROR, OFF
TRACE, DEBUG, INFO, WARN, ERROR, OFF
}
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.skywalking.apm.dependencies.org.slf4j.impl;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.skywalking.apm.agent.core.logging.api.ILog;
import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
/**
* implement {@link ILoggerFactory},factory adapter logger for {@link Logger}
*/
public class InternalLoggerFactory implements ILoggerFactory {
private ConcurrentMap<String, Slf4jLoggerAdapter> loggerCache = new ConcurrentHashMap();
@Override
public Logger getLogger(final String name) {
final Slf4jLoggerAdapter hitPLogger = loggerCache.get(name);
if (hitPLogger != null) {
return hitPLogger;
}
final ILog logger = LogManager.getLogger(name);
final Slf4jLoggerAdapter slf4jLoggerAdapter = new Slf4jLoggerAdapter(logger, name);
final Slf4jLoggerAdapter before = loggerCache.putIfAbsent(name, slf4jLoggerAdapter);
if (before != null) {
return before;
}
return slf4jLoggerAdapter;
}
}
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.skywalking.apm.dependencies.org.slf4j.impl;
import org.apache.skywalking.apm.agent.core.logging.api.ILog;
import org.slf4j.Logger;
import org.slf4j.Marker;
/**
* simple adapter {@link Logger}
*/
public class Slf4jLoggerAdapter implements Logger {
private final ILog log;
private final String name;
public Slf4jLoggerAdapter(ILog log, String name) {
this.log = log;
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public boolean isTraceEnabled() {
return log.isTraceEnabled();
}
@Override
public void trace(final String msg) {
log.trace(msg);
}
@Override
public void trace(final String format, final Object arg) {
log.trace(format, arg);
}
@Override
public void trace(final String format, final Object arg1, final Object arg2) {
log.trace(format, arg1, arg2);
}
@Override
public void trace(final String format, final Object... arguments) {
log.trace(format, arguments);
}
@Override
public void trace(final String msg, final Throwable t) {
log.trace(t, msg);
}
@Override
public boolean isTraceEnabled(final Marker marker) {
return log.isTraceEnabled();
}
@Override
public void trace(final Marker marker, final String msg) {
log.trace(msg);
}
@Override
public void trace(final Marker marker, final String format, final Object arg) {
log.trace(format, arg);
}
@Override
public void trace(final Marker marker, final String format, final Object arg1, final Object arg2) {
log.trace(format, arg1, arg2);
}
@Override
public void trace(final Marker marker, final String format, final Object... argArray) {
log.trace(format, argArray);
}
@Override
public void trace(final Marker marker, final String msg, final Throwable t) {
log.trace(t, msg);
}
@Override
public boolean isDebugEnabled() {
return log.isDebugEnable();
}
@Override
public void debug(final String msg) {
log.debug(msg);
}
@Override
public void debug(final String format, final Object arg) {
log.debug(format, arg);
}
@Override
public void debug(final String format, final Object arg1, final Object arg2) {
log.debug(format, arg1, arg2);
}
@Override
public void debug(final String format, final Object... arguments) {
log.debug(format, arguments);
}
@Override
public void debug(final String msg, final Throwable t) {
log.debug(t, msg);
}
@Override
public boolean isDebugEnabled(final Marker marker) {
return log.isDebugEnable();
}
@Override
public void debug(final Marker marker, final String msg) {
log.debug(msg);
}
@Override
public void debug(final Marker marker, final String format, final Object arg) {
log.debug(format, arg);
}
@Override
public void debug(final Marker marker, final String format, final Object arg1, final Object arg2) {
log.debug(format, arg1, arg2);
}
@Override
public void debug(final Marker marker, final String format, final Object... arguments) {
log.debug(format, arguments);
}
@Override
public void debug(final Marker marker, final String msg, final Throwable t) {
log.debug(t, msg);
}
@Override
public boolean isInfoEnabled() {
return log.isInfoEnable();
}
@Override
public void info(final String msg) {
log.info(msg);
}
@Override
public void info(final String format, final Object arg) {
log.info(format, arg);
}
@Override
public void info(final String format, final Object arg1, final Object arg2) {
log.info(format, arg1, arg2);
}
@Override
public void info(final String format, final Object... arguments) {
log.info(format, arguments);
}
@Override
public void info(final String msg, final Throwable t) {
log.info(t, msg);
}
@Override
public boolean isInfoEnabled(final Marker marker) {
return log.isInfoEnable();
}
@Override
public void info(final Marker marker, final String msg) {
log.info(msg);
}
@Override
public void info(final Marker marker, final String format, final Object arg) {
log.info(format, arg);
}
@Override
public void info(final Marker marker, final String format, final Object arg1, final Object arg2) {
log.info(format, arg1, arg2);
}
@Override
public void info(final Marker marker, final String format, final Object... arguments) {
log.info(format, arguments);
}
@Override
public void info(final Marker marker, final String msg, final Throwable t) {
log.info(t, msg);
}
@Override
public boolean isWarnEnabled() {
return log.isWarnEnable();
}
@Override
public void warn(final String msg) {
log.warn(msg);
}
@Override
public void warn(final String format, final Object arg) {
log.warn(format, arg);
}
@Override
public void warn(final String format, final Object... arguments) {
log.warn(format, arguments);
}
@Override
public void warn(final String format, final Object arg1, final Object arg2) {
log.warn(format, arg1, arg2);
}
@Override
public void warn(final String msg, final Throwable t) {
log.warn(t, msg);
}
@Override
public boolean isWarnEnabled(final Marker marker) {
return log.isWarnEnable();
}
@Override
public void warn(final Marker marker, final String msg) {
log.warn(msg);
}
@Override
public void warn(final Marker marker, final String format, final Object arg) {
log.warn(format, arg);
}
@Override
public void warn(final Marker marker, final String format, final Object arg1, final Object arg2) {
log.warn(format, arg1, arg2);
}
@Override
public void warn(final Marker marker, final String format, final Object... arguments) {
log.warn(format, arguments);
}
@Override
public void warn(final Marker marker, final String msg, final Throwable t) {
log.warn(msg, t);
}
@Override
public boolean isErrorEnabled() {
return log.isErrorEnable();
}
@Override
public void error(final String msg) {
log.error(msg);
}
@Override
public void error(final String format, final Object arg) {
log.error(null, format, arg);
}
@Override
public void error(final String format, final Object arg1, final Object arg2) {
log.error(null, format, arg1, arg2);
}
@Override
public void error(final String format, final Object... arguments) {
log.error(null, format, arguments);
}
@Override
public void error(final String msg, final Throwable t) {
log.error(msg, t);
}
@Override
public boolean isErrorEnabled(final Marker marker) {
return log.isErrorEnable();
}
@Override
public void error(final Marker marker, final String msg) {
log.error(msg);
}
@Override
public void error(final Marker marker, final String format, final Object arg) {
log.error(null, format, arg);
}
@Override
public void error(final Marker marker, final String format, final Object arg1, final Object arg2) {
log.error(null, format, arg1, arg2);
}
@Override
public void error(final Marker marker, final String format, final Object... arguments) {
log.error(null, format, arguments);
}
@Override
public void error(final Marker marker, final String msg, final Throwable t) {
log.error(t, msg);
}
}
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.skywalking.apm.dependencies.org.slf4j.impl;
import org.slf4j.ILoggerFactory;
import org.slf4j.spi.LoggerFactoryBinder;
/**
* The slf4j-api would try to load org.slf4j.impl.StaticLoggerBinder internal. In the agent core, we add our own implementation
* for bridging to SkyWalking internal log component.
* Therefore, logs of netty/grpc/kafka(agent shaded components) would output through the SkyWalking's log.
*
* Don't move this class to any other package, its package must be as same as the shaded org.apache.skywalking.apm.dependencies.org.slf4j.impl
*/
public final class StaticLoggerBinder implements LoggerFactoryBinder {
private static final String LOGGER_FACTORY_CLASS_STR = InternalLoggerFactory.class.getName();
/**
* The unique instance of this class.
*/
private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
/**
* The ILoggerFactory instance returned by the {@link #getLoggerFactory} method should always be the same object
*/
private final ILoggerFactory loggerFactory;
/**
* Private constructor to prevent instantiation
*/
private StaticLoggerBinder() {
loggerFactory = new InternalLoggerFactory();
}
/**
* Returns the singleton of this class.
* Dot't delete this method, this method will called by {@link org.slf4j.LoggerFactory#bind()}
*
* @return the StaticLoggerBinder singleton
*/
public static StaticLoggerBinder getSingleton() {
return SINGLETON;
}
/**
* Returns the factory.
*
* @return the factor.
*/
@Override
public ILoggerFactory getLoggerFactory() {
return loggerFactory;
}
/**
* Returns the class name.
*
* @return the class name;
*/
@Override
public String getLoggerFactoryClassStr() {
return LOGGER_FACTORY_CLASS_STR;
}
}
......@@ -85,6 +85,7 @@
<exclude>org.checkerframework:checker-compat-qual</exclude>
<exclude>org.codehaus.mojo:animal-sniffer-annotations</exclude>
<exclude>io.perfmark:*</exclude>
<exclude>org.slf4j:*</exclude>
</excludes>
</artifactSet>
<relocations>
......
......@@ -14,7 +14,6 @@ These are known and common FAQs. We welcome you to contribute yours.
* [Why metrics indexes(ElasticSearch) in Hour and Day precisions stop update after upgrade to 7.x?](Hour-Day-Metrics-Stopping.md)
* [6.x version upgrade](v6-version-upgrade.md)
* [Why only traces in UI?](Why-have-traces-no-others.md)
* [Too many GRPC logs in the console](Too-many-gRPC-logs.md)
* [The trace doesn't continue in kafka consumer side](kafka-plugin.md)
* [Agent or collector version upgrade, 3.x -> 5.0.0-alpha](v3-version-upgrade.md)
* [EnhanceRequireObjectCache class cast exception](EnhanceRequireObjectCache-Cast-Exception.md)
......
### Problem
Too many GRPC log in the console
### Reason
Skywalking uses the GRPC framework to send data, and the GRPC framework reads log configuration files for log output.
### Resolve
Add filter to `org.apache.skywalking.apm.dependencies` package in log configuration file
......@@ -92,7 +92,7 @@ property key | Description | Default |
`collector.backend_service`|Collector SkyWalking trace receiver service addresses.|`127.0.0.1:11800`|
`collector.grpc_upstream_timeout`|How long grpc client will timeout in sending data to upstream. Unit is second.|`30` seconds|
`collector.get_profile_task_interval`|Sniffer get profile task list interval.|`20`|
`logging.level`|The log level. Default is debug.|`DEBUG`|
`logging.level`|Log level: TRACE, DEBUG, INFO, WARN, ERROR, OFF. Default is info.|`INFO`|
`logging.file_name`|Log file name.|`skywalking-api.log`|
`logging.output`| Log output. Default is FILE. Use CONSOLE means output to stdout. |`FILE`|
`logging.dir`|Log files directory. Default is blank string, means, use "{theSkywalkingAgentJarDir}/logs " to output logs. {theSkywalkingAgentJarDir} is the directory where the skywalking agent jar file is located |`""`|
......@@ -145,7 +145,7 @@ property key | Description | Default |
`plugin.dubbo.consumer_arguments_length_threshold`| When `plugin.dubbo.collect_consumer_arguments` is `true`, Arguments of length from the front will to the OAP backend |`256`|
`plugin.dubbo.collect_provider_arguments`| Apache Dubbo provider collect `arguments` in RPC call, use `Object#toString` to collect `arguments`. |`false`|
`plugin.dubbo.consumer_provider_length_threshold`| When `plugin.dubbo.provider_consumer_arguments` is `true`, Arguments of length from the front will to the OAP backend |`256`|
`plugin.kafka.bootstrap_servers`| A list of host/port pairs to use for establishing the initial connection to the Kafka cluster. | `localhost:9092`
`plugin.kafka.bootstrap_servers`| A list of host/port pairs to use for establishing the initial connection to the Kafka cluster. | `localhost:9092`|
`plugin.kafka.get_topic_timeout`| Timeout period of reading topics from the Kafka server, the unit is second. |`10`|
`plugin.kafka.consumer_config`| Kafka producer configuration. ||
`plugin.kafka.producer_config`| Kafka producer configuration. Read [producer configure](http://kafka.apache.org/24/documentation.html#producerconfigs) to get more details. Check [Kafka report doc](How-to-enable-kafka-reporter.md) for more details and examples. | |
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册