Reputation: 1749
I'm building a web stack based on Dropwizard v0.9.1. All logs from the stack are sent to Loggly via a custom implementation of the AppenderFactory interface:
@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) {
...
}
}
This class isn't registered with the Environment in my Application class. Instead, it seems to be autowired by Dropwizard based on the @JsonTypeName annotation. Despite this, the token
and tag
fields are populated by values that appear in my configuration yaml file:
logging:
level: INFO
appenders:
# send logs to loggly
- type: loggly
threshold: INFO
token: "my-secret-loggly-token"
tag: "webservice-ci"
The thing is, these configuration values don't appear in my application's Configuration class, which means that I can't re-use them when building other Resources or HealthChecks.
Ideally, I'd like to manually register the LogglyAppenderFactory
like this:
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);
}
}
so that both the LogglyAppenderFactory and the LogglyHealthCheck can use the same configuration values that dictate how they talk to the external service.
I suspect that this might be possible if I introduce a Dependency Injection framework like Google Guice and use it to inject the application configuration into both objects, but on the other hand, since logback appenders are typically created very early in the application lifecycle, I don't know if Guice will be ready to go when the AppenderFactory is being created.
Does anybody know how to do this? If not, am I stuck with putting the token into my config file twice? Once in the logging.appenders
section, and again in some other section that the LogglyHealthCheck can access?
Upvotes: 1
Views: 805
Reputation: 1749
Turns out that the Configuration class exposes a LoggingFactory that contains the logging config. I added this helper method to my Configuration class that extracts the field that I care about from my custom 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;
}
It isn't pretty, but it works!
Upvotes: 1
Reputation: 651
I think you're looking for
configuration.getLoggingFactory();
This API gives you all the logging config from your config file.
eg.
configuration.getLoggingFactory().getLevel();
configuration.getLoggingFactory().getAppenders()
((ConsoleAppenderFactory)configuration.getLoggingFactory().getAppenders().get(0)).getLogFormat();
Not the prettiest API, but it should work
Upvotes: 2