Я написал специальный appender для log4j2, который отправляет информацию журнала в центральный регистратор.
CUSTOM APPENDER:
@Plugin(name = "WebLoggingAppender", category = "Core", elementType = "appender", printObject = true)
public class WebLoggingAppender extends AbstractAppender {
private static WebLoggerClient client;
private String artifact;
private String host;
private int port;
protected WebLoggingAppender(String name, Filter filter,
Layout<? extends Serializable> layout, String filename) {
super(name, filter, layout);
}
@PluginFactory
public static WebLoggingAppender createAppender(@PluginAttribute("name") String name,
@PluginAttribute("artifact") String artifact,
@PluginAttribute("host") String host,
@PluginAttribute("port") int port,
@PluginAttribute("fileName") final String fileName,
@PluginElement("Layout") Layout<? extends Serializable> layout,
@PluginElement("Filters") Filter filter) {
WebLoggingAppender appender = new WebLoggingAppender(name, filter, layout, fileName);
appender.artifact = artifact;
appender.host = host;
appender.port = port;
appender.initClient();
return appender;
}
@Override
public void append(LogEvent logEvent) {
Log log = buildLogObject(logEvent);
client.sendLog(log);
}
private Log buildLogObject(LogEvent logEvent) {
String ex = "";
if (logEvent.getThrown() != null) {
ex = getStackTrace(logEvent.getThrown());
logEvent.getThrown().printStackTrace();
}
return Log.newBuilder()
.setLevel(logEvent.getLevel().intLevel())
.setTime(logEvent.getTimeMillis())
.setLogMessage(logEvent.getMessage().toString())
.setStackTrace(logEvent.getSource().toString())
.setLoggerName(artifact)
.setException(ex).build();
}
void initClient() {
WebLoggingAppender.client = new WebLoggerClient(host, port);
System.out.println("gRPC client for logging is ready.");
}
private static String getStackTrace(final Throwable throwable) {
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw, true);
throwable.printStackTrace(pw);
return sw.getBuffer().toString();
}
}
Здесь контролируются все конфигурации регистрациииз logging.properties
файла.
application.yml
logging:
config: "classpath:logging.properties"
logging.properties
# Declare loggers
name=LoggingConfig
appenders=a_console, a_web, a_rolling
rootLogger.level=info
rootLogger.appenderRefs=ar_console, ar_web, ar_rolling
rootLogger.appenderRef.ar_console.ref=sout
rootLogger.appenderRef.ar_web.ref=web
rootLogger.appenderRef.ar_rolling.ref=DailyRollingAppender
rootLogger.appenderRef.ar_rolling.level=error
rootLogger.appenderRef.ar_console.level=error
rootLogger.appenderRef.ar_web.level=info
# Console logger
appender.a_console.type=Console
appender.a_console.name=sout
appender.a_console.layout.type=PatternLayout
appender.a_console.layout.pattern=%d{ISO8601} [%t] %-5p (%F\:%L) - %m%n
# Web logger
appender.a_web.type=WebLoggingAppender
appender.a_web.name=web
appender.a_web.artifact=AhmadTea Producer
appender.a_web.host=${CENTRAL_LOGGER_HOST}
appender.a_web.port=6565
# File logger(only for errors)
appender.a_rolling.type=RollingFile
appender.a_rolling.name=DailyRollingAppender
appender.a_rolling.layout.pattern=%d{ISO8601} [%t] %-5p (%F\:%L) - %m%n
appender.a_rolling.fileName=C:\\logs\\rest-auth\\producer.log
appender.a_rolling.filePattern=C:\\logs\\rest-auth\\producer-%d{yyyy-MM-dd}.log
appender.a_rolling.layout.type=PatternLayout
appender.a_rolling.policies.type=Policies
appender.a_rolling.policies.time.type=TimeBasedTriggeringPolicy
appender.a_rolling.policies.time.interval=1
Все былоработал хорошо, пока я не попытался получить доступ к системной переменной из файла logging.properties.Приложение видит ${CENTRAL_LOGGER_HOST}
как строку, не являющуюся переменной.
ИСКЛЮЧЕННОЕ ПРОИЗВОДСТВО:
2018-12-17 14:54:39,532 main ERROR Unable to invoke factory method in class uz.demo.tea.common.logging.WebLoggingAppender for element WebLoggingAppender: java.lang.IllegalArgumentException: Invalid host or port: ${CENTRAL_LOGGER_HOST} 6565 java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:136)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:958)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:898)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:890)
at org.apache.logging.log4j.core.config.AbstractConfiguration.doConfigure(AbstractConfiguration.java:513)
at org.apache.logging.log4j.core.config.AbstractConfiguration.initialize(AbstractConfiguration.java:237)
at org.apache.logging.log4j.core.config.AbstractConfiguration.start(AbstractConfiguration.java:249)
at org.apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:545)
at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:261)
at org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.loadConfiguration(Log4J2LoggingSystem.java:175)
at org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.loadConfiguration(Log4J2LoggingSystem.java:166)
at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithSpecificConfig(AbstractLoggingSystem.java:67)
at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:57)
at org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.initialize(Log4J2LoggingSystem.java:147)
at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:269)
at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:237)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:200)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:173)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:74)
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:54)
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:364)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:323)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1277)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1265)
at uz.demo.tea.ApiApplication.main(ApiApplication.java:12)
Caused by: java.lang.IllegalArgumentException: Invalid host or port: ${CENTRAL_LOGGER_HOST} 6565
at io.grpc.internal.GrpcUtil.authorityFromHostAndPort(GrpcUtil.java:480)
at io.grpc.netty.NettyChannelBuilder.<init>(NettyChannelBuilder.java:115)
at io.grpc.netty.NettyChannelBuilder.forAddress(NettyChannelBuilder.java:101)
at io.grpc.netty.NettyChannelProvider.builderForAddress(NettyChannelProvider.java:37)
at io.grpc.netty.NettyChannelProvider.builderForAddress(NettyChannelProvider.java:23)
at io.grpc.ManagedChannelBuilder.forAddress(ManagedChannelBuilder.java:37)
at uz.demo.tea.common.logging.WebLoggerClient.init(WebLoggerClient.java:18)
at uz.demo.tea.common.logging.WebLoggerClient.<init>(WebLoggerClient.java:13)
at uz.demo.tea.common.logging.WebLoggingAppender.initClient(WebLoggingAppender.java:68)
at uz.demo.tea.common.logging.WebLoggingAppender.createAppender(WebLoggingAppender.java:41)
... 33 more
Caused by: java.net.URISyntaxException: Illegal character in authority at index 2: //${CENTRAL_LOGGER_HOST}:6565
at java.net.URI$Parser.fail(URI.java:2848)
at java.net.URI$Parser.parseAuthority(URI.java:3186)
at java.net.URI$Parser.parseHierarchical(URI.java:3097)
at java.net.URI$Parser.parse(URI.java:3063)
at java.net.URI.<init>(URI.java:673)
at io.grpc.internal.GrpcUtil.authorityFromHostAndPort(GrpcUtil.java:478)
... 42 more
Я мог бы использовать System.getenv("CENTRAL_LOGGER_HOST")
, однако я считаю, что было бы неплохоесли все элементы конфигурации хранятся вместе.
Есть ли хороший способ доступа к системным переменным в файле свойств?
PS Я не использовал имя log4j2.properties, так как оновызвал загрузку appender дважды.