diff --git a/deployment/src/main/java/io/quarkiverse/logging/splunk/LoggingSplunkProcessor.java b/deployment/src/main/java/io/quarkiverse/logging/splunk/LoggingSplunkProcessor.java index 47857c4..e3b6694 100644 --- a/deployment/src/main/java/io/quarkiverse/logging/splunk/LoggingSplunkProcessor.java +++ b/deployment/src/main/java/io/quarkiverse/logging/splunk/LoggingSplunkProcessor.java @@ -12,6 +12,7 @@ import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem; import io.quarkus.deployment.builditem.FeatureBuildItem; import io.quarkus.deployment.builditem.LogHandlerBuildItem; +import io.quarkus.deployment.builditem.NamedLogHandlersBuildItem; import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem; class LoggingSplunkProcessor { @@ -29,6 +30,12 @@ LogHandlerBuildItem logHandler(SplunkLogHandlerRecorder recorder, SplunkConfig c return new LogHandlerBuildItem(recorder.initializeHandler(config)); } + @BuildStep + @Record(ExecutionTime.RUNTIME_INIT) + NamedLogHandlersBuildItem logNamedHandlers(SplunkLogHandlerRecorder recorder, SplunkConfig config) { + return new NamedLogHandlersBuildItem(recorder.initializeHandlers(config)); + } + @BuildStep ExtensionSslNativeSupportBuildItem enableSSL() { // Enable SSL support by default diff --git a/deployment/src/test/java/io/quarkiverse/logging/splunk/LoggingSplunkNamedHandlerConfigTest.java b/deployment/src/test/java/io/quarkiverse/logging/splunk/LoggingSplunkNamedHandlerConfigTest.java new file mode 100644 index 0000000..b09e466 --- /dev/null +++ b/deployment/src/test/java/io/quarkiverse/logging/splunk/LoggingSplunkNamedHandlerConfigTest.java @@ -0,0 +1,41 @@ +/* +Copyright (c) 2023 Amadeus s.a.s. +Contributor(s): Kevin Viet, Romain Quinio, Yohann Puyhaubert (Amadeus s.a.s.) + */ +package io.quarkiverse.logging.splunk; + +import io.quarkus.test.QuarkusUnitTest; +import org.jboss.logging.Logger; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.mockserver.model.JsonBody.json; + +class LoggingSplunkNamedHandlerConfigTest extends AbstractMockServerTest { + + @RegisterExtension + static final QuarkusUnitTest unitTest = new QuarkusUnitTest() + .withConfigurationResource("application-splunk-logging-named-handler.properties") + .withConfigurationResource("mock-server.properties") + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)); + + static final Logger logger = Logger.getLogger(LoggingSplunkNamedHandlerConfigTest.class); + + static final Logger monitoringLogger = Logger.getLogger("monitoring"); + + @Test + void indexWithDefaultLoggerAndNamedLogger() { + logger.warn("hello splunk"); + monitoringLogger.info("{\"key\":\"value\"}"); + awaitMockServer(); + httpServer.verify(requestToJsonEndpoint() + .withBody(json("{ index: 'mylogindex'}")) + .withHeader("Authorization", "Splunk 12345678-1234-1234-1234-1234567890AB")); + httpServer.verify(requestToJsonEndpoint() + .withBody(json("{ index: 'mystatsindex'}")) + .withHeader("Authorization", "Splunk 12345678-0000-0000-0000-1234567890AB")); + } + +} diff --git a/deployment/src/test/resources/application-splunk-logging-named-handler.properties b/deployment/src/test/resources/application-splunk-logging-named-handler.properties new file mode 100644 index 0000000..05b7f3d --- /dev/null +++ b/deployment/src/test/resources/application-splunk-logging-named-handler.properties @@ -0,0 +1,10 @@ +quarkus.log.handler.splunk.token=12345678-1234-1234-1234-1234567890AB +quarkus.log.handler.splunk.level=WARN +quarkus.log.handler.splunk.format=%s%e +quarkus.log.handler.splunk.metadata-index=mylogindex +quarkus.log.handler.splunk."MONITORING".url=http://localhost:8088 +quarkus.log.handler.splunk."MONITORING".token=12345678-0000-0000-0000-1234567890AB +quarkus.log.handler.splunk."MONITORING".level=INFO +quarkus.log.handler.splunk."MONITORING".metadata-index=mystatsindex +quarkus.log.category."monitoring".handlers=MONITORING +quarkus.log.category."monitoring".use-parent-handlers=false diff --git a/docs/modules/ROOT/pages/includes/quarkus-log-handler-splunk.adoc b/docs/modules/ROOT/pages/includes/quarkus-log-handler-splunk.adoc index da9f035..6dd7281 100644 --- a/docs/modules/ROOT/pages/includes/quarkus-log-handler-splunk.adoc +++ b/docs/modules/ROOT/pages/includes/quarkus-log-handler-splunk.adoc @@ -421,6 +421,418 @@ endif::add-copy-button-to-env-var[] --|`Map` | + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.enabled]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.enabled[quarkus.log.handler.splunk."handlers".enabled]` + +[.description] +-- +Determine whether to enable the handler + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__ENABLED+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__ENABLED+++` +endif::add-copy-button-to-env-var[] +--|boolean +|`true` + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.level]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.level[quarkus.log.handler.splunk."handlers".level]` + +[.description] +-- +The splunk handler log level. By default, it is no more strict than the root handler level. + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__LEVEL+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__LEVEL+++` +endif::add-copy-button-to-env-var[] +--|link:https://docs.jboss.org/jbossas/javadoc/7.1.2.Final/org/jboss/logmanager/Level.html[Level] + +|`ALL` + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.url]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.url[quarkus.log.handler.splunk."handlers".url]` + +[.description] +-- +Splunk HEC endpoint base url. +With raw events, the endpoint targeted is /services/collector/raw. With flat or nested JSON events, the endpoint targeted is /services/collector/event/1.0. + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__URL+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__URL+++` +endif::add-copy-button-to-env-var[] +--|string +|`https://localhost:8088/` + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.disable-certificate-validation]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.disable-certificate-validation[quarkus.log.handler.splunk."handlers".disable-certificate-validation]` + +[.description] +-- +Disable TLS certificate validation with HEC endpoint + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__DISABLE_CERTIFICATE_VALIDATION+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__DISABLE_CERTIFICATE_VALIDATION+++` +endif::add-copy-button-to-env-var[] +--|boolean +|`false` + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.token]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.token[quarkus.log.handler.splunk."handlers".token]` + +[.description] +-- +The application token to authenticate with HEC, the token is mandatory if the extension is enabled https://docs.splunk.com/Documentation/Splunk/latest/Data/FormateventsforHTTPEventCollector++#++HEC_token + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__TOKEN+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__TOKEN+++` +endif::add-copy-button-to-env-var[] +--|string +| + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.send-mode]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.send-mode[quarkus.log.handler.splunk."handlers".send-mode]` + +[.description] +-- +The strategy to send events to HEC. +In sequential mode, there is only one HTTP connection to HEC and the order of events is preserved, but performance is lower. In parallel mode, event batches are sent asynchronously over multiple HTTP connections, and events with the same timestamp (that has 1 millisecond resolution) may be indexed out of order by Splunk. + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__SEND_MODE+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__SEND_MODE+++` +endif::add-copy-button-to-env-var[] +-- a| +`sequential`, `parallel` +|`sequential` + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.channel]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.channel[quarkus.log.handler.splunk."handlers".channel]` + +[.description] +-- +A GUID to identify an HEC client and guarantee isolation at HEC level in case of slow clients. https://docs.splunk.com/Documentation/Splunk/latest/Data/AboutHECIDXAck++#++About_channels_and_sending_data + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__CHANNEL+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__CHANNEL+++` +endif::add-copy-button-to-env-var[] +--|string +| + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.batch-interval]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.batch-interval[quarkus.log.handler.splunk."handlers".batch-interval]` + +[.description] +-- +Batching delay before sending a group of events. If 0, the events are sent immediately. + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__BATCH_INTERVAL+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__BATCH_INTERVAL+++` +endif::add-copy-button-to-env-var[] +--|link:https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html[Duration] + link:#duration-note-anchor-{summaryTableId}[icon:question-circle[], title=More information about the Duration format] +|`10S` + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.batch-size-count]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.batch-size-count[quarkus.log.handler.splunk."handlers".batch-size-count]` + +[.description] +-- +Maximum number of events in a batch. By default 10, if 0 no batching. + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__BATCH_SIZE_COUNT+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__BATCH_SIZE_COUNT+++` +endif::add-copy-button-to-env-var[] +--|long +|`10` + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.batch-size-bytes]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.batch-size-bytes[quarkus.log.handler.splunk."handlers".batch-size-bytes]` + +[.description] +-- +Maximum total size in bytes of events in a batch. By default 10KB, if 0 no batching. + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__BATCH_SIZE_BYTES+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__BATCH_SIZE_BYTES+++` +endif::add-copy-button-to-env-var[] +--|long +|`10` + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.max-retries]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.max-retries[quarkus.log.handler.splunk."handlers".max-retries]` + +[.description] +-- +Maximum number of retries in case of I/O exceptions with HEC connection. + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__MAX_RETRIES+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__MAX_RETRIES+++` +endif::add-copy-button-to-env-var[] +--|long +|`0` + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.format]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.format[quarkus.log.handler.splunk."handlers".format]` + +[.description] +-- +The log format, defining which metadata are inlined inside the log main payload. +Specific metadata (hostname, category, thread name, ...), as well as MDC key/value map, can also be sent in a structured way. + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__FORMAT+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__FORMAT+++` +endif::add-copy-button-to-env-var[] +--|string +|`%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] (%t) %s%e%n` + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.include-exception]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.include-exception[quarkus.log.handler.splunk."handlers".include-exception]` + +[.description] +-- +Whether to send the thrown exception message as a structured metadata of the log event (as opposed to %e in a formatted message, it does not include the exception name or stacktrace). Only applicable to 'nested' serialization. + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__INCLUDE_EXCEPTION+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__INCLUDE_EXCEPTION+++` +endif::add-copy-button-to-env-var[] +--|boolean +|`false` + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.include-logger-name]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.include-logger-name[quarkus.log.handler.splunk."handlers".include-logger-name]` + +[.description] +-- +Whether to send the logger name as a structured metadata of the log event (equivalent of %c in a formatted message). Only applicable to 'nested' serialization. + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__INCLUDE_LOGGER_NAME+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__INCLUDE_LOGGER_NAME+++` +endif::add-copy-button-to-env-var[] +--|boolean +|`false` + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.include-thread-name]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.include-thread-name[quarkus.log.handler.splunk."handlers".include-thread-name]` + +[.description] +-- +Whether to send the thread name as a structured metadata of the log event (equivalent of %t in a formatted message). Only applicable to 'nested' serialization. + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__INCLUDE_THREAD_NAME+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__INCLUDE_THREAD_NAME+++` +endif::add-copy-button-to-env-var[] +--|boolean +|`false` + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.metadata-host]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.metadata-host[quarkus.log.handler.splunk."handlers".metadata-host]` + +[.description] +-- +Overrides the host name metadata value. + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__METADATA_HOST+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__METADATA_HOST+++` +endif::add-copy-button-to-env-var[] +--|string +| + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.metadata-source]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.metadata-source[quarkus.log.handler.splunk."handlers".metadata-source]` + +[.description] +-- +The source value to assign to the event data. For example, if you're sending data from an app you're developing, you could set this key to the name of the app. https://docs.splunk.com/Documentation/Splunk/latest/Data/FormateventsforHTTPEventCollector++#++Event_metadata + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__METADATA_SOURCE+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__METADATA_SOURCE+++` +endif::add-copy-button-to-env-var[] +--|string +| + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.metadata-source-type]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.metadata-source-type[quarkus.log.handler.splunk."handlers".metadata-source-type]` + +[.description] +-- +The optional format of the events, to enable some parsing on Splunk side. https://docs.splunk.com/Documentation/Splunk/latest/Data/FormateventsforHTTPEventCollector++#++Event_metadata +A given source type may have indexed fields extraction enabled, which is the case of the built-in _json used for nested serialization. + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__METADATA_SOURCE_TYPE+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__METADATA_SOURCE_TYPE+++` +endif::add-copy-button-to-env-var[] +--|string +| + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.metadata-index]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.metadata-index[quarkus.log.handler.splunk."handlers".metadata-index]` + +[.description] +-- +The optional name of the index by which the event data is to be stored. If set, it must be within the list of allowed indexes of the token (if it has the indexes parameter set). https://docs.splunk.com/Documentation/Splunk/latest/Data/FormateventsforHTTPEventCollector++#++Event_metadata + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__METADATA_INDEX+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__METADATA_INDEX+++` +endif::add-copy-button-to-env-var[] +--|string +| + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.metadata-fields-metadata-fields]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.metadata-fields-metadata-fields[quarkus.log.handler.splunk."handlers".metadata-fields]` + +[.description] +-- +Optional static key/value pairs to populate the "fields" key of event metadata. This isn't applicable to raw serialization. https://docs.splunk.com/Documentation/Splunk/latest/Data/FormateventsforHTTPEventCollector++#++Event_metadata + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__METADATA_FIELDS+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__METADATA_FIELDS+++` +endif::add-copy-button-to-env-var[] +--|`Map` +| + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.metadata-severity-field-name]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.metadata-severity-field-name[quarkus.log.handler.splunk."handlers".metadata-severity-field-name]` + +[.description] +-- +The name of the key used to convey the severity / log level in the metadata fields. Only applicable to 'flat' serialization. With 'nested' serialization, there is already a 'severity' field. + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__METADATA_SEVERITY_FIELD_NAME+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__METADATA_SEVERITY_FIELD_NAME+++` +endif::add-copy-button-to-env-var[] +--|string +|`severity` + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.serialization]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.serialization[quarkus.log.handler.splunk."handlers".serialization]` + +[.description] +-- +The format of the payload. + - With raw serialization, the log message is sent 'as is' in the HTTP body. Metadata can only be common to a whole batch and are sent via HTTP parameters. + - With nested serialization, the log message is sent into a 'message' field of a JSON structure which also contains dynamic metadata. + - With flat serialization, the log message is sent into the root 'event' field. Dynamic metadata is sent via the 'fields' root object. + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__SERIALIZATION+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__SERIALIZATION+++` +endif::add-copy-button-to-env-var[] +-- a| +`raw`, `nested`, `flat` +|`nested` + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.async]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.async[quarkus.log.handler.splunk."handlers".async]` + +[.description] +-- +Indicates whether to log asynchronously + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__ASYNC+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__ASYNC+++` +endif::add-copy-button-to-env-var[] +--|boolean +|`false` + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.async.queue-length]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.async.queue-length[quarkus.log.handler.splunk."handlers".async.queue-length]` + +[.description] +-- +The queue length to use before flushing writing + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__ASYNC_QUEUE_LENGTH+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__ASYNC_QUEUE_LENGTH+++` +endif::add-copy-button-to-env-var[] +--|int +|`512` + + +a| [[quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.async.overflow]]`link:#quarkus-log-handler-splunk_quarkus.log.handler.splunk.-handlers-.async.overflow[quarkus.log.handler.splunk."handlers".async.overflow]` + +[.description] +-- +Determine whether to block the publisher (rather than drop the message) when the queue is full + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__ASYNC_OVERFLOW+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_LOG_HANDLER_SPLUNK__HANDLERS__ASYNC_OVERFLOW+++` +endif::add-copy-button-to-env-var[] +-- a| +`block`, `discard` +|`block` + |=== ifndef::no-duration-note[] [NOTE] diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index 2bd81a5..2b43c69 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -242,6 +242,43 @@ After tuning `quarkus.log.handler.splunk.batch-size-count` and `quarkus.log.hand By setting `quarkus.log.handler.splunk.send-mode=parallel` multiple batches will be sent over the wire in parallel, potentially increasing throughput with the HEC endpoint. +=== Named Splunk log handlers + +A named log handler can be configured to manage multiple Splunk configurations for particular log emissions. Like for core Quarkus handlers (*console*, *file* or *syslog*), +Splunk named handlers follow the same configuration: + +``` +# Global configuration +quarkus.log.handler.splunk.token=12345678-1234-1234-1234-1234567890AB +quarkus.log.handler.splunk.metadata-index=mylogindex + +# Splunk named handler configuration, named here MONITORING +quarkus.log.handler.splunk."MONITORING".token=12345678-0000-0000-0000-1234567890AB +quarkus.log.handler.splunk."MONITORING".metadata-index=mystatsindex + +# Registration of the custom handler through Quarkus core category management, here monitoring as the logging category +quarkus.log.category."monitoring".handlers=MONITORING +quarkus.log.category."monitoring".use-parent-handlers=false +``` + +Next to use such logger in actual code, you can rely on annotation or factory: + +* With annotation: +``` +@LoggerName("monitoring") +Logger monitoringLogger; +``` + +* With factory: +``` +static final Logger monitoringLogger = Logger.getLogger("monitoring"); +``` + +==== Some important considerations +* Every handler is isolated and uses a separate Splunk client and connection pool, which means it has a cost. +* The configuration from the root handler are not inherited by named handlers. +* Use `quarkus.log.category."named-handler".use-parent-handlers=false` is required if you do not want the root handler to also receive log events already sent to named handlers. + == Extension Configuration Reference This extension follows the `log handlers` configuration domain that is defined by Quarkus, every configuration property of this extension will belong to the following configuration root : `quarkus.log.handler.splunk` diff --git a/integration-test/src/main/resources/application.properties b/integration-test/src/main/resources/application.properties index 1b24776..e8dbe11 100644 --- a/integration-test/src/main/resources/application.properties +++ b/integration-test/src/main/resources/application.properties @@ -1,7 +1,7 @@ quarkus.log.handler.splunk.url=https://localhost:8099 -quarkus.log.handler.splunk.index=main +quarkus.log.handler.splunk.metadata-index=main quarkus.log.handler.splunk.token=29fe2838-cab6-4d17-a392-37b7b8f41f75 quarkus.log.handler.splunk.batch-interval=1s quarkus.log.handler.splunk.disable-certificate-validation=true quarkus.log.console.enable=true -quarkus.log.handler.splunk.serialization=nested \ No newline at end of file +quarkus.log.handler.splunk.serialization=nested diff --git a/runtime/src/main/java/io/quarkiverse/logging/splunk/SplunkConfig.java b/runtime/src/main/java/io/quarkiverse/logging/splunk/SplunkConfig.java index dda2497..047da96 100644 --- a/runtime/src/main/java/io/quarkiverse/logging/splunk/SplunkConfig.java +++ b/runtime/src/main/java/io/quarkiverse/logging/splunk/SplunkConfig.java @@ -1,14 +1,10 @@ /* -Copyright (c) 2021 Amadeus s.a.s. -Contributor(s): Kevin Viet, Romain Quinio (Amadeus s.a.s.) +Copyright (c) 2023 Amadeus s.a.s. +Contributor(s): Kevin Viet, Romain Quinio, Yohann Puyhaubert (Amadeus s.a.s.) */ package io.quarkiverse.logging.splunk; -import java.time.Duration; -import java.util.HashMap; import java.util.Map; -import java.util.Optional; -import java.util.logging.Level; import io.quarkus.runtime.annotations.ConfigItem; import io.quarkus.runtime.annotations.ConfigPhase; @@ -21,205 +17,14 @@ public class SplunkConfig { /** - * Determine whether to enable the handler + * Configuration for Splunk HEC logging for the root level. */ - @ConfigItem(defaultValue = "true") - public boolean enabled; - - /** - * The splunk handler log level. By default, it is no more strict than the root handler level. - */ - @ConfigItem(defaultValue = "ALL") - public Level level; - - /** - * Splunk HEC endpoint base url. - *

- * With raw events, the endpoint targeted is /services/collector/raw. - * With flat or nested JSON events, the endpoint targeted is /services/collector/event/1.0. - */ - @ConfigItem(defaultValue = "https://localhost:8088/") - public String url; - - /** - * Disable TLS certificate validation with HEC endpoint - */ - @ConfigItem(defaultValue = "false") - public boolean disableCertificateValidation; - - /** - * The application token to authenticate with HEC, the token is mandatory if the extension is enabled - * https://docs.splunk.com/Documentation/Splunk/latest/Data/FormateventsforHTTPEventCollector#HEC_token - */ - @ConfigItem - public Optional token; - - /** - * The strategy to send events to HEC. - *

- * In sequential mode, there is only one HTTP connection to HEC and the order of events is preserved, but performance is - * lower. - * In parallel mode, event batches are sent asynchronously over multiple HTTP connections, and events with the same - * timestamp - * (that has 1 millisecond resolution) may be indexed out of order by Splunk. - */ - @ConfigItem(defaultValue = "sequential") - public SendMode sendMode; - - /** - * A GUID to identify an HEC client and guarantee isolation at HEC level in case of slow clients. - * https://docs.splunk.com/Documentation/Splunk/latest/Data/AboutHECIDXAck#About_channels_and_sending_data - */ - @ConfigItem - public Optional channel; - - /** - * Batching delay before sending a group of events. - * If 0, the events are sent immediately. - */ - @ConfigItem(defaultValue = "10s") - public Duration batchInterval; - - /** - * Maximum number of events in a batch. By default 10, if 0 no batching. - */ - @ConfigItem(defaultValue = "10") - public long batchSizeCount; - - /** - * Maximum total size in bytes of events in a batch. By default 10KB, if 0 no batching. - */ - @ConfigItem(defaultValue = "10") - public long batchSizeBytes; - - /** - * Maximum number of retries in case of I/O exceptions with HEC connection. - */ - @ConfigItem(defaultValue = "0") - public long maxRetries; - - /** - * The log format, defining which metadata are inlined inside the log main payload. - *

- * Specific metadata (hostname, category, thread name, ...), as well as MDC key/value map, can also be sent in a structured - * way. - */ - @ConfigItem(defaultValue = "%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] (%t) %s%e%n") - public String format; - - /** - * Whether to send the thrown exception message as a structured metadata of the log event (as opposed to %e in a formatted - * message, it does not include the exception name or stacktrace). - * Only applicable to 'nested' serialization. - */ - @ConfigItem(defaultValue = "false") - public boolean includeException; - - /** - * Whether to send the logger name as a structured metadata of the log event (equivalent of %c in a formatted message). - * Only applicable to 'nested' serialization. - */ - @ConfigItem(defaultValue = "false") - public boolean includeLoggerName; - - /** - * Whether to send the thread name as a structured metadata of the log event (equivalent of %t in a formatted message). - * Only applicable to 'nested' serialization. - */ - @ConfigItem(defaultValue = "false") - public boolean includeThreadName; - - /** - * Overrides the host name metadata value. - */ - @ConfigItem(defaultValueDocumentation = "The equivalent of %h in a formatted message") - public Optional metadataHost; - - /** - * The source value to assign to the event data. For example, if you're sending data from an app you're developing, - * you could set this key to the name of the app. - * https://docs.splunk.com/Documentation/Splunk/latest/Data/FormateventsforHTTPEventCollector#Event_metadata - */ - @ConfigItem - public Optional metadataSource; - - /** - * The optional format of the events, to enable some parsing on Splunk side. - * https://docs.splunk.com/Documentation/Splunk/latest/Data/FormateventsforHTTPEventCollector#Event_metadata - *

- * A given source type may have indexed fields extraction enabled, which is the case of the built-in _json used for nested - * serialization. - */ - @ConfigItem(defaultValueDocumentation = "_json for nested serialization, not set otherwise") - public Optional metadataSourceType; - - /** - * The optional name of the index by which the event data is to be stored. If set, it must be within the - * list of allowed indexes of the token (if it has the indexes parameter set). - * https://docs.splunk.com/Documentation/Splunk/latest/Data/FormateventsforHTTPEventCollector#Event_metadata - */ - @ConfigItem - public Optional metadataIndex; - - /** - * Optional static key/value pairs to populate the "fields" key of event metadata. This isn't - * applicable to raw serialization. - * https://docs.splunk.com/Documentation/Splunk/latest/Data/FormateventsforHTTPEventCollector#Event_metadata - */ - @ConfigItem - public Map metadataFields = new HashMap<>(); - - /** - * The name of the key used to convey the severity / log level in the metadata fields. - * Only applicable to 'flat' serialization. - * With 'nested' serialization, there is already a 'severity' field. - */ - @ConfigItem(defaultValue = "severity") - public String metadataSeverityFieldName; - - /** - * Determines whether the events are sent in raw mode. In case the raw event (i.e. the actual log message) - * is not a JSON object you need to explicitly set a source type or Splunk will reject the event (the - * default source type, _json, assumes that the incoming event can be parsed as JSON) - * - * @deprecated Use {@link #serialization} - */ - @Deprecated(forRemoval = true) - @ConfigItem(defaultValue = "false") - public boolean raw; - - /** - * The format of the payload. - *

- */ - @ConfigItem(defaultValue = "nested") - public SerializationFormat serialization; - - /** - * AsyncHandler config - *

- * This is independent of the SendMode, i.e. whether the HTTP client is async or not. - */ - AsyncConfig async; - + @ConfigItem(name = ConfigItem.PARENT) + public SplunkHandlerConfig config; /** - * Mirrors com.splunk.logging.HttpEventCollectorSender.SendMode + * Map of all the custom/named handlers configuration using Splunk implementation. */ - public enum SendMode { - SEQUENTIAL, - PARALLEL - } + @ConfigItem(name = ConfigItem.PARENT) + public Map namedHandlers; - public enum SerializationFormat { - RAW, - NESTED, - FLAT - } } diff --git a/runtime/src/main/java/io/quarkiverse/logging/splunk/SplunkHandlerConfig.java b/runtime/src/main/java/io/quarkiverse/logging/splunk/SplunkHandlerConfig.java new file mode 100644 index 0000000..c29eaf2 --- /dev/null +++ b/runtime/src/main/java/io/quarkiverse/logging/splunk/SplunkHandlerConfig.java @@ -0,0 +1,225 @@ +/* +Copyright (c) 2023 Amadeus s.a.s. +Contributor(s): Kevin Viet, Romain Quinio, Yohann Puyhaubert (Amadeus s.a.s.) + */ +package io.quarkiverse.logging.splunk; + +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.logging.Level; + +import io.quarkus.runtime.annotations.ConfigGroup; +import io.quarkus.runtime.annotations.ConfigItem; + +/** + * The configuration of the Splunk root or any Splunk named handler. + */ +@ConfigGroup +public class SplunkHandlerConfig { + /** + * Determine whether to enable the handler + */ + @ConfigItem(defaultValue = "true") + public boolean enabled = true; + + /** + * The splunk handler log level. By default, it is no more strict than the root handler level. + */ + @ConfigItem(defaultValue = "ALL") + public Level level = Level.ALL; + + /** + * Splunk HEC endpoint base url. + *

+ * With raw events, the endpoint targeted is /services/collector/raw. + * With flat or nested JSON events, the endpoint targeted is /services/collector/event/1.0. + */ + @ConfigItem(defaultValue = "https://localhost:8088/") + public String url = "https://localhost:8088/"; + + /** + * Disable TLS certificate validation with HEC endpoint + */ + @ConfigItem(defaultValue = "false") + public boolean disableCertificateValidation = false; + + /** + * The application token to authenticate with HEC, the token is mandatory if the extension is enabled + * https://docs.splunk.com/Documentation/Splunk/latest/Data/FormateventsforHTTPEventCollector#HEC_token + */ + @ConfigItem + public Optional token; + + /** + * The strategy to send events to HEC. + *

+ * In sequential mode, there is only one HTTP connection to HEC and the order of events is preserved, but performance is + * lower. + * In parallel mode, event batches are sent asynchronously over multiple HTTP connections, and events with the same + * timestamp + * (that has 1 millisecond resolution) may be indexed out of order by Splunk. + */ + @ConfigItem(defaultValue = "sequential") + public SendMode sendMode = SendMode.SEQUENTIAL; + + /** + * A GUID to identify an HEC client and guarantee isolation at HEC level in case of slow clients. + * https://docs.splunk.com/Documentation/Splunk/latest/Data/AboutHECIDXAck#About_channels_and_sending_data + */ + @ConfigItem + public Optional channel; + + /** + * Batching delay before sending a group of events. + * If 0, the events are sent immediately. + */ + @ConfigItem(defaultValue = "10s") + public Duration batchInterval = Duration.ofSeconds(10); + + /** + * Maximum number of events in a batch. By default 10, if 0 no batching. + */ + @ConfigItem(defaultValue = "10") + public long batchSizeCount = 10; + + /** + * Maximum total size in bytes of events in a batch. By default 10KB, if 0 no batching. + */ + @ConfigItem(defaultValue = "10") + public long batchSizeBytes = 10; + + /** + * Maximum number of retries in case of I/O exceptions with HEC connection. + */ + @ConfigItem(defaultValue = "0") + public long maxRetries = 0; + + /** + * The log format, defining which metadata are inlined inside the log main payload. + *

+ * Specific metadata (hostname, category, thread name, ...), as well as MDC key/value map, can also be sent in a structured + * way. + */ + @ConfigItem(defaultValue = "%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] (%t) %s%e%n") + public String format = "%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] (%t) %s%e%n"; + + /** + * Whether to send the thrown exception message as a structured metadata of the log event (as opposed to %e in a formatted + * message, it does not include the exception name or stacktrace). + * Only applicable to 'nested' serialization. + */ + @ConfigItem(defaultValue = "false") + public boolean includeException = false; + + /** + * Whether to send the logger name as a structured metadata of the log event (equivalent of %c in a formatted message). + * Only applicable to 'nested' serialization. + */ + @ConfigItem(defaultValue = "false") + public boolean includeLoggerName = false; + + /** + * Whether to send the thread name as a structured metadata of the log event (equivalent of %t in a formatted message). + * Only applicable to 'nested' serialization. + */ + @ConfigItem(defaultValue = "false") + public boolean includeThreadName = false; + + /** + * Overrides the host name metadata value. + */ + @ConfigItem(defaultValueDocumentation = "The equivalent of %h in a formatted message") + public Optional metadataHost; + + /** + * The source value to assign to the event data. For example, if you're sending data from an app you're developing, + * you could set this key to the name of the app. + * https://docs.splunk.com/Documentation/Splunk/latest/Data/FormateventsforHTTPEventCollector#Event_metadata + */ + @ConfigItem + public Optional metadataSource; + + /** + * The optional format of the events, to enable some parsing on Splunk side. + * https://docs.splunk.com/Documentation/Splunk/latest/Data/FormateventsforHTTPEventCollector#Event_metadata + *

+ * A given source type may have indexed fields extraction enabled, which is the case of the built-in _json used for nested + * serialization. + */ + @ConfigItem(defaultValueDocumentation = "_json for nested serialization, not set otherwise") + public Optional metadataSourceType; + + /** + * The optional name of the index by which the event data is to be stored. If set, it must be within the + * list of allowed indexes of the token (if it has the indexes parameter set). + * https://docs.splunk.com/Documentation/Splunk/latest/Data/FormateventsforHTTPEventCollector#Event_metadata + */ + @ConfigItem + public Optional metadataIndex; + + /** + * Optional static key/value pairs to populate the "fields" key of event metadata. This isn't + * applicable to raw serialization. + * https://docs.splunk.com/Documentation/Splunk/latest/Data/FormateventsforHTTPEventCollector#Event_metadata + */ + @ConfigItem + public Map metadataFields = new HashMap<>(); + + /** + * The name of the key used to convey the severity / log level in the metadata fields. + * Only applicable to 'flat' serialization. + * With 'nested' serialization, there is already a 'severity' field. + */ + @ConfigItem(defaultValue = "severity") + public String metadataSeverityFieldName = "severity"; + + /** + * Determines whether the events are sent in raw mode. In case the raw event (i.e. the actual log message) + * is not a JSON object you need to explicitly set a source type or Splunk will reject the event (the + * default source type, _json, assumes that the incoming event can be parsed as JSON) + * + * @deprecated Use {@link #serialization} + */ + @Deprecated(forRemoval = true) + @ConfigItem(defaultValue = "false") + public boolean raw = false; + + /** + * The format of the payload. + *

+ */ + @ConfigItem(defaultValue = "nested") + public SerializationFormat serialization = SerializationFormat.NESTED; + + /** + * AsyncHandler config + *

+ * This is independent of the SendMode, i.e. whether the HTTP client is async or not. + */ + @ConfigItem + AsyncConfig async; + + /** + * Mirrors com.splunk.logging.HttpEventCollectorSender.SendMode + */ + public enum SendMode { + SEQUENTIAL, + PARALLEL + } + + public enum SerializationFormat { + RAW, + NESTED, + FLAT + } + +} diff --git a/runtime/src/main/java/io/quarkiverse/logging/splunk/SplunkLogHandlerRecorder.java b/runtime/src/main/java/io/quarkiverse/logging/splunk/SplunkLogHandlerRecorder.java index a0b9ab1..d54b628 100644 --- a/runtime/src/main/java/io/quarkiverse/logging/splunk/SplunkLogHandlerRecorder.java +++ b/runtime/src/main/java/io/quarkiverse/logging/splunk/SplunkLogHandlerRecorder.java @@ -1,16 +1,18 @@ /* -Copyright (c) 2021 Amadeus s.a.s. -Contributor(s): Kevin Viet, Romain Quinio (Amadeus s.a.s.) +Copyright (c) 2023 Amadeus s.a.s. +Contributor(s): Kevin Viet, Romain Quinio, Yohann Puyhaubert (Amadeus s.a.s.) */ package io.quarkiverse.logging.splunk; import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.logging.Handler; import java.util.logging.Level; +import java.util.stream.Collectors; import org.jboss.logmanager.formatters.PatternFormatter; import org.jboss.logmanager.handlers.AsyncHandler; @@ -25,36 +27,66 @@ @Recorder public class SplunkLogHandlerRecorder { - public RuntimeValue> initializeHandler(SplunkConfig config) { - if (!config.enabled) { + public RuntimeValue> initializeHandler(SplunkConfig rootConfig) { + if (!rootConfig.config.enabled) { return new RuntimeValue<>(Optional.empty()); } + + Handler handler = buildHandlerFromConfig(rootConfig.config); + return new RuntimeValue<>(Optional.of(handler)); + } + + public RuntimeValue> initializeHandlers(SplunkConfig rootConfig) { + if (rootConfig.namedHandlers == null || rootConfig.namedHandlers.isEmpty()) { + return new RuntimeValue<>(Collections.EMPTY_MAP); + } + + Map namedHandlers = rootConfig.namedHandlers + .entrySet() + .stream() + .filter(e -> e.getValue().enabled) + .collect(Collectors.toMap( + e -> e.getKey(), + e -> buildHandlerFromConfig(e.getValue()))); + + return new RuntimeValue<>(namedHandlers); + } + + private Handler buildHandlerFromConfig(SplunkHandlerConfig config) { if (!config.token.isPresent()) { throw new IllegalArgumentException("The property quarkus.log.handler.splunk.token is mandatory"); } HttpEventCollectorSender sender = createSender(config); SplunkLogHandler splunkLogHandler = createSplunkLogHandler(sender, config); splunkLogHandler.setLevel(config.level); - splunkLogHandler.setFormatter(new PatternFormatter(config.format)); + splunkLogHandler.setFormatter( + new PatternFormatter(config.format)); - Handler handler = config.async.enable ? createAsyncHandler(config.async, config.level, splunkLogHandler) + Handler handler = config.async.enable + ? createAsyncHandler(config.async, + config.level, splunkLogHandler) : splunkLogHandler; - return new RuntimeValue<>(Optional.of(handler)); + return handler; } - static HttpEventCollectorSender createSender(SplunkConfig config) { + static HttpEventCollectorSender createSender(SplunkHandlerConfig config) { HttpEventCollectorErrorHandler.onError(new SplunkErrorCallback()); String type = ""; - if (config.raw || config.serialization == SplunkConfig.SerializationFormat.RAW) { + if (config.raw || config.serialization == SplunkHandlerConfig.SerializationFormat.RAW) { type = "Raw"; } // Timeout settings is not used and passing a null is correct regarding the code HttpEventCollectorSender sender = new HttpEventCollectorSender( - config.url, config.token.get(), config.channel.orElse(""), type, + config.url, + config.token.get(), + config.channel.orElse(""), + type, config.batchInterval.getSeconds(), - config.batchSizeCount, config.batchSizeBytes, - config.sendMode.name().toLowerCase(), buildMetadata(config), null); - if (config.serialization == SplunkConfig.SerializationFormat.FLAT) { + config.batchSizeCount, + config.batchSizeBytes, + config.sendMode.name().toLowerCase(), + buildMetadata(config), null); + if (config.serialization == SplunkHandlerConfig.SerializationFormat.FLAT) { SplunkFlatEventSerializer serializer = new SplunkFlatEventSerializer(config.metadataSeverityFieldName); sender.setEventHeaderSerializer(serializer); sender.setEventBodySerializer(serializer); @@ -62,7 +94,7 @@ static HttpEventCollectorSender createSender(SplunkConfig config) { return sender; } - static Map buildMetadata(SplunkConfig config) { + static Map buildMetadata(SplunkHandlerConfig config) { HashMap metadata = new HashMap<>(); // Note: sending an empty index is invalid, the index property has to be omitted config.metadataIndex.ifPresent(s -> metadata.put(MetadataTags.INDEX, s)); @@ -76,7 +108,7 @@ static Map buildMetadata(SplunkConfig config) { if (config.metadataSourceType.isPresent()) { metadata.put(MetadataTags.SOURCETYPE, config.metadataSourceType.get()); - } else if (config.serialization == SplunkConfig.SerializationFormat.NESTED) { + } else if (config.serialization == SplunkHandlerConfig.SerializationFormat.NESTED) { metadata.put(MetadataTags.SOURCETYPE, "_json"); } @@ -84,8 +116,12 @@ static Map buildMetadata(SplunkConfig config) { return metadata; } - private SplunkLogHandler createSplunkLogHandler(HttpEventCollectorSender sender, SplunkConfig config) { - return new SplunkLogHandler(sender, config.includeException, config.includeLoggerName, config.includeThreadName, + private SplunkLogHandler createSplunkLogHandler(HttpEventCollectorSender sender, + SplunkHandlerConfig config) { + return new SplunkLogHandler(sender, + config.includeException, + config.includeLoggerName, + config.includeThreadName, config.disableCertificateValidation, config.maxRetries); }