Error Monitoring
Capture, group, and analyze errors from connected telemetry sources.
How it works
Moneat turns error telemetry into issues your team can triage. When an error arrives, Moneat normalizes the payload, extracts exception and runtime context, generates a fingerprint, and stores the event history for analysis.
Error monitoring is source-neutral in the dashboard. Source-specific details only matter when you are configuring ingestion or troubleshooting a payload.
Ingestion sources
| Source | Error data Moneat can use |
|---|---|
| Sentry-compatible SDKs | Exception events, breadcrumbs, tags, users, request data, releases, and replays |
| OpenTelemetry | Span status, exception events, exception attributes, and related logs |
| Datadog-compatible intake | APM and log error context from compatible agents |
Sentry-compatible SDKs are currently the richest source for full exception events and client replay correlation. OpenTelemetry and Datadog-compatible telemetry still contribute error context to traces, logs, service health, and related issue workflows as supported by the incoming signal.
Sentry-compatible envelope endpoint
When you use a Sentry-compatible SDK, the SDK sends events to the envelope endpoint automatically:
POST /api/{projectId}/envelope/
Content-Type: application/x-sentry-envelope
X-Sentry-Auth: Sentry sentry_key=<public_key>,sentry_version=7The endpoint supports gzip compression. Events are processed asynchronously and typically appear
in the dashboard within seconds.
Event data
Error events can include:
- Exception details - Type, message, and stack trace
- Breadcrumbs - Trail of events leading up to the error
- Tags - Key-value pairs for filtering, such as environment and release
- User context - User ID, email, and IP address when provided
- Device/OS info - Platform, browser, and OS version
- Request data - URL, method, and request metadata for web applications
- Custom context - Additional fields attached by the source SDK or exporter
Symbolicate Apple crashes
Release builds of iOS, macOS, tvOS, and watchOS apps strip their symbols, so the SDK on the device
reports the app's frames as addresses, often with the function <redacted>. Upload each build's
dSYMs to turn those frames back into functions, files, and lines:
export SENTRY_URL=https://api.moneat.io
export SENTRY_AUTH_TOKEN=<your_auth_token>
export SENTRY_ORG=<your_org_slug>
sentry-cli debug-files upload --project <project_slug> path/to/dSYMsUpload the dSYMs of a build before it ships, since Moneat symbolicates events as they arrive. Xcode
build phases and fastlane actions that run sentry-cli upload to Moneat the same way once
SENTRY_URL points at it.
When an event arrives, Moneat finds the image that holds each native frame's address in the event's debug images, reads the uploaded dSYM whose UUID matches that image, and replaces the frame with the function, file, and line at that address. A frame with inlined calls becomes one frame per function. Exception and thread stack traces are both symbolicated. Thin and universal dSYMs work; a binary that has only a symbol table names its functions without files or lines.
Frames in system libraries and other images without an uploaded dSYM keep what the SDK sent. Each
debug image whose frames were looked up records the outcome as debug_status in the event's debug
metadata: found, missing when no file was uploaded for its UUID, or malformed when the uploaded
file could not be read.
Kotlin/Native frames are named by their Kotlin function, such as
kfun:com.example.app.Recorder#start(kotlin.Int){}kotlin.Int. Kotlin/Native links the Kotlin
standard library and the app's code into one image, which the SDK marks as all the app's. When an
exception has Kotlin/Native frames under the release's package, the application ID before @ in the
release name, its Kotlin/Native frames count as the app's own only under that package, so grouping
uses the app's code rather than the standard library.
Error grouping
Automatic fingerprinting
For Sentry-compatible events, Moneat uses the main thrown exception's type and the innermost
application frame's module or class plus function. A frame without an in_app flag is eligible;
frames explicitly marked outside the application are used only when no eligible frame exists.
When a module is present, filenames and line numbers do not affect grouping. Without a module,
the function and filename provide a fallback; generic SourceFile and Unknown Source filenames are
ignored. An exception without frames groups by its type.
For obfuscated Android builds, upload each build's ProGuard/R8 mapping before sending events.
Moneat retraces the exception and frames before grouping, so different obfuscated names can resolve
to the same issue across releases. When the retraced stack has frames under the release's package, the
application ID before @ in the release name, frames without an in_app flag are classified by it:
frames under the package are application frames and the rest are library or platform frames. Grouping
then uses the innermost frame of the app's own code. Events received without their mapping retain their
raw symbols.
Apple events group by their symbolicated function names. When the app's
innermost frame is still <redacted>, its name would put every unsymbolicated error of one exception
type in the same issue, so an error with a message groups by its exception type and message instead.
Values that change between occurrences are replaced in the message first: UUIDs, 0x hex values, runs
of eight or more hex digits that mix letters and digits, and numbers.
Take 1f0c3d1e-9a7b-4c2d-8e5f-0a1b2c3d4e5f was released and
Take 8a2b7c4d-9a7b-4c2d-8e5f-0a1b2c3d4e5f was released share an issue.
An event without an exception, such as one sent with captureMessage or by a logging integration,
groups by its message, with the same values replaced. When the SDK sends a message template with
separate parameters, the template is used, so Could not load asset %s is one issue for every asset;
the issue title shows the formatted message. An event with neither an exception nor a message groups
into a single <unlabeled event> issue.
Custom fingerprinting
Sentry-compatible SDKs can override default grouping with a custom fingerprint:
Sentry.captureException(error, {
fingerprint: ["custom-group-key"],
});To refine automatic grouping, include the exact {{ default }} placeholder:
Sentry.captureException(error, {
fingerprint: ["{{ default }}", "checkout"],
});Moneat replaces each placeholder with the automatic fingerprint components. A fingerprint containing
only {{ default }} groups exactly like automatic grouping. Other values, including their whitespace
and order, are used as supplied; a fingerprint without the placeholder overrides automatic grouping.
Existing issue history
The stable class-and-function grouping update applies when new events are ingested. Previously stored
events retain their issue IDs, history, statuses, and comments; Moneat does not backfill or automatically
merge them. A recurring error whose fingerprint changes starts a new issue after the update, while its
older history remains accessible in the previous issue. New-issue alerts and release new-issue counts
can therefore show a one-time new issue at this cut-over. Type-only fingerprints and custom
fingerprints without {{ default }} retain their grouping when their inputs are unchanged.
Uploading a missing mapping later likewise does not regroup stored events. Upload mappings before ingestion to keep subsequent releases together.
Retraced Android events change fingerprints once when their mapping first applies. They group by the original exception type and the class and method of the app's innermost frame. Earlier events of the same error stay in issues keyed by obfuscated names or a platform frame, so each recurring error starts one new issue.
Apple events change fingerprints once as well. Errors whose innermost app frame is <redacted> used
to share one issue per exception type; they now group by type and message, so each recurring error
starts one new issue. Once a build's dSYMs are uploaded, its errors group by the symbolicated function,
which starts one more new issue per recurring error. Earlier events keep their issues, and uploading
dSYMs later does not regroup stored events.
Events without an exception used to share one <unlabeled event> issue per project whatever their
message. They now group by message, so each recurring message starts one new issue and raises one
new-issue alert. The <unlabeled event> issue keeps its history and status, and afterwards collects
only events that have no message either.
Usage & rate limiting
Moneat meters ingestion by plan and billable usage rather than by source-specific event quotas. If an organization reaches a configured budget cap or ingestion limit, Moneat can reject or drop new events to protect the account.
Monitor usage, included capacity, overages, and budgets under Billing & Plans.
Supported platforms
Any platform that can emit OpenTelemetry errors, Sentry-compatible envelopes, or compatible agent telemetry can contribute error context to Moneat.
For full exception capture through Sentry-compatible SDKs, popular platforms include JavaScript, TypeScript, Python, Java, Kotlin, Swift, Go, Ruby, PHP, .NET, Rust, Elixir, React, Vue, Angular, Next.js, Django, Flask, Spring, Android, iOS, React Native, Flutter, and Node.js.