0

I'm using this addon bundle for dropwizard to log messages to a Graylog server: https://github.com/gini/dropwizard-gelf

It worked out of the box simply by adding it to the pom.xml and configuring it in the config.yml of my dropwizard server. Great stuff!

The only problem is, if my Graylog server is not available during startup for some reason, the GelfAppenderFactory throws a RuntimeException and dropwizard exits. My webserver never starts just because the logging server is unavailable. Not good.

Any ideas how I can get around it? My current approach would be to copy&paste the GelfAppenderFactory to my own code and wrap the crucial part in a try/catch block. That feels rather crude... so any help is much appreciated.

craddack
  • 116
  • 1
  • 4
  • 1
    There are a few options. You could overwrite the DefaultLogFactory and handle that in the configure method. You could overwrite the ConfigureCommand and handle it when it tries to create the logging. – pandaadb Mar 18 '16 at 16:16
  • Thanks for the quick response. I'd hoped to get around messing with the dropwizard innards, though. – craddack Mar 18 '16 at 16:30
  • In that case, look at your main class. In the run method, you could in theory wrap everything in a massive try catch and analyse the exception – pandaadb Mar 18 '16 at 16:45
  • 1
    Create a hybrid logger that either caches or uses something else in case of exception. E.g. do a delegate, one logger goes to file, one logger to GELF. If GELF throws an exception, you catch it and use the other logger. That way you don't loose anything. You can even cache the statements that could not be sent. So on the next log event (with probably reasonable timers) you just retry the ones that failed before? – pandaadb Mar 18 '16 at 16:58
  • Yeah, that's the bigger solution. I'll look into it. Maybe I should also checkout other Graylog adapters like [logstash-gelf](https://github.com/mp911de/logstash-gelf) – craddack Mar 21 '16 at 12:23
  • @pandaadb: I'm trying to overwrite DefaultLoggingFactory at the moment. How do I get dropwizard to use my overwritten class instead of DefaultLoggingFactory? – craddack Mar 24 '16 at 12:01
  • 1
    Hey. What I did is, in the Configuration file, overwrite setLoggingFactory and annotate it with @JsonProperty("logging"). in the setLoggingFactory use your own type, for example for me: public void setLoggingFactory(MyOwnDropWizardLoggingConfig factory). DW will read the type and parse it accordingly. It must extend the LoggingFactory. It must have a zero argument constructor. My full config: http://stackoverflow.com/questions/27483442/dropwizard-doesnt-log-custom-loggers-to-file/33085996#33085996 – pandaadb Mar 24 '16 at 12:22
  • Hmm... I must be missing something. I get: Failed to parse configuration at: logging; Problem deserializing property 'logging' (expected type: [simple type, class com.example.util.graylog.GracefulLoggingFactory]; actual type: io.dropwizard.logging.DefaultLoggingFactory), problem: argument type mismatch (through reference chain: AppConfiguration["logging"]) – craddack Mar 24 '16 at 13:17
  • I'm working with Dropwizard 0.9.1 btw. LoggingFactory is an interface now, so I extend DefaultLoggingFactory. – craddack Mar 24 '16 at 13:23
  • Did that do the trick? Alternatively, in that link above, there is also an example on how to add a completely new type to DW and make it available to it. So instead of "logging" you can have a completely custom type. Ah yes, and I was working on 0.8.4 at the time – pandaadb Mar 24 '16 at 15:25

2 Answers2

0

This was the configuration I was using in my application:

in run(Configuration cofing, Environment env) method

// GELF Configuration
GelfAppenderFactory gelfAppenderFactory = (GelfAppenderFactory) Iterables.find(configuration.getLoggingFactory().getAppenders(), new Predicate<AppenderFactory>() {
    @Override
    public boolean apply(AppenderFactory input) {
        return input instanceof GelfAppenderFactory;
    }
}, null);

if (gelfAppenderFactory != null) {
    GelfBootstrap.bootstrap(getName(), gelfAppenderFactory.getHost(), gelfAppenderFactory.getPort(), false);
    Thread.currentThread().setUncaughtExceptionHandler(UncaughtExceptionHandlers.systemExit());
}// End GELF configuration

in your .yaml file

logging:
  level: INFO
   appenders:
     - type: console
     - type: gelf
         host: graylog2
         includeFullMDC: true
António Ribeiro
  • 4,129
  • 5
  • 32
  • 49
Vish Vaka
  • 1
  • 2
  • Thank you. Unfortunately this does not solve my problem, because the GelfAppender configured in the YML throws a runtime exception **before** `run` is executed (in case the logging server is not reachable) – craddack Mar 21 '16 at 12:15
0

To achieve what I wanted I gave up trying to use dropwizard-gelf. Which is probably a good idea anyway, because it uses an outdated version of a discontinued plugin (https://github.com/Moocar/logback-gelf).

Instead I reset dropwizard's logging configuration and reverted to loading a logback.xml file from the classpath like this:

void reset() {
  ILoggerFactory factory = LoggerFactory.getILoggerFactory();
  LoggerContext context = (LoggerContext)factory;
  context.reset();
  ContextInitializer initializer = new ContextInitializer(context);
  initializer.autoConfig();
}

Unfortunately Dropwizard does not provide any standard way to re-enable Logback's standard ways (see https://github.com/dropwizard/dropwizard/pull/567)

However, now I am free to use the (actively developed) plugin logstash-gelf (https://github.com/mp911de/logstash-gelf) with a Logback configuration.

Thanks @pandaadb for all your help. In the end digging into Dropwizard's inner workings was just too much hassle for me.

craddack
  • 116
  • 1
  • 4