Java error tracking installation
Contents
This guide covers the server-side Java SDK (
posthog-server), for JVM server applications. For Android apps, see the Android error tracking installation guide.
- 1
Install the Java SDK
RequiredInstall the PostHog Java SDK with Gradle or Maven.
Gradle
build.gradleMaven
pom.xmlSource context not yet supportedThe Java SDK captures stack traces with file names, line numbers, and function names, but does not yet support source context (displaying the surrounding lines of code in the error tracking UI). Symbolication of obfuscated builds is supported through ProGuard/R8 mappings — see Deobfuscate stack traces below.
- 2
Initialize the client
RequiredBuild a client once during application startup and reuse it. It uses an internal queue to send events asynchronously.
JavaYou can find your project token and instance address in your project settings.
- 3
Capture exceptions
RequiredUse
captureExceptionto send an exception to PostHog as an$exceptionevent. The exception type, message, and full stack trace are captured, along with the cause chain and any suppressed exceptions.JavaBy default, exceptions are captured personlessly: the SDK generates a UUID and sets
$process_person_profiletofalse, so no person profile is created.Associate a person
Pass a distinct ID to link the exception to a person:
JavaAdd properties
Pass extra properties to include with the event. You can also override reserved exception properties such as
$exception_level(severity) and$exception_fingerprint(issue grouping) here:JavaFor finer control over groups, feature flags, or the timestamp, pass
PostHogCaptureOptionsinstead of a plain map:Java - 4
Associate exceptions with users via request context
RecommendedInside a web request, you usually don't want to pass a distinct ID to every
captureExceptioncall. Use request context to set the distinct ID (and session ID) once per request, so every capture on that thread — including exceptions — is attributed to the right person and associated with session replay.JavaSee the request context documentation for how to build the context from incoming headers.
- 5
Configure in-app frames
OptionalPostHog classifies each stack frame as either in-app (your code) or library code, which controls how issues are grouped and displayed. This is configured on the client through
inAppExcludesandinAppIncludes.Out of the box, the SDK ships a sensible default
inAppExcludeslist that marks common JVM and framework packages as library code, so it works with zero configuration. The defaults are:Any frame not matched by
inAppExcludesis considered in-app. To narrow this down to just your own packages, setinAppIncludes:JavaExcludes always win over includes. Assigning your own
inAppExcludeslist replaces the defaults rather than adding to them, so start from the default set above if you only want to add entries. - 6
Capture uncaught exceptions
OptionalTo automatically capture exceptions that crash a thread, opt in with
captureUncaughtExceptions. On setup, the SDK installs a JVM-wideThread.defaultUncaughtExceptionHandlerthat captures the crashing exception (marked as fatal, unhandled), flushes, and then delegates to any handler that was previously registered. The handler is removed again when you callposthog.close().JavaSet a low flushAt for the crash pathThe handler captures the exception and then calls
flush(), which drains the queue synchronously on the crashing thread. The capture itself is enqueued asynchronously, though, so it may not have landed in the queue by the timeflush()runs. The background flush doesn't reliably cover this either: it only sends onceflushAtevents (default100) have accumulated, or on the flush interval (default every5seconds), neither of which is likely to fire before the process exits. If you rely on capturing the crash, setflushAt(1)so the enqueue itself triggers a send — at the cost of batching for every other event on that client. Delivery under an immediate hard exit is best-effort. - 7
Capture logged errors with Logback
OptionalIf your application uses Logback, you can automatically capture logged errors as exceptions with the PostHog appender, without adding
captureExceptioncalls throughout your code.Add the appender module:
build.gradlepom.xmlRegister the appender in your
logback.xml:logback.xmlThen register your PostHog client with the appender once during startup, before the logging you want to capture. Registration is process-wide, so events logged before a client is registered are dropped.
JavaAlternatively, let the appender create and own its own client from
logback.xmlby settingapiKey(and optionallyhost) instead of callingsetPostHog:logback.xmlA few things to know about what the appender captures:
- Only log events at or above
minimumCaptureLevel(defaultERROR) that carry aThrowableare captured. Message-only logs are skipped. - The log level is mapped onto
$exception_level(ERROR→error,WARN→warning). - Events from the SDK's own loggers (
com.posthog.*) are always skipped, so the SDK can't recursively report its own errors. - Because capture runs through the SDK's
captureException, request-context distinct-id resolution and in-app frame configuration apply automatically. - If the same exception is both logged and reaches the uncaught-exception handler, it's captured only once.
- Only log events at or above
- 8
Deobfuscate stack traces
OptionalIf you obfuscate your JVM builds with ProGuard or R8, upload the mapping file to PostHog so stack traces are deobfuscated in the error tracking UI.
Set
releaseIdentifieron the client. This stamps every captured stack frame with amap_idthat ties it to the uploaded mapping:JavaThen upload the mapping file with the PostHog CLI, using the same identifier for
--map-id:TerminalThe
--map-idvalue must match thereleaseIdentifierset at runtime for that build. This is only needed for obfuscated builds — non-obfuscated JVM apps produce readable stack traces without any upload. - 9
Verify error tracking
RecommendedTrigger a test exception to confirm events are being sent to PostHog. You should see it appear in the error tracking issues view.
Java
What's not supported yet
- Source context. Captured frames include file names, line numbers, and function names, but the surrounding lines of source code are not shown in the UI.
- Framework middleware. There is no built-in Spring (or other framework) middleware for automatic capture yet. Use the Logback appender, the uncaught-exception handler, and manual
captureExceptioncalls, wiring request context in your framework integration.