A Wheels plugin for Sentry error tracking. Provides automatic SDK initialization, controller mixin methods, configurable scope capture, and breadcrumb support.
- Wheels 4.0+
- Lucee 5+ or Adobe ColdFusion 2018+
wheels packages add wheels-sentryThis installs the package into vendor/wheels-sentry/. At boot the framework's package loader reads package.json and builds the client; the mixin attaches to all controllers on application start, so no application code is required.
The loader is asked to register a /plugins/sentry mapping, and this package declares it — but on Lucee a mapping registered after application start does not resolve (the entry is written to application.mappings and never consulted, wheels-dev/wheels#3639). The client is therefore constructed through the declared alias when the engine honours it, and otherwise through the install path wheels packages add guarantees, and the boot log records which was used.
If you previously hand-installed this into plugins/sentry/, remove that directory after running wheels packages add wheels-sentry. The set(overwritePlugins=false) / set(deletePluginDirectories=false) knobs in config/settings.cfm are no longer required — they only mattered for the deprecated plugins/ install path.
All settings are configured via set() in config/settings.cfm.
set(sentryDSN="https://your-key@o123.ingest.us.sentry.io/456");The DSN can also be read from the SENTRY_DSN Java system environment variable as a fallback.
The plugin controls what data is included in Sentry events. Settings are split into two groups: non-sensitive data (on by default) and PII/sensitive data (off by default).
| Setting | Default | Description |
|---|---|---|
sentryDSN |
"" |
Required. Your Sentry DSN. |
sentrySendDefaultPii |
false |
Master toggle for PII. When true, enables includeUser, includeSession, and includeCookies. |
sentryIncludeHeaders |
true |
Include HTTP request headers. |
sentryIncludeServerContext |
true |
Include server name, port, remote addr, http host. |
sentryIncludeUser |
follows sentrySendDefaultPii |
Include user context set via sentrySetUser(). |
sentryIncludeSession |
follows sentrySendDefaultPii |
Include session scope data. |
sentryIncludeCookies |
follows sentrySendDefaultPii |
Include cookie data in request context. |
Individual PII settings override sentrySendDefaultPii. For example, to enable only user context but not session or cookies:
set(sentrySendDefaultPii=false);
set(sentryIncludeUser=true);- Exception type, message, and CFML stack trace with source context
- Request URL and HTTP method
- Tags:
wheels.controller,wheels.action,cfml.engine,cfml.framework,wheels.environment - Breadcrumbs added during the request
- App context: environment, release, Wheels environment
- Server name
- Environment: Read from
application.wheels.environment(e.g.,production,development) - Release: Read from the
APP_VERSIONJava system environment variable, or"unknown"
The plugin adds mixin methods to all controllers:
// In any controller action
function show() {
try {
// risky operation
} catch (any e) {
sentryCapture(e);
// or with extra data:
sentryCapture(exception=e, level="warning", additionalData={orderId: params.key});
}
}sentryMessage("Payment processed for order #params.key#", "info");The plugin does not read user identity from the session automatically. This keeps it generic across applications. To attach user identity, call sentrySetUser() in a before filter:
// app/controllers/Controller.cfc
component extends="wheels.Controller" {
function config() {
filters(through="setSentryUser");
}
private function setSentryUser() {
if (structKeyExists(session, "currentUser")) {
sentrySetUser({
id: session.currentUser.id,
email: session.currentUser.email,
username: session.currentUser.name
});
}
}
}The struct passed to sentrySetUser() accepts any keys supported by Sentry's user context: id, email, username, ip_address, etc.
Breadcrumbs are included in the next captured event:
sentryAddBreadcrumb("Loaded order #params.key#", "data");
sentryAddBreadcrumb("Checking inventory", "logic", {warehouse: "east"});For unhandled errors that reach the Wheels error handler (production mode), add Sentry capture to app/events/onerror.cfm:
<cfscript>
try {
if (structKeyExists(application, "sentry") && structKeyExists(local, "exception")) {
application.sentry.captureException(
exception: local.exception,
level: "error",
useThread: false,
showJavaStackTrace: true
);
}
} catch (any sentryError) {
writeLog(text="Sentry capture failed: #sentryError.message#", type="error", file="application");
}
</cfscript>Note: useThread: false is recommended in error handlers because threads may be killed during shutdown.
Sentry levels: fatal, error, warning, info, debug
Both modern and legacy Sentry DSN formats are supported:
Modern: https://{PUBLIC_KEY}@{HOST}/{PROJECT_ID}
Legacy: https://{PUBLIC_KEY}:{SECRET_KEY}@{HOST}/{PROJECT_ID}
MIT