Launch Week Day 1 - Error Tracking
A brand new Error Tracking experience. Smarter grouping, manual merging, a better UI, and more.
Today we are shipping a brand new error tracking experience. Grouping is smarter, you can merge and unmerge issues by hand for the first time, the issue page is built for real triage, and context finally fits how errors are actually debugged.
Why we rebuilt it
Error tracking worked, but three problems kept showing up in support and in our own projects.
-
Poor grouping
Automatic grouping missed obvious duplicates. When it grouped things wrong, there was no way to merge issues by hand. You were stuck with duplicate groups.
-
Datasource limits on context
Metrics and error context were coupled in ways that did not match how people debug. People hit datasource boundaries when they only wanted richer error context.
-
A detail page that did not scale
Long issue pages with a sidebar sheet on mobile were hard to scan. Stack traces, events, and metadata fought for the same scroll area.
Smarter grouping
We normalize more noise before we hash an issue. The goal is simple. The same logical failure should land in one group even when UUIDs, versions, or line numbers change.
We hash the error type and up to 80 stack lines. Each part is normalized first.
Tokenize and normalize volatile identifiers
Variable fragments are replaced with stable placeholders.
| Pattern | Placeholder |
|---|---|
| UUIDs | <uuid> |
| Hex values (e.g. 0xdeadbeef) | <hex> |
| Long hash-like strings | <hash> |
| Quoted strings (double, single, or backtick) | <quoted> |
| JAR coordinates | <jar> |
| Numbers | <num> |
Reduce Java frame noise
A frame like:
(Plugin.java:42)
becomes:
(Plugin.java)
The same bug at a nearby line no longer opens a second group.
Skip Java internal frames in the group hash
When we build the stack portion of the hash, we walk up to 80 lines but skip frames that are JDK or platform internals.
A frame counts as internal when it starts with java., javax., sun., com.sun., or jdk..
That keeps servlet filters, reflection, proxies, and thread-pool frames from deciding the group. Two traces that only differ in infrastructure above your code get the same hash if they share the same first application frame.
For example, this alone:
at com.example.Plugin.handle(Plugin.java:42)
hashes the same as a deep trace that only adds internals before that frame:
at java.base/java.lang.Thread.run(Thread.java:840)
at javax.servlet.Filter.doFilter(Filter.java:10)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at com.sun.proxy.$Proxy1.invoke(Unknown Source)
at jdk.proxy2.$Proxy2.run(Unknown Source)
at com.example.Plugin.handle(Plugin.java:42)
Stabilize lambda signatures
Lambda markers collapse to a single $$Lambda token so small bytecode differences do not fragment groups.
Whitespace normalization
Runs of spaces collapse to one space.
Hashing outcome
We concatenate normalized error type and stack lines, then hash with SHA-256. Source maps apply earlier when they are available, so the input to grouping stays stable across builds.
A new issue view
The issue detail page is built like an inspector instead of a long article.
Split layout per event
Each occurrence carries its own stack and context, so the issue page uses a split layout on desktop instead of one long scroll.
Events and a compact timeline sit on the left; stack, context, and activity sit on the right and update when you select an event, not only the latest one on the issue.
You can drag the divider and we remember the width for next time. URLs support ?occurrence= and ?tab= so you can link straight to the view you care about.
Breakdown tab
The left sidebar now has a Breakdown view next to Occurrences. It sums context across the events you have loaded so you can see which versions, platforms, and environments are affected without stepping through each occurrence. Every section has a bar split by value, then a count and a percentage. Values past the top few roll into one row.
If you have not loaded every occurrence yet, the panel says how many events it used. Load more from the list when you need the full picture.
Manual merge and unmerge (new)
Error tracking never had UI to combine or split groups. You could only wait for automatic grouping to get it right.
Now you can select two or more issues on the list and merge them into one group. Pick which issue stays primary. On the detail page you can unmerge individual hashes when automatic grouping lumped too much together.
Context without datasource boundaries
Starting with SDK version 0.24.0, error context is no longer bound to datasources.
Your default metrics still flow into context automatically. You can also attach manual context for specific errors only. FastStats config now lets you turn metrics off while error tracking stays on.
To enable this, we built a brand new route in our data collector, dedicated to submitting errors. Due too this seperation, metrics can now be disbaled while error tracking stays on.
Example configuration:
submitMetrics=false
submitErrors=true
Upgrading to 0.24.0
0.24.0 moves the SDK from standalone metrics instances to a shared platform context that owns the token, config, metrics, error tracking, feature flags, and lifecycle. If you are on 0.23.0, follow the Java migration guide for the full set of breaking changes and a step-by-step checklist.