The official Java SDK for LogFlux. Send logs, metrics, traces, events, and audit entries directly to the LogFlux cloud with end-to-end encryption from Java and Kotlin applications. The server never sees your plaintext data.
GitHub Repository ยท Release Notes
Key Features
- End-to-end encryption – AES-256-GCM with RSA key exchange
- 7 entry types – Log, Metric, Trace, Event, Audit, Telemetry, TelemetryManaged
- Multipart binary transport – 33% less overhead than JSON + base64
- Async by default – Background daemon threads with non-blocking queue
- Breadcrumbs – Automatic trail of recent events attached to error captures
- Distributed tracing – Spans, child spans, trace header propagation
- Scopes – Per-request context isolation
- Failsafe – SDK errors never crash your application
- Zero external dependencies – javax.crypto, java.net.http, java.util.zip
Installation
Gradle
1
| implementation 'io.logflux:logflux-java-sdk:3.0.1'
|
Maven
1
2
3
4
5
| <dependency>
<groupId>io.logflux</groupId>
<artifactId>logflux-java-sdk</artifactId>
<version>3.0.1</version>
</dependency>
|
Quick Start
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| import io.logflux.sdk.LogFlux;
import io.logflux.sdk.Options;
public class Main {
public static void main(String[] args) {
LogFlux.init(Options.builder("eu-lf_your_api_key")
.source("my-service")
.environment("production")
.release("1.2.3")
.build());
LogFlux.info("server started");
// Before process exit
LogFlux.flush(2000);
LogFlux.close();
}
}
|
Entry Types
Log (Type 1)
Standard application logs with 8 severity levels.
1
2
3
4
5
6
7
8
9
10
11
| LogFlux.debug("cache miss for key users:123");
LogFlux.info("request processed");
LogFlux.warn("deprecated API called");
LogFlux.error("database connection failed");
LogFlux.critical("out of memory");
// With attributes
LogFlux.log(LogLevel.ERROR, "query timeout", Map.of(
"db.host", "primary.db.internal",
"duration_ms", "5023"
));
|
Metric (Type 2)
Counters, gauges, and distributions.
1
2
3
4
5
6
7
8
| LogFlux.counter("http.requests.total", 1, Map.of(
"method", "GET",
"status", "200"
));
LogFlux.gauge("system.cpu.usage", 85.2, Map.of(
"host", "web-01"
));
|
Event (Type 4)
Discrete application events.
1
2
3
4
| LogFlux.event("user.signup", Map.of(
"user_id", "usr_987",
"plan", "starter"
));
|
Audit (Type 5)
Immutable audit trail with Object Lock storage (365-day retention).
1
2
3
| LogFlux.audit("record.deleted", "usr_456", "invoice", "inv_789", Map.of(
"reason", "customer_request"
));
|
Trace (Type 3)
Distributed tracing with span helpers.
1
2
3
4
5
6
7
| Span span = LogFlux.startSpan("http.server", "GET /api/users");
Span dbSpan = span.startChild("db.query", "SELECT * FROM users");
// ... query ...
dbSpan.end();
span.end();
|
Telemetry (Types 6 and 7)
Device and sensor data. Type 6 is end-to-end encrypted, type 7 is server-side encrypted.
Error Capture
Capture Java exceptions with automatic stack traces and breadcrumb trail.
1
2
3
4
5
6
7
8
9
10
11
| try {
database.query(sql);
} catch (Exception e) {
LogFlux.captureError(e);
// With extra context
LogFlux.captureError(e, Map.of(
"sql", sql,
"db.host", "primary"
));
}
|
Throwable chain unwrapping: if the exception has a cause chain, all causes are captured.
Breadcrumbs
Breadcrumbs record a trail of events leading up to an error. They are automatically added for log and event calls, and attached to captureError.
1
2
3
4
5
6
7
8
| LogFlux.info("loading config"); // auto breadcrumb
LogFlux.event("user.login", null); // auto breadcrumb
LogFlux.addBreadcrumb("http", "GET /api/users", Map.of(
"status", "200"
));
LogFlux.captureError(exception); // includes breadcrumb trail
|
Scopes
Per-request context isolation. Attributes set on a scope are merged into every entry.
1
2
3
4
5
6
7
8
9
10
11
| LogFlux.withScope(scope -> {
scope.setUser("usr_456");
scope.setRequest("GET", "/api/users", "req_abc123");
scope.setAttribute("tenant", "acme-corp");
scope.info("processing request");
if (error != null) {
scope.captureError(error);
}
});
|
Trace Context Propagation
Propagate trace context across services via HTTP headers.
1
2
3
4
5
6
7
8
| // Client: inject trace header
Span span = LogFlux.startSpan("http.client", "GET /api");
Map<String, String> headers = span.injectHeaders();
// Server: continue from incoming headers
Span span = LogFlux.continueFromHeaders(request.getHeaders(), "http.server", "GET /api");
// ... handle request ...
span.end();
|
Framework Integration
Spring Boot
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| import io.logflux.sdk.LogFlux;
import io.logflux.sdk.Options;
import io.logflux.sdk.Span;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.*;
@Component
public class LogFluxFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
Span span = LogFlux.startSpan("http.server",
request.getMethod() + " " + request.getRequestURI());
span.setAttribute("http.method", request.getMethod());
try {
chain.doFilter(req, res);
HttpServletResponse response = (HttpServletResponse) res;
span.setAttribute("http.status_code", String.valueOf(response.getStatus()));
} catch (Exception e) {
span.setError(e);
throw e;
} finally {
span.end();
}
}
}
|
Android
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| import io.logflux.sdk.LogFlux;
import io.logflux.sdk.Options;
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
LogFlux.init(Options.builder("eu-lf_your_api_key")
.source("my-android-app")
.environment("production")
.release(BuildConfig.VERSION_NAME)
.build());
// Capture uncaught exceptions
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
LogFlux.captureError(throwable);
LogFlux.flush(2000);
});
}
}
|
Configuration
Options (Builder Pattern)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| Options options = Options.builder("eu-lf_your_api_key")
.source("my-service")
.environment("production")
.release("1.2.3")
.queueSize(1000)
.batchSize(100)
.flushInterval(5000)
.workerCount(2)
.maxRetries(3)
.sampleRate(1.0)
.maxBreadcrumbs(100)
.failsafe(true)
.enableCompression(true)
.build();
|
Environment Variables
1
| LogFlux.initFromEnv("my-node");
|
Reads LOGFLUX_API_KEY, LOGFLUX_ENVIRONMENT, LOGFLUX_NODE, LOGFLUX_QUEUE_SIZE, LOGFLUX_BATCH_SIZE, LOGFLUX_KEY_PERSISTENCE, LOGFLUX_KEY_PERSISTENCE_PATH, LOGFLUX_KEY_ROTATION_DAYS, etc.
Key Persistence
The SDK persists AES encryption keys to disk by default, reusing them across restarts instead of performing a new handshake each time. This reduces key proliferation in the database and speeds up initialization.
| Option | Type | Default | Description |
|---|
.keyPersistence(boolean) | boolean | true | Enable/disable key persistence |
.keyPersistencePath(String) | String | ~/.logflux/sessions/ | Custom directory for session files |
.keyRotationDays(long) | long | 0 (never) | Rotate key after N days |
Session files are stored at ~/.logflux/sessions/<hash>.json with 0600 permissions. If the cached key is rejected by the server (401/403), the SDK automatically re-handshakes and saves the new key.
1
2
3
4
5
6
7
8
9
10
| // Disable persistence (for ephemeral containers)
LogFlux.init(Options.builder("eu-lf_your_key")
.keyPersistence(false)
.build());
// Custom path and 30-day rotation
LogFlux.init(Options.builder("eu-lf_your_key")
.keyPersistencePath("/var/lib/myapp/logflux/")
.keyRotationDays(30)
.build());
|
On Android, keys are stored in the Android Keystore instead of the filesystem. No additional configuration is required.
BeforeSend Hooks
Filter or modify entries before they are sent. Return null to drop.
1
2
3
4
5
6
7
8
9
10
| Options options = Options.builder("eu-lf_...")
.beforeSendLog(log -> {
if ((int) log.get("level") == 8) return null; // drop debug
return log;
})
.beforeSendAudit(audit -> {
((Map<String, String>) audit.get("attributes")).remove("ip");
return audit;
})
.build();
|
Sampling
1
| Options.builder("...").sampleRate(0.1).build(); // send 10%
|
Audit entries (type 5) are never sampled.
Security
- Zero-knowledge: All payloads encrypted client-side with AES-256-GCM
- RSA key exchange: AES keys negotiated via RSA-2048 OAEP handshake
- Key zeroing: AES keys cleared from memory on
close() - Bounded reads: All HTTP responses size-limited
- Failsafe: SDK errors never crash the host application
Requirements
- Java 11 or later
- LogFlux account with API key
License
Elastic License 2.0 (ELv2) – free for all use except offering as a hosted or managed service to third parties.
Support
Disclaimer
The Java logo and trademarks are the property of Oracle Corporation. LogFlux is not affiliated with, endorsed by, or sponsored by Oracle Corporation. The Java logo is used solely for identification purposes to indicate compatibility and integration capabilities.