diff --git a/.changeset/browser-rum-dashboard-template.md b/.changeset/browser-rum-dashboard-template.md new file mode 100644 index 0000000000..fd16b607c6 --- /dev/null +++ b/.changeset/browser-rum-dashboard-template.md @@ -0,0 +1,12 @@ +--- +'@hyperdx/app': minor +--- + +feat: add Browser RUM dashboard template + +- New "Browser RUM" template in the dashboards gallery for browser sessions instrumented with the HyperDX Browser SDK (or any OTel browser instrumentation emitting a `rum.sessionId` resource attribute) +- Performance Overview section: page-view/session/error KPIs, Core Web Vitals (LCP/INP/CLS) p75, median/p75/p90 page-load percentiles, and long-task health +- Page Views Breakdown section: traffic grouped by URL, browser (parsed from the `http.user_agent` the document-load instrumentation emits), country, and device size (derived from `screen.xy`) +- Errors section with tabs for an overview, JS exceptions (by message and by page), and failing API calls +- Five dashboard-level filters: Service, Environment, Service Version, Page URL, and Country +- Top Countries tile and the Country filter populate when the OTel collector's `geoip` processor is enabled (geo can't be derived in the browser) diff --git a/packages/app/src/dashboardTemplates/browser-rum.json b/packages/app/src/dashboardTemplates/browser-rum.json new file mode 100644 index 0000000000..61d188f498 --- /dev/null +++ b/packages/app/src/dashboardTemplates/browser-rum.json @@ -0,0 +1,1024 @@ +{ + "version": "0.1.0", + "name": "Browser RUM", + "description": "Core Web Vitals, page-load percentiles, traffic breakdowns, and error tracking for browser sessions instrumented with the HyperDX Browser SDK (or any OpenTelemetry RUM instrumentation emitting rum.sessionId).", + "tags": ["Browser / RUM"], + "filters": [ + { + "id": "rum-filter-service", + "type": "QUERY_EXPRESSION", + "name": "Service", + "expression": "ServiceName", + "source": "Traces", + "where": "ResourceAttributes.rum.sessionId:*", + "whereLanguage": "lucene" + }, + { + "id": "rum-filter-environment", + "type": "QUERY_EXPRESSION", + "name": "Environment", + "expression": "ResourceAttributes['deployment.environment']", + "source": "Traces", + "where": "ResourceAttributes.rum.sessionId:* AND ResourceAttributes.deployment.environment:*", + "whereLanguage": "lucene" + }, + { + "id": "rum-filter-version", + "type": "QUERY_EXPRESSION", + "name": "Service Version", + "expression": "ResourceAttributes['service.version']", + "source": "Traces", + "where": "ResourceAttributes.rum.sessionId:* AND ResourceAttributes.service.version:*", + "whereLanguage": "lucene" + }, + { + "id": "rum-filter-url", + "type": "QUERY_EXPRESSION", + "name": "Page URL", + "expression": "SpanAttributes['location.href']", + "source": "Traces", + "where": "ResourceAttributes.rum.sessionId:* AND SpanAttributes.location.href:*", + "whereLanguage": "lucene" + }, + { + "id": "rum-filter-country", + "type": "QUERY_EXPRESSION", + "name": "Country", + "expression": "ResourceAttributes['geo.country.name']", + "source": "Traces", + "where": "ResourceAttributes.rum.sessionId:* AND ResourceAttributes.geo.country.name:*", + "whereLanguage": "lucene" + } + ], + "containers": [ + { + "id": "rum-perf", + "title": "Performance Overview", + "collapsed": false + }, + { + "id": "rum-breakdown", + "title": "Page Views Breakdown", + "collapsed": false + }, + { + "id": "rum-errors", + "title": "Errors", + "collapsed": false, + "tabs": [ + { + "id": "rum-errors-overview", + "title": "Overview" + }, + { + "id": "rum-errors-js", + "title": "JS Exceptions" + }, + { + "id": "rum-errors-api", + "title": "API Failures" + } + ] + } + ], + "tiles": [ + { + "id": "rum-006", + "containerId": "rum-perf", + "x": 0, + "y": 0, + "w": 6, + "h": 4, + "config": { + "name": "Page Views", + "source": "Traces", + "displayType": "number", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "count", + "valueExpression": "", + "aggCondition": "SpanName:\"documentLoad\" OR SpanName:\"routeChange\" OR SpanAttributes.component:\"page-view\" OR SpanAttributes.component:\"navigation\"", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "numberFormat": { + "output": "number", + "mantissa": 0, + "thousandSeparated": true + } + } + }, + { + "id": "rum-017", + "containerId": "rum-perf", + "x": 6, + "y": 0, + "w": 6, + "h": 4, + "config": { + "name": "Median Page Load (ms)", + "source": "Traces", + "displayType": "number", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "quantile", + "level": 0.5, + "valueExpression": "Duration / 1000000", + "aggCondition": "SpanName:\"documentLoad\"", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "numberFormat": { + "output": "number", + "mantissa": 0, + "thousandSeparated": true + } + } + }, + { + "id": "rum-018", + "containerId": "rum-perf", + "x": 12, + "y": 0, + "w": 6, + "h": 4, + "config": { + "name": "p90 Page Load (ms)", + "source": "Traces", + "displayType": "number", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "quantile", + "level": 0.9, + "valueExpression": "Duration / 1000000", + "aggCondition": "SpanName:\"documentLoad\"", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "numberFormat": { + "output": "number", + "mantissa": 0, + "thousandSeparated": true + } + } + }, + { + "id": "rum-001", + "containerId": "rum-perf", + "x": 18, + "y": 0, + "w": 6, + "h": 4, + "config": { + "name": "LCP p75 (ms)", + "source": "Traces", + "displayType": "number", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "quantile", + "level": 0.75, + "valueExpression": "toFloat64OrZero(SpanAttributes['lcp'])", + "aggCondition": "SpanName:\"webvitals\" AND SpanAttributes.lcp:*", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "numberFormat": { + "output": "number", + "mantissa": 0, + "thousandSeparated": true + } + } + }, + { + "id": "rum-002", + "containerId": "rum-perf", + "x": 0, + "y": 4, + "w": 6, + "h": 4, + "config": { + "name": "INP p75 (ms)", + "source": "Traces", + "displayType": "number", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "quantile", + "level": 0.75, + "valueExpression": "toFloat64OrZero(SpanAttributes['inp'])", + "aggCondition": "SpanName:\"webvitals\" AND SpanAttributes.inp:*", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "numberFormat": { + "output": "number", + "mantissa": 0, + "thousandSeparated": true + } + } + }, + { + "id": "rum-003", + "containerId": "rum-perf", + "x": 6, + "y": 4, + "w": 6, + "h": 4, + "config": { + "name": "CLS p75", + "source": "Traces", + "displayType": "number", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "quantile", + "level": 0.75, + "valueExpression": "toFloat64OrZero(SpanAttributes['cls'])", + "aggCondition": "SpanName:\"webvitals\" AND SpanAttributes.cls:*", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "numberFormat": { + "output": "number", + "mantissa": 3, + "thousandSeparated": true + } + } + }, + { + "id": "rum-005", + "containerId": "rum-perf", + "x": 12, + "y": 4, + "w": 6, + "h": 4, + "config": { + "name": "Active Sessions", + "source": "Traces", + "displayType": "number", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "count_distinct", + "valueExpression": "ResourceAttributes['rum.sessionId']", + "aggCondition": "ResourceAttributes.rum.sessionId:*", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "numberFormat": { + "output": "number", + "mantissa": 0, + "thousandSeparated": true + } + } + }, + { + "id": "rum-019", + "containerId": "rum-perf", + "x": 18, + "y": 4, + "w": 6, + "h": 4, + "config": { + "name": "Sessions w/ Errors", + "source": "Traces", + "displayType": "number", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "count_distinct", + "valueExpression": "ResourceAttributes['rum.sessionId']", + "aggCondition": "ResourceAttributes.rum.sessionId:* AND StatusCode:error", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "numberFormat": { + "output": "number", + "mantissa": 0, + "thousandSeparated": true + } + } + }, + { + "id": "rum-020", + "containerId": "rum-perf", + "x": 0, + "y": 8, + "w": 24, + "h": 7, + "config": { + "name": "Page Load — median, p75 and p90 (ms)", + "source": "Traces", + "displayType": "line", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "quantile", + "level": 0.5, + "valueExpression": "Duration / 1000000", + "aggCondition": "SpanName:\"documentLoad\"", + "aggConditionLanguage": "lucene", + "alias": "median" + }, + { + "aggFn": "quantile", + "level": 0.75, + "valueExpression": "Duration / 1000000", + "aggCondition": "SpanName:\"documentLoad\"", + "aggConditionLanguage": "lucene", + "alias": "p75" + }, + { + "aggFn": "quantile", + "level": 0.9, + "valueExpression": "Duration / 1000000", + "aggCondition": "SpanName:\"documentLoad\"", + "aggConditionLanguage": "lucene", + "alias": "p90" + } + ], + "where": "", + "whereLanguage": "lucene", + "numberFormat": { + "output": "number", + "mantissa": 0, + "thousandSeparated": true + } + } + }, + { + "id": "rum-021", + "containerId": "rum-perf", + "x": 0, + "y": 15, + "w": 12, + "h": 6, + "config": { + "name": "Page Views over Time", + "source": "Traces", + "displayType": "line", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "count", + "valueExpression": "", + "alias": "Page Views", + "aggCondition": "SpanName:\"documentLoad\" OR SpanName:\"routeChange\" OR SpanAttributes.component:\"page-view\" OR SpanAttributes.component:\"navigation\"", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "numberFormat": { + "output": "number", + "mantissa": 0, + "thousandSeparated": true + } + } + }, + { + "id": "rum-024", + "containerId": "rum-perf", + "x": 12, + "y": 15, + "w": 12, + "h": 6, + "config": { + "name": "Long Tasks over Time", + "source": "Traces", + "displayType": "stacked_bar", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "count", + "valueExpression": "", + "alias": "Long Tasks", + "aggCondition": "SpanName:\"longtask\"", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "numberFormat": { + "output": "number", + "mantissa": 0, + "thousandSeparated": true + } + } + }, + { + "id": "rum-014", + "containerId": "rum-breakdown", + "x": 0, + "y": 0, + "w": 8, + "h": 8, + "config": { + "name": "Top URLs", + "source": "Traces", + "displayType": "table", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "count", + "valueExpression": "", + "alias": "Views", + "aggCondition": "SpanName:\"documentLoad\" OR SpanName:\"routeChange\" OR SpanAttributes.component:\"page-view\" OR SpanAttributes.component:\"navigation\"", + "aggConditionLanguage": "lucene" + }, + { + "aggFn": "count_distinct", + "valueExpression": "ResourceAttributes['rum.sessionId']", + "alias": "Sessions", + "aggCondition": "SpanName:\"documentLoad\" OR SpanName:\"routeChange\" OR SpanAttributes.component:\"page-view\" OR SpanAttributes.component:\"navigation\"", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "groupBy": [ + { + "valueExpression": "coalesce(nullif(SpanAttributes['http.url'], ''), nullif(SpanAttributes['page.url'], ''), nullif(SpanAttributes['location.href'], ''))", + "alias": "URL" + } + ], + "orderBy": "Views DESC", + "limit": { + "limit": 20 + }, + "onClick": { + "type": "search", + "target": { + "mode": "id", + "id": "Traces" + }, + "whereTemplate": "(SpanAttributes.http.url:\"{{URL}}\" OR SpanAttributes.page.url:\"{{URL}}\" OR SpanAttributes.location.href:\"{{URL}}\")", + "whereLanguage": "lucene" + } + } + }, + { + "id": "rum-026", + "containerId": "rum-breakdown", + "x": 8, + "y": 0, + "w": 8, + "h": 8, + "config": { + "name": "Top Browsers", + "source": "Traces", + "displayType": "table", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "count_distinct", + "valueExpression": "ResourceAttributes['rum.sessionId']", + "alias": "Sessions", + "aggCondition": "ResourceAttributes.rum.sessionId:* AND SpanAttributes.http.user_agent:*", + "aggConditionLanguage": "lucene" + }, + { + "aggFn": "count", + "valueExpression": "", + "alias": "Page Loads", + "aggCondition": "ResourceAttributes.rum.sessionId:* AND SpanAttributes.http.user_agent:*", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "groupBy": [ + { + "valueExpression": "multiIf(positionCaseInsensitive(SpanAttributes['http.user_agent'], 'Edg/') > 0, 'Edge', positionCaseInsensitive(SpanAttributes['http.user_agent'], 'OPR/') > 0, 'Opera', positionCaseInsensitive(SpanAttributes['http.user_agent'], 'Firefox/') > 0, 'Firefox', positionCaseInsensitive(SpanAttributes['http.user_agent'], 'Chrome/') > 0, 'Chrome', positionCaseInsensitive(SpanAttributes['http.user_agent'], 'Safari/') > 0, 'Safari', 'Other')", + "alias": "Browser" + } + ], + "orderBy": "Sessions DESC", + "limit": { + "limit": 10 + }, + "onClick": { + "type": "search", + "target": { + "mode": "id", + "id": "Traces" + }, + "whereTemplate": "positionCaseInsensitive(SpanAttributes['http.user_agent'], '{{Browser}}') > 0", + "whereLanguage": "sql" + } + } + }, + { + "id": "rum-027", + "containerId": "rum-breakdown", + "x": 16, + "y": 0, + "w": 8, + "h": 8, + "config": { + "name": "Top Countries (requires geoip processor)", + "source": "Traces", + "displayType": "table", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "count_distinct", + "valueExpression": "ResourceAttributes['rum.sessionId']", + "alias": "Sessions", + "aggCondition": "ResourceAttributes.rum.sessionId:*", + "aggConditionLanguage": "lucene" + }, + { + "aggFn": "count", + "valueExpression": "", + "alias": "Views", + "aggCondition": "ResourceAttributes.rum.sessionId:*", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "groupBy": [ + { + "valueExpression": "coalesce(nullif(ResourceAttributes['geo.country.name'], ''), nullif(SpanAttributes['geo.country.name'], ''), nullif(ResourceAttributes['geo.country.iso_code'], ''), nullif(SpanAttributes['geo.country.iso_code'], ''))", + "alias": "Country" + } + ], + "orderBy": "Sessions DESC", + "limit": { + "limit": 10 + }, + "onClick": { + "type": "search", + "target": { + "mode": "id", + "id": "Traces" + }, + "whereTemplate": "ResourceAttributes.geo.country.name:\"{{Country}}\"", + "whereLanguage": "lucene" + } + } + }, + { + "id": "rum-028", + "containerId": "rum-breakdown", + "x": 0, + "y": 8, + "w": 12, + "h": 8, + "config": { + "name": "Top Device Sizes", + "source": "Traces", + "displayType": "table", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "count_distinct", + "valueExpression": "ResourceAttributes['rum.sessionId']", + "alias": "Sessions", + "aggCondition": "SpanName:\"documentLoad\" AND SpanAttributes.screen.xy:*", + "aggConditionLanguage": "lucene" + }, + { + "aggFn": "count", + "valueExpression": "", + "alias": "Views", + "aggCondition": "SpanName:\"documentLoad\" AND SpanAttributes.screen.xy:*", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "groupBy": [ + { + "valueExpression": "SpanAttributes['screen.xy']", + "alias": "Device" + } + ], + "orderBy": "Sessions DESC", + "limit": { + "limit": 10 + }, + "onClick": { + "type": "search", + "target": { + "mode": "id", + "id": "Traces" + }, + "whereTemplate": "SpanName:\"documentLoad\" AND SpanAttributes.screen.xy:\"{{Device}}\"", + "whereLanguage": "lucene" + } + } + }, + { + "id": "rum-011", + "containerId": "rum-breakdown", + "x": 12, + "y": 8, + "w": 12, + "h": 8, + "config": { + "name": "Slowest Pages (p75 page load)", + "source": "Traces", + "displayType": "table", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "quantile", + "level": 0.75, + "valueExpression": "Duration / 1000000", + "aggCondition": "SpanName:\"documentLoad\"", + "aggConditionLanguage": "lucene", + "alias": "Page Load p75 (ms)" + }, + { + "aggFn": "count", + "valueExpression": "", + "alias": "Views", + "aggCondition": "SpanName:\"documentLoad\"", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "groupBy": [ + { + "valueExpression": "coalesce(nullif(SpanAttributes['http.url'], ''), nullif(SpanAttributes['page.url'], ''), nullif(SpanAttributes['location.href'], ''))", + "alias": "URL" + } + ], + "orderBy": "`Page Load p75 (ms)` DESC", + "limit": { + "limit": 20 + }, + "onClick": { + "type": "search", + "target": { + "mode": "id", + "id": "Traces" + }, + "whereTemplate": "SpanName:\"documentLoad\" AND (SpanAttributes.http.url:\"{{URL}}\" OR SpanAttributes.page.url:\"{{URL}}\" OR SpanAttributes.location.href:\"{{URL}}\")", + "whereLanguage": "lucene" + } + } + }, + { + "id": "rum-016", + "containerId": "rum-breakdown", + "x": 0, + "y": 16, + "w": 24, + "h": 8, + "config": { + "name": "Top Errored Sessions", + "source": "Traces", + "displayType": "table", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "count", + "valueExpression": "", + "aggCondition": "StatusCode:error", + "aggConditionLanguage": "lucene", + "alias": "Errors" + }, + { + "aggFn": "count_distinct", + "valueExpression": "TraceId", + "alias": "Traces" + }, + { + "aggFn": "any", + "valueExpression": "nullif(SpanAttributes['userEmail'], '')", + "alias": "User" + }, + { + "aggFn": "any", + "valueExpression": "ServiceName", + "alias": "Service" + } + ], + "where": "ResourceAttributes.rum.sessionId:*", + "whereLanguage": "lucene", + "groupBy": [ + { + "valueExpression": "ResourceAttributes['rum.sessionId']", + "alias": "Session" + } + ], + "having": "Errors > 0", + "havingLanguage": "sql", + "orderBy": "Errors DESC", + "limit": { + "limit": 20 + }, + "onClick": { + "type": "search", + "target": { + "mode": "id", + "id": "Traces" + }, + "whereTemplate": "ResourceAttributes.rum.sessionId:\"{{Session}}\"", + "whereLanguage": "lucene" + } + } + }, + { + "id": "rum-007", + "containerId": "rum-errors", + "tabId": "rum-errors-overview", + "x": 0, + "y": 0, + "w": 12, + "h": 4, + "config": { + "name": "JS Errors", + "source": "Traces", + "displayType": "number", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "count", + "valueExpression": "", + "aggCondition": "ResourceAttributes.rum.sessionId:* AND StatusCode:error AND NOT (SpanAttributes.component:\"fetch\" OR SpanAttributes.component:\"xml-http-request\")", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "numberFormat": { + "output": "number", + "mantissa": 0, + "thousandSeparated": true + } + } + }, + { + "id": "rum-008", + "containerId": "rum-errors", + "tabId": "rum-errors-overview", + "x": 12, + "y": 0, + "w": 12, + "h": 4, + "config": { + "name": "AJAX Errors", + "source": "Traces", + "displayType": "number", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "count", + "valueExpression": "", + "aggCondition": "ResourceAttributes['rum.sessionId'] != '' AND (SpanAttributes['component'] = 'fetch' OR SpanAttributes['component'] = 'xml-http-request') AND (toUInt16OrZero(SpanAttributes['http.status_code']) >= 400 OR StatusCode = 'STATUS_CODE_ERROR')", + "aggConditionLanguage": "sql" + } + ], + "where": "", + "whereLanguage": "sql", + "numberFormat": { + "output": "number", + "mantissa": 0, + "thousandSeparated": true + } + } + }, + { + "id": "rum-010", + "containerId": "rum-errors", + "tabId": "rum-errors-overview", + "x": 0, + "y": 4, + "w": 24, + "h": 7, + "config": { + "name": "Errors over Time", + "source": "Traces", + "displayType": "line", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "count", + "valueExpression": "", + "aggCondition": "StatusCode:error AND NOT (SpanAttributes.component:\"fetch\" OR SpanAttributes.component:\"xml-http-request\")", + "aggConditionLanguage": "lucene", + "alias": "JS Errors" + }, + { + "aggFn": "count", + "valueExpression": "", + "aggCondition": "(SpanAttributes['component'] = 'fetch' OR SpanAttributes['component'] = 'xml-http-request') AND (toUInt16OrZero(SpanAttributes['http.status_code']) >= 400 OR StatusCode = 'STATUS_CODE_ERROR')", + "aggConditionLanguage": "sql", + "alias": "AJAX Errors" + } + ], + "where": "ResourceAttributes.rum.sessionId:*", + "whereLanguage": "lucene", + "numberFormat": { + "output": "number", + "mantissa": 0, + "thousandSeparated": true + } + } + }, + { + "id": "rum-012", + "containerId": "rum-errors", + "tabId": "rum-errors-js", + "x": 0, + "y": 0, + "w": 12, + "h": 8, + "config": { + "name": "Top JS Errors (by message)", + "source": "Traces", + "displayType": "table", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "count", + "valueExpression": "", + "alias": "Occurrences", + "aggCondition": "ResourceAttributes.rum.sessionId:* AND StatusCode:error AND NOT (SpanAttributes.component:\"fetch\" OR SpanAttributes.component:\"xml-http-request\")", + "aggConditionLanguage": "lucene" + }, + { + "aggFn": "count_distinct", + "valueExpression": "ResourceAttributes['rum.sessionId']", + "alias": "Sessions", + "aggCondition": "ResourceAttributes.rum.sessionId:* AND StatusCode:error AND NOT (SpanAttributes.component:\"fetch\" OR SpanAttributes.component:\"xml-http-request\")", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "groupBy": [ + { + "valueExpression": "coalesce(nullif(SpanAttributes['exception.message'], ''), nullif(SpanAttributes['message'], ''), SpanName)", + "alias": "Error" + } + ], + "orderBy": "Occurrences DESC", + "limit": { + "limit": 20 + }, + "onClick": { + "type": "search", + "target": { + "mode": "id", + "id": "Traces" + }, + "whereTemplate": "StatusCode:error AND (SpanAttributes.exception.message:\"{{Error}}\" OR SpanAttributes.message:\"{{Error}}\" OR SpanName:\"{{Error}}\")", + "whereLanguage": "lucene" + } + } + }, + { + "id": "rum-015", + "containerId": "rum-errors", + "tabId": "rum-errors-js", + "x": 12, + "y": 0, + "w": 12, + "h": 8, + "config": { + "name": "Errors per Page", + "source": "Traces", + "displayType": "table", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "count", + "valueExpression": "", + "alias": "Errors", + "aggCondition": "ResourceAttributes.rum.sessionId:* AND StatusCode:error AND NOT (SpanAttributes.component:\"fetch\" OR SpanAttributes.component:\"xml-http-request\")", + "aggConditionLanguage": "lucene" + }, + { + "aggFn": "count_distinct", + "valueExpression": "ResourceAttributes['rum.sessionId']", + "alias": "Sessions", + "aggCondition": "ResourceAttributes.rum.sessionId:* AND StatusCode:error AND NOT (SpanAttributes.component:\"fetch\" OR SpanAttributes.component:\"xml-http-request\")", + "aggConditionLanguage": "lucene" + } + ], + "where": "", + "whereLanguage": "lucene", + "groupBy": [ + { + "valueExpression": "coalesce(nullif(SpanAttributes['http.url'], ''), nullif(SpanAttributes['page.url'], ''), nullif(SpanAttributes['location.href'], ''))", + "alias": "URL" + } + ], + "orderBy": "Errors DESC", + "limit": { + "limit": 20 + }, + "onClick": { + "type": "search", + "target": { + "mode": "id", + "id": "Traces" + }, + "whereTemplate": "StatusCode:error AND (SpanAttributes.http.url:\"{{URL}}\" OR SpanAttributes.page.url:\"{{URL}}\" OR SpanAttributes.location.href:\"{{URL}}\")", + "whereLanguage": "lucene" + } + } + }, + { + "id": "rum-013", + "containerId": "rum-errors", + "tabId": "rum-errors-api", + "x": 0, + "y": 0, + "w": 24, + "h": 8, + "config": { + "name": "Top Failing API Calls", + "source": "Traces", + "displayType": "table", + "granularity": "auto", + "alignDateRangeToGranularity": true, + "select": [ + { + "aggFn": "count", + "valueExpression": "", + "alias": "Failures", + "aggCondition": "ResourceAttributes['rum.sessionId'] != '' AND (SpanAttributes['component'] = 'fetch' OR SpanAttributes['component'] = 'xml-http-request') AND (toUInt16OrZero(SpanAttributes['http.status_code']) >= 400 OR StatusCode = 'STATUS_CODE_ERROR')", + "aggConditionLanguage": "sql" + }, + { + "aggFn": "count_distinct", + "valueExpression": "ResourceAttributes['rum.sessionId']", + "alias": "Sessions", + "aggCondition": "ResourceAttributes['rum.sessionId'] != '' AND (SpanAttributes['component'] = 'fetch' OR SpanAttributes['component'] = 'xml-http-request') AND (toUInt16OrZero(SpanAttributes['http.status_code']) >= 400 OR StatusCode = 'STATUS_CODE_ERROR')", + "aggConditionLanguage": "sql" + } + ], + "where": "", + "whereLanguage": "sql", + "groupBy": [ + { + "valueExpression": "coalesce(nullif(SpanAttributes['http.url'], ''), '')", + "alias": "Endpoint" + } + ], + "orderBy": "Failures DESC", + "limit": { + "limit": 20 + }, + "onClick": { + "type": "search", + "target": { + "mode": "id", + "id": "Traces" + }, + "whereTemplate": "(SpanAttributes.component:\"fetch\" OR SpanAttributes.component:\"xml-http-request\") AND SpanAttributes.http.url:\"{{Endpoint}}\"", + "whereLanguage": "lucene" + } + } + } + ] +} diff --git a/packages/app/src/dashboardTemplates/index.ts b/packages/app/src/dashboardTemplates/index.ts index 609affa295..58e84c5684 100644 --- a/packages/app/src/dashboardTemplates/index.ts +++ b/packages/app/src/dashboardTemplates/index.ts @@ -3,6 +3,7 @@ import { DashboardTemplateSchema, } from '@hyperdx/common-utils/dist/types'; +import browserRum from './browser-rum.json'; import dotnetRuntime from './dotnet-runtime.json'; import goRuntime from './go-runtime.json'; import jvmRuntimeMetrics from './jvm-runtime-metrics.json'; @@ -23,6 +24,7 @@ function parseTemplate( } const templates: Record = { + 'browser-rum': browserRum, 'dotnet-runtime': dotnetRuntime, 'go-runtime': goRuntime, 'jvm-runtime-metrics': jvmRuntimeMetrics,