Spring boot: доступ к системной переменной из log4j2.properties - PullRequest
0 голосов
/ 17 декабря 2018

Я написал специальный 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 дважды.

...