A batching HTTP log shipper for Java: a fast, drop-in replacement for Log4j2's stock
HttpAppender, which sends one synchronous HTTP request per log event. Current release:
0.3.0 (CHANGELOG).
On this page: Why · Supported vendors · Quick start · Benchmarks · Documentation · Project
- Log4j2's default
HttpAppenderdoes one blocking request per event, so the logging call blocks the application thread. - At volume, per-request overhead (TLS, headers, round-trip latency) dominates.
- Vendor intake APIs are all designed for bulk ingest, and this library uses them: events are enqueued (non-blocking) and shipped in compressed batches by background threads.
Local test: 5,000 log events sent to a mock intake on the same machine. The intake takes 5 ms to answer each request.
Stock HttpAppender style |
Batch appender | |
|---|---|---|
| How it sends | One request per event, waits for each answer | 500 events per request, from a background thread |
| HTTP requests | 5,000 | 10 (500× fewer) |
| Time to deliver all 5,000 events | 32.6 s | 0.08 s (about 400× faster) |
| Your thread while logging | Blocked on every request | Continues immediately |
This is the best case by design: the mock answers in exactly 5 ms whatever the batch size. On real networks the gain depends on how far away the intake is; see the CloudHub results. Run it yourself.
Each vendor page is self-contained: setup, a copy-paste configuration, what gets sent, how to verify delivery, troubleshooting and, where measured, its CloudHub benchmark. Every page links the same option list, docs/configuration.md.
In the table, Test 3 is the 5-minute sustained run on 0.1 vCore workers in Sydney, on CloudHub 1.0 (CH1) and CloudHub 2.0 (CH2).
| Vendor page | Sample Mule project | Test 3 batch ÷ stock req/s, CH1 / CH2 | Batch logs delivered, CH1 / CH2 |
|---|---|---|---|
| Datadog | batch · stock | 53.5× / 28.5× | 100.0% / 100.0% |
| New Relic | batch · stock | 110.8× / 59.5× | 44.5% / 77.3% ¹ |
| Elasticsearch (ELK / Elastic Cloud) | batch · stock | 139.5× / 48.6× | 100.0% / 100.0% |
| Dynatrace | batch · stock | 6.5× / 4.4× ² | 100.0% / 100.0% |
| Splunk HEC | none yet; Java example config | not measured | — |
| Generic HTTP (any HTTP log intake) | none yet; Java example config | not measured | — |
CH1 and CH2 run at different concurrency, so compare within a column, never CH1 against CH2.
- New Relic has only US and EU intake; these Sydney workers ship to the US, and the spill backlog was still draining when the next test's restart replaced the worker. New Relic batch delivered 100% in Test 4.
- A single-record POST to the in-region Dynatrace intake is quick, so the stock appender is penalised far less there; batch req/s matches the other vendors.
-
Build and install the artifacts into your local Maven repository (JDK 17+, Maven 3.8+; see docs/building.md):
mvn clean install -DskipTests
-
Add the dependency.
batch-http-log4j2brings inbatch-http-core, which has no runtime dependencies beyond the JDK.<dependency> <groupId>com.mulesoft.support.batchhttp</groupId> <artifactId>batch-http-log4j2</artifactId> <version>0.3.0</version> </dependency>
-
Configure
log4j2.xml. A minimal Datadog example:<Configuration status="WARN" packages="com.mulesoft.support.batchhttp.log4j2"> <Appenders> <BatchHttp name="datadog" vendor="datadog" apiKey="${env:DD_API_KEY}" service="orders-api" source="java"> <PatternLayout pattern="%m"/> </BatchHttp> </Appenders> <Loggers> <!-- additivity="false" keeps these events from also bubbling to the root, so they ship to the appender exactly once. --> <Logger name="com.example.orders" level="INFO" additivity="false"> <AppenderRef ref="datadog"/> </Logger> <Root level="INFO"> <AppenderRef ref="datadog"/> </Root> </Loggers> </Configuration>
-
Pick your vendor page from Supported vendors for the required options, recommended production settings and a ready-to-run Mule sample. Every option, its default and the vendors it applies to: docs/configuration.md. Using it from Mule: docs/mule.md.
Important
packages is required wherever the library is on the application classloader rather than
the Log4j2 boot classpath (every Mule 4 / CloudHub app). Without it Log4j2 ignores
<BatchHttp> with a startup warning, and nothing ships.
Two more rules for log4j2.xml:
- Secrets only through Log4j2 lookups (
${env:...},${sys:...}). Mule${...}placeholders andsecure::properties do not resolve inlog4j2.xml; see Injecting secrets. - Sync or async loggers both work.
<BatchHttp>already enqueues without blocking, so plain<Root>/<Logger>never block your threads on network I/O.<AsyncRoot>/<AsyncLogger>need the LMAX Disruptor (com.lmax:disruptor) on the classpath: the Mule runtime provides it, a standalone Java app must add it.
Four batch/stock pairs of the same Mule app (one per vendor, sixteen apps across CloudHub 1.0 and
2.0) were load-tested with oha on 0.1 vCore workers in Sydney,
with engine 0.2.0, disk spill on, and the logs delivered counted at each vendor.
Over the 5-minute run the batch appender sustained 6.5–139.5× the stock appender's request rate on CloudHub 1.0 and 4.4–59.5× on CloudHub 2.0. The batch apps delivered 100% of their logs to Datadog, Elasticsearch and Dynatrace in every test; the stock apps lost logs at all four vendors on CloudHub 1.0. Datadog, New Relic and Elasticsearch were measured on 2026-10-12, Dynatrace on 2026-10-13. These are single runs: read them as directional.
The chart compares sustained request throughput, batch against stock, per vendor on each plane; look at the gap within each vendor group (smallest for Dynatrace; see note 2 under the vendor table).
Method, caveats and all four tests: docs/benchmark-results.md. Styled standalone report: docs/index.html (open it locally after cloning). To reproduce: docs/benchmark-runbook.md.
Start at the documentation index: every page, grouped by task, with what it covers.
Status: proof-of-concept (0.3.0), validated by unit + end-to-end tests (mvn test) and the
benchmarks above. The roadmap lists what a production v1 would add; release
history is in the CHANGELOG.
- Governance: published but not supported. The code is shared because it may be useful, but contributions are not actively solicited and there is no support commitment. Bug reports, questions and ideas belong on the repository's GitHub Issues page, not with the author directly; see CONTRIBUTING.md.
- Security: report vulnerabilities as described in SECURITY.md, via Salesforce's responsible disclosure process, not as a public GitHub issue.
- License: Apache License, Version 2.0 (LICENSE.txt). Every source and
configuration file of the library carries the
SPDX-License-Identifier: Apache-2.0header; the samples underdemo/are exempt from the header. The license covers the files in this repository only. The Mule demos run on the Mule runtime and use MuleSoft connectors, which are not part of this repository and are licensed separately by MuleSoft. - Code of Conduct: participation is governed by the Salesforce Open Source CODE_OF_CONDUCT.md.
- Author: created and maintained by Vitalii Mykytenko, Senior Principal Technical Support Engineer, MuleSoft Signature Success Support, Australia.
Docs index · Configuration · Benchmarks · Roadmap · Changelog
