Dropwizard 0.9.1:在自定义 AppenderFactory 实现中使用应用程序配置值
Dropwizard 0.9.1: Use Application Configuration Values in Custom AppenderFactory Implementation
我正在构建一个基于 Dropwizard v0.9.1 的网络堆栈。堆栈中的所有日志都发送到 Loggly via a custom implementation of the AppenderFactory 接口:
@JsonTypeName("loggly")
public class LogglyAppenderFactory extends AbstractAppenderFactory {
@JsonProperty
private String token;
@JsonProperty
private final Optional<String> tag = Optional.absent();
@Override
public Appender<ILoggingEvent> build(LoggerContext context, String applicationName, Layout<ILoggingEvent> layout) {
...
}
protected Layout<ILoggingEvent> buildLayout(LoggerContext context) {
...
}
}
此 class 未在我的应用程序 class 中的环境中注册。相反,它似乎是由 Dropwizard 基于 @JsonTypeName 注释自动装配的。尽管如此,token
和 tag
字段由出现在我的配置 yaml 文件中的值填充:
logging:
level: INFO
appenders:
# send logs to loggly
- type: loggly
threshold: INFO
token: "my-secret-loggly-token"
tag: "webservice-ci"
问题是,这些配置值没有出现在我的应用程序的 Configuration class 中,这意味着我无法在构建其他资源或健康检查时重新使用它们。
理想情况下,我想像这样手动注册 LogglyAppenderFactory
:
public class WebServiceApplication extends Application<WebServiceAppConfiguration> {
@Override
public void run(WebServiceAppConfiguration configuration, Environment environment) throws Exception {
final HttpClient httpClient = new HttpClientBuilder(environment).using(configuration.getHttpClientConfiguration()).build("httpClient");
// to be clear, environment.logAppenders() doesn't exist, and this doesn't work
final LogglyAppenderFactory logglyAppenderFactory = new LogglyAppenderFactoryBuilder(configuration).build();
environment.logAppenders().register(logglyAppenderFactory)
// when we make this HealthCheck, it would be cool to reference the same config values that the AppenderFactory used
final LogglyHealthCheck logglyHealthCheck = new LogglyHealthCheck(httpClient, configuration);
environment.healthChecks().register("Loggly", logglyHealthCheck);
}
}
这样 LogglyAppenderFactory 和 LogglyHealthCheck 都可以使用相同的配置值来指示它们如何与外部服务通信。
我怀疑如果我引入像 Google Guice 这样的依赖注入框架并使用它将应用程序配置注入到两个对象中,这可能是可能的,但另一方面,因为通常会创建 logback appender在应用程序生命周期的早期,我不知道在创建 AppenderFactory 时 Guice 是否准备就绪。
有人知道怎么做吗?如果没有,我是否坚持将令牌两次放入我的配置文件?一次进入 logging.appenders
部分,然后再次进入 LogglyHealthCheck 可以访问的其他部分?
我想你在找
configuration.getLoggingFactory();
此 API 为您提供配置文件中的所有日志记录配置。
例如
configuration.getLoggingFactory().getLevel();
configuration.getLoggingFactory().getAppenders()
((ConsoleAppenderFactory)configuration.getLoggingFactory().getAppenders().get(0)).getLogFormat();
不是最漂亮的API,但应该可以
原来配置 class 公开了一个包含日志记录配置的 LoggingFactory。我将这个辅助方法添加到我的配置 class 中,它从我的自定义 AppenderFactory 中提取我关心的字段:
/**
* Extracts the Loggly token from the logging.appenders section of the configuration file.
* If a {@link LogglyAppenderFactory} is not specified as one of the log appenders, this method returns null.
* @return the Loggly token or null if no token is specified
*/
public String getLogglyToken() {
final DefaultLoggingFactory loggingFactory = (DefaultLoggingFactory) getLoggingFactory();
for (final AppenderFactory appenderFactory : loggingFactory.getAppenders()) {
if (appenderFactory instanceof LogglyAppenderFactory) {
final LogglyAppenderFactory logglyAppenderFactory = (LogglyAppenderFactory) appenderFactory;
return logglyAppenderFactory.getToken();
}
}
return null;
}
虽然不漂亮,但很管用!
我正在构建一个基于 Dropwizard v0.9.1 的网络堆栈。堆栈中的所有日志都发送到 Loggly via a custom implementation of the AppenderFactory 接口:
@JsonTypeName("loggly")
public class LogglyAppenderFactory extends AbstractAppenderFactory {
@JsonProperty
private String token;
@JsonProperty
private final Optional<String> tag = Optional.absent();
@Override
public Appender<ILoggingEvent> build(LoggerContext context, String applicationName, Layout<ILoggingEvent> layout) {
...
}
protected Layout<ILoggingEvent> buildLayout(LoggerContext context) {
...
}
}
此 class 未在我的应用程序 class 中的环境中注册。相反,它似乎是由 Dropwizard 基于 @JsonTypeName 注释自动装配的。尽管如此,token
和 tag
字段由出现在我的配置 yaml 文件中的值填充:
logging:
level: INFO
appenders:
# send logs to loggly
- type: loggly
threshold: INFO
token: "my-secret-loggly-token"
tag: "webservice-ci"
问题是,这些配置值没有出现在我的应用程序的 Configuration class 中,这意味着我无法在构建其他资源或健康检查时重新使用它们。
理想情况下,我想像这样手动注册 LogglyAppenderFactory
:
public class WebServiceApplication extends Application<WebServiceAppConfiguration> {
@Override
public void run(WebServiceAppConfiguration configuration, Environment environment) throws Exception {
final HttpClient httpClient = new HttpClientBuilder(environment).using(configuration.getHttpClientConfiguration()).build("httpClient");
// to be clear, environment.logAppenders() doesn't exist, and this doesn't work
final LogglyAppenderFactory logglyAppenderFactory = new LogglyAppenderFactoryBuilder(configuration).build();
environment.logAppenders().register(logglyAppenderFactory)
// when we make this HealthCheck, it would be cool to reference the same config values that the AppenderFactory used
final LogglyHealthCheck logglyHealthCheck = new LogglyHealthCheck(httpClient, configuration);
environment.healthChecks().register("Loggly", logglyHealthCheck);
}
}
这样 LogglyAppenderFactory 和 LogglyHealthCheck 都可以使用相同的配置值来指示它们如何与外部服务通信。
我怀疑如果我引入像 Google Guice 这样的依赖注入框架并使用它将应用程序配置注入到两个对象中,这可能是可能的,但另一方面,因为通常会创建 logback appender在应用程序生命周期的早期,我不知道在创建 AppenderFactory 时 Guice 是否准备就绪。
有人知道怎么做吗?如果没有,我是否坚持将令牌两次放入我的配置文件?一次进入 logging.appenders
部分,然后再次进入 LogglyHealthCheck 可以访问的其他部分?
我想你在找
configuration.getLoggingFactory();
此 API 为您提供配置文件中的所有日志记录配置。
例如
configuration.getLoggingFactory().getLevel();
configuration.getLoggingFactory().getAppenders()
((ConsoleAppenderFactory)configuration.getLoggingFactory().getAppenders().get(0)).getLogFormat();
不是最漂亮的API,但应该可以
原来配置 class 公开了一个包含日志记录配置的 LoggingFactory。我将这个辅助方法添加到我的配置 class 中,它从我的自定义 AppenderFactory 中提取我关心的字段:
/**
* Extracts the Loggly token from the logging.appenders section of the configuration file.
* If a {@link LogglyAppenderFactory} is not specified as one of the log appenders, this method returns null.
* @return the Loggly token or null if no token is specified
*/
public String getLogglyToken() {
final DefaultLoggingFactory loggingFactory = (DefaultLoggingFactory) getLoggingFactory();
for (final AppenderFactory appenderFactory : loggingFactory.getAppenders()) {
if (appenderFactory instanceof LogglyAppenderFactory) {
final LogglyAppenderFactory logglyAppenderFactory = (LogglyAppenderFactory) appenderFactory;
return logglyAppenderFactory.getToken();
}
}
return null;
}
虽然不漂亮,但很管用!