Composing request logger

Has anyone been able to use composing request logger in their setup?

druid.request.logging.type=composing

druid.request.logging.loggerProviders=[“file”,“emitter”]

Above is the config I am using in the runtime.properties file of historical. But the server startup is failing with the below error:

2018-08-07T17:33:26,461 ERROR [main] io.druid.cli.CliHistorical - Error when starting up. Failing.

com.google.inject.ProvisionException: Unable to provision, see the following errors:

  1. Problem parsing object at prefix[druid.request.logging]: Can not instantiate value of type [simple type, class io.druid.server.log.NoopRequestLoggerProvider] from String value (‘file’); no single-String constructor/factory method

at [Source: N/A; line: -1, column: -1] (through reference chain: io.druid.server.log.ComposingRequestLoggerProvider[“loggerProviders”]->java.util.ArrayList[0]).

at io.druid.guice.JsonConfigProvider.bind(JsonConfigProvider.java:133) (via modules: com.google.inject.util.Modules$OverrideModule -> com.google.inject.util.Modules$OverrideModule -> io.druid.guice.QueryableModule)

at io.druid.guice.JsonConfigProvider.bind(JsonConfigProvider.java:133) (via modules: com.google.inject.util.Modules$OverrideModule -> com.google.inject.util.Modules$OverrideModule -> io.druid.guice.QueryableModule)

while locating com.google.common.base.Supplier<io.druid.server.log.RequestLoggerProvider>

at io.druid.guice.JsonConfigProvider.bind(JsonConfigProvider.java:134) (via modules: com.google.inject.util.Modules$OverrideModule -> com.google.inject.util.Modules$OverrideModule -> io.druid.guice.QueryableModule)

while locating io.druid.server.log.RequestLoggerProvider

at io.druid.guice.QueryableModule.configure(QueryableModule.java:47) (via modules: com.google.inject.util.Modules$OverrideModule -> com.google.inject.util.Modules$OverrideModule -> io.druid.guice.QueryableModule)

while locating io.druid.server.log.RequestLogger

for the 5th parameter of io.druid.server.QueryLifecycleFactory.(QueryLifecycleFactory.java:52)

at io.druid.server.QueryLifecycleFactory.class(QueryLifecycleFactory.java:52)

while locating io.druid.server.QueryLifecycleFactory

for the 1st parameter of io.druid.server.QueryResource.(QueryResource.java:113)

at io.druid.server.QueryResource.class(QueryResource.java:78)

while locating io.druid.server.QueryResource

1 error

at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1028) ~[guice-4.1.0.jar:?]

at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1050) ~[guice-4.1.0.jar:?]

at io.druid.guice.LifecycleModule$2.start(LifecycleModule.java:132) ~[druid-api-0.12.1.jar:0.12.1]

at io.druid.cli.GuiceRunnable.initLifecycle(GuiceRunnable.java:101) [druid-services-0.13.0-SNAPSHOT.jar:0.13.0-SNAPSHOT]

at io.druid.cli.ServerRunnable.run(ServerRunnable.java:50) [druid-services-0.13.0-SNAPSHOT.jar:0.13.0-SNAPSHOT]

at io.druid.cli.Main.main(Main.java:116) [druid-services-0.13.0-SNAPSHOT.jar:0.13.0-SNAPSHOT]

Caused by: java.lang.IllegalArgumentException: Can not instantiate value of type [simple type, class io.druid.server.log.NoopRequestLoggerProvider] from String value (‘file’); no single-String constructor/factory method

at [Source: N/A; line: -1, column: -1] (through reference chain: io.druid.server.log.ComposingRequestLoggerProvider[“loggerProviders”]->java.util.ArrayList[0])

at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:2774) ~[jackson-databind-2.4.6.jar:2.4.6]

at com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:2700) ~[jackson-databind-2.4.6.jar:2.4.6]

Any insight on this? I have written a custom request logger that I would like to use along with the FileRequestLogger. But running into this issue (which seems like a bug to me). Just wanted to see if someone else has had luck using the composite request logger or if I am doing something wrong.

FWIW, just specifying druid.request.logging.type=composing works. However, when I also have druid.request.logging.loggerProviders=[“file”,“emitter”], server startup fails with the above error.

Ok, I figured this out finally. And I don’t see how anyone can figure this out without stepping through the code and understanding what the jackson/json parser needs.
For users who are trying to use composing request logger in future, below is an example configuration that use file and emitter request loggers:

druid.request.logging.type=composing

druid.request.logging.loggerProviders=[{“type”:“file”, “dir”:"/logs/druid"}, {“type”:“emitter”}]

Notice how the list elements are objects. Also notice that the config for file request logger has just “dir” with the druid.request.logging stripped out.