Configuration
import ai.auralog.Auralog;import ai.auralog.AuralogConfig;import java.time.Duration;
Auralog.init(AuralogConfig.builder() .apiKey("aura_your_api_key") .environment("production") // default "production" .endpoint("https://ingest.auralog.ai") // default .flushInterval(Duration.ofSeconds(5)) // default .captureErrors(true) // default .build());Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
apiKey | String | required | Your Auralog ingest key. Copy it from the startup modal or create another in project settings. |
environment | String | "production" | e.g. "production", "staging", "dev". |
endpoint | String | https://ingest.auralog.ai | Ingest endpoint override. |
flushInterval | Duration | Duration.ofSeconds(5) | Time between batched flushes. Errors flush immediately regardless. |
captureErrors | boolean | true | If true, uncaught exceptions are auto-reported via Thread.UncaughtExceptionHandler. |
globalMetadata | Supplier<Map<String, Object>> or Map<String, Object> | null | Baseline metadata merged into every log entry — including auralog-slf4j bridge entries and uncaught-exception captures. See Global metadata below. |
Global metadata
Section titled “Global metadata”Available since ai.auralog:auralog-core 0.2.0.
Use globalMetadata to attach session-scoped fields — userId, organisation id, feature-flag snapshot, build SHA — to every log entry without threading them through every call site. The merged metadata flows through direct API calls and entries emitted via the auralog-slf4j bridge and uncaught-exception captures, so attribution is consistent across all three.
Static form
Section titled “Static form”If the value never changes for the lifetime of the SDK instance, pass a Map:
Auralog.init(AuralogConfig.builder() .apiKey("aura_...") .globalMetadata(Map.of("app", "checkout-service", "region", "us-east-1")) .build());This is a convenience overload that wraps the map as () -> map internally; the supplier form below is the load-bearing API.
Supplier form
Section titled “Supplier form”For values that change at runtime — the canonical case being a per-request ScopedValue or ThreadLocal user — pass a Supplier<Map<String, Object>>. It is invoked at every log emission, so it always reflects current host state:
import java.util.Map;import java.util.function.Supplier;
Auralog.init(AuralogConfig.builder() .apiKey("aura_...") .globalMetadata((Supplier<Map<String, Object>>) () -> Map.of("userId", CurrentUser.get())) .build());Now every direct call, every entry routed through auralog-slf4j, and every uncaught exception carries userId — searchable in the dashboard via userId:abc and visible to your AI provider during analysis.
Merge semantics
Section titled “Merge semantics”When a per-call metadata argument is also provided, the two are shallow-merged with per-call winning on collision:
// globalMetadata: () -> Map.of("userId", "u_42", "region", "us")auralog.info("impersonating session", Map.of("userId", "u_99"));// final metadata: {userId=u_99, region=us}This lets a specific log line legitimately reference a different user (impersonation, admin actions) without mutating global state.
Failure modes
Section titled “Failure modes”The SDK never crashes the host. If the supplier:
- throws — the entry ships without
globalMetadata(per-call metadata is preserved). A single warning fires perLoggerinstance viaSystem.LoggeratWARNING(logger nameai.auralog.internal); subsequent failures of the same kind are silent. - returns a
CompletionStage/CompletableFuture— same. Async suppliers are not awaited; cache async state in something synchronously accessible (ScopedValue,ThreadLocal). - returns a value the JSON encoder cannot serialize (circular refs, opaque types) — same. The entry still ships with just per-call metadata.
SLF4J MDC
Section titled “SLF4J MDC”SLF4J MDC is not auto-merged into globalMetadata. Today the bridge installs a NOPMDCAdapter so MDC is a no-op, but even when MDC populates we keep it separate from globalMetadata to avoid mental-model overlap. Auto-MDC-merge is a candidate for a future opt-in flag if there’s demand.
Performance
Section titled “Performance”The supplier runs on every log emission. Keep it O(1) — read from a ScopedValue / ThreadLocal / cached object, not a database or remote call.
Builder pattern
Section titled “Builder pattern”AuralogConfig is immutable; build with AuralogConfig.builder():
AuralogConfig config = AuralogConfig.builder() .apiKey("k") .environment("staging") .build();Auralog.init(config);apiKey is the only required field. Everything else has sensible defaults.
Idempotent
Section titled “Idempotent”Calling Auralog.init(...) again replaces the previous configuration and flushes the prior transport. Useful for rotating API keys without restarting the JVM.
Reading from the environment
Section titled “Reading from the environment”Auralog.init(AuralogConfig.builder() .apiKey(System.getenv("AURALOG_API_KEY")) .environment(System.getenv().getOrDefault("APP_ENV", "dev")) .build());