Faro: Update configuration with best practices (#112108)

* Clean up faro configuration to align with best practices

* Update grafana docs

* remove fixme comment

* fix tests

* don't spread config in
This commit is contained in:
Josh Hunt
2025-10-13 13:46:29 +01:00
committed by GitHub
parent 32f1912311
commit ea25b75966
9 changed files with 223 additions and 201 deletions
+31 -25
View File
@@ -1194,11 +1194,39 @@ facility =
tag = tag =
[log.frontend] [log.frontend]
# Should Faro javascript agent be initialized # Enables the Grafana Faro javascript agent integration for capturing frontend performance and error events.
enabled = false enabled = false
# Custom HTTP endpoint to send events to. Default will log the events to stdout. # Custom HTTP endpoint to send Grafana Faro events to. Default will send events to /log-grafana-javascript-agent and log the events to stdout.
custom_endpoint = custom_endpoint = /log-grafana-javascript-agent
# API Key for Grafana Faro custom endpoint
api_key =
# level of internal logging for debugging Grafana Javascript Agent.
# possible values are: 0 = OFF, 1 = ERROR, 2 = WARN, 3 = INFO, 4 = VERBOSE
# more details: https://github.com/grafana/faro-web-sdk/blob/v1.3.7/docs/sources/tutorials/quick-start-browser.md#how-to-activate-debugging
internal_logger_level = 0
# Enables the Console instrumentation for Grafana Faro
# See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/console-instrumentation/
instrumentations_console_enabled = true
# Enables the Performance instrumentation for Grafana Faro.
# See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/performance-instrumentation/
instrumentations_performance_enabled = true
# Enables the Content Security Policy Violations instrumentation for Grafana Faro.
# See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/csp-violation-tracking/
instrumentations_csp_enabled = true
# Enables the Tracing instrumentation for Grafana Faro.
# See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/tracing-instrumentation/
instrumentations_tracing_enabled = true
# Enables sending attribution data for web vitals with the Performance instrumentation.
# See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/web-vitals/#web-vitals-attribution-data
web_vitals_attribution_enabled = true
# Requests per second limit enforced per an extended period, for Grafana backend log ingestion endpoint (/log). # Requests per second limit enforced per an extended period, for Grafana backend log ingestion endpoint (/log).
log_endpoint_requests_per_second_limit = 3 log_endpoint_requests_per_second_limit = 3
@@ -1206,28 +1234,6 @@ log_endpoint_requests_per_second_limit = 3
# Max requests accepted per short interval of time for Grafana backend log ingestion endpoint (/log) # Max requests accepted per short interval of time for Grafana backend log ingestion endpoint (/log)
log_endpoint_burst_limit = 15 log_endpoint_burst_limit = 15
# Enables all Faro default instrumentation by using `getWebInstrumentations`. Overrides other instrumentation flags.
instrumentations_all_enabled = false
# Should error instrumentation be enabled, only affects Grafana Javascript Agent
instrumentations_errors_enabled = true
# Should console instrumentation be enabled, only affects Grafana Javascript Agent
instrumentations_console_enabled = false
# Should webvitals instrumentation be enabled, only affects Grafana Javascript Agent
instrumentations_webvitals_enabled = false
# Should tracing instrumentation be enabled, only affects Grafana Javascript Agent
instrumentations_tracing_enabled = false
# level of internal logging for debugging Grafana Javascript Agent.
# possible values are: 0 = OFF, 1 = ERROR, 2 = WARN, 3 = INFO, 4 = VERBOSE
# more details: https://github.com/grafana/faro-web-sdk/blob/v1.3.7/docs/sources/tutorials/quick-start-browser.md#how-to-activate-debugging
internal_logger_level = 0
# Api Key, only applies to Grafana Javascript Agent provider
api_key =
#################################### Usage Quotas ######################## #################################### Usage Quotas ########################
[quota] [quota]
+23 -19
View File
@@ -1172,35 +1172,39 @@
;tag = ;tag =
[log.frontend] [log.frontend]
# Should Faro javascript agent be initialized # Enables the Grafana Faro javascript agent integration for capturing frontend performance and error events.
;enabled = false ;enabled = false
# Custom HTTP endpoint to send events to. Default will log the events to stdout. # Custom HTTP endpoint to send Grafana Faro events to. Default will send events to /log-grafana-javascript-agent and log the events to stdout.
;custom_endpoint = /log-grafana-javascript-agent ;custom_endpoint = /log-grafana-javascript-agent
# Requests per second limit enforced an extended period, for Grafana backend log ingestion endpoint (/log). # API Key for Grafana Faro custom endpoint
;log_endpoint_requests_per_second_limit = 3 ;api_key =
# Max requests accepted per short interval of time for Grafana backend log ingestion endpoint (/log). # level of internal logging for debugging Grafana Javascript Agent.
;log_endpoint_burst_limit = 15 # possible values are: 0 = OFF, 1 = ERROR, 2 = WARN, 3 = INFO, 4 = VERBOSE
# more details: https://github.com/grafana/faro-web-sdk/blob/v1.3.7/docs/sources/tutorials/quick-start-browser.md#how-to-activate-debugging
;internal_logger_level =
# Enables all Faro default instrumentation by using `getWebInstrumentations`. Overrides other instrumentation flags. # Enables the Console instrumentation for Grafana Faro
;instrumentations_all_enabled = false # See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/console-instrumentation/
;instrumentations_console_enabled = true
# Should error instrumentation be enabled, only affects Grafana Javascript Agent # Enables the Performance instrumentation for Grafana Faro.
;instrumentations_errors_enabled = true # See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/performance-instrumentation/
;instrumentations_performance_enabled = true
# Should console instrumentation be enabled, only affects Grafana Javascript Agent # Enables the Content Security Policy Violations instrumentation for Grafana Faro.
;instrumentations_console_enabled = false # See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/csp-violation-tracking/
; instrumentations_csp_enabled = true
# Should webvitals instrumentation be enabled, only affects Grafana Javascript Agent # Enables the Tracing instrumentation for Grafana Faro.
;instrumentations_webvitals_enabled = false # See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/tracing-instrumentation/
;instrumentations_tracing_enabled = true
# Should tracing instrumentation be enabled, only affects Grafana Javascript Agent # Enables sending attribution data for web vitals with the Performance instrumentation.
;instrumentations_tracing_enabled = false # See https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/web-vitals/#web-vitals-attribution-data
;web_vitals_attribution_enabled = true
# Api Key, only applies to Grafana Javascript Agent provider
;api_key = testApiKey
#################################### Usage Quotas ######################## #################################### Usage Quotas ########################
[quota] [quota]
@@ -1641,11 +1641,35 @@ Syslog tag. By default, the process's `argv[0]` is used.
#### `enabled` #### `enabled`
Faro JavaScript agent is initialized. Default is `false`. Grafana Faro instrumentation is initialized. Default is `false`. Enables the default set of instrumentations from `getWebInstrumentations`. See the options below to selectively disable some of these.
#### `custom_endpoint` #### `custom_endpoint`
Custom HTTP endpoint to send events captured by the Faro agent to. Default, `/log-grafana-javascript-agent`, logs the events to standard output. Custom HTTP endpoint to send events captured by the Grafana Faro agent to. Default, `/log-grafana-javascript-agent`, logs the events to standard output.
#### `api_key`
If `custom_endpoint` required authentication, you can set the API key here. Only relevant for Grafana JavaScript Agent provider.
#### `instrumentations_console_enabled`
Enables the [Console instrumentation](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/console-instrumentation/) for Grafana Faro, defaults to `true`.
#### `instrumentations_performance_enabled`
Enables the [Performance instrumentation](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/performance-instrumentation/) for Grafana Faro, defaults to `true`.
#### `instrumentations_csp_enabled`
Enables the [Content Security Policy Violations instrumentation](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/csp-violation-tracking/) for Grafana Faro, defaults to `true`.
#### `instrumentations_tracing_enabled`
Enables the [Tracing instrumentation](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/tracing-instrumentation/) for Grafana Faro, defaults to `true`.
#### `web_vitals_attribution_enabled`
Enables sending [attribution data for web vitals](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/web-vitals/#web-vitals-attribution-data) with the Performance instrumentation, defaults to `true`.
#### `log_endpoint_requests_per_second_limit` #### `log_endpoint_requests_per_second_limit`
@@ -1655,30 +1679,6 @@ Requests per second limit enforced per an extended period, for Grafana backend l
Maximum requests accepted per short interval of time for Grafana backend log ingestion endpoint, `/log-grafana-javascript-agent`. Default is `15`. Maximum requests accepted per short interval of time for Grafana backend log ingestion endpoint, `/log-grafana-javascript-agent`. Default is `15`.
#### `instrumentations_all_enabled`
Enables all Faro default instrumentation by using `getWebInstrumentations`. Overrides other instrumentation flags.
#### `instrumentations_errors_enabled`
Turn on error instrumentation. Only affects Grafana JavaScript Agent.
#### `instrumentations_console_enabled`
Turn on console instrumentation. Only affects Grafana JavaScript Agent
#### `instrumentations_webvitals_enabled`
Turn on web vitals instrumentation. Only affects Grafana JavaScript Agent
#### `instrumentations_tracing_enabled`
Turns on tracing instrumentation. Only affects Grafana JavaScript Agent.
#### `api_key`
If `custom_endpoint` required authentication, you can set the API key here. Only relevant for Grafana JavaScript Agent provider.
<hr> <hr>
### `[quota]` ### `[quota]`
+9 -4
View File
@@ -1,3 +1,5 @@
import type { InternalLoggerLevel } from '@grafana/faro-core';
import { SystemDateFormatSettings } from '../datetime/formats'; import { SystemDateFormatSettings } from '../datetime/formats';
import { MapLayerOptions } from '../geo/layer'; import { MapLayerOptions } from '../geo/layer';
@@ -93,11 +95,14 @@ export interface LicenseInfo {
export interface GrafanaJavascriptAgentConfig { export interface GrafanaJavascriptAgentConfig {
enabled: boolean; enabled: boolean;
customEndpoint: string; customEndpoint: string;
errorInstrumentalizationEnabled: boolean;
consoleInstrumentalizationEnabled: boolean;
webVitalsInstrumentalizationEnabled: boolean;
tracingInstrumentalizationEnabled: boolean;
apiKey: string; apiKey: string;
internalLoggerLevel: InternalLoggerLevel;
consoleInstrumentalizationEnabled: boolean;
performanceInstrumentalizationEnabled: boolean;
cspInstrumentalizationEnabled: boolean;
tracingInstrumentalizationEnabled: boolean;
webVitalsAttribution: boolean;
} }
export interface UnifiedAlertingStateHistoryConfig { export interface UnifiedAlertingStateHistoryConfig {
+5 -4
View File
@@ -153,13 +153,14 @@ export class GrafanaBootConfig {
dateFormats?: SystemDateFormatSettings; dateFormats?: SystemDateFormatSettings;
grafanaJavascriptAgent = { grafanaJavascriptAgent = {
enabled: false, enabled: false,
customEndpoint: '',
apiKey: '', apiKey: '',
allInstrumentationsEnabled: false, customEndpoint: '',
errorInstrumentalizationEnabled: true,
consoleInstrumentalizationEnabled: false, consoleInstrumentalizationEnabled: false,
webVitalsInstrumentalizationEnabled: false, performanceInstrumentalizationEnabled: false,
cspInstrumentalizationEnabled: false,
tracingInstrumentalizationEnabled: false, tracingInstrumentalizationEnabled: false,
webVitalsAttribution: false,
internalLoggerLevel: 0,
}; };
pluginCatalogURL = 'https://grafana.com/grafana/plugins/'; pluginCatalogURL = 'https://grafana.com/grafana/plugins/';
pluginAdminEnabled = true; pluginAdminEnabled = true;
+26 -22
View File
@@ -1,32 +1,36 @@
package setting package setting
type GrafanaJavascriptAgent struct { type GrafanaJavascriptAgent struct {
Enabled bool `json:"enabled"` EndpointRPS int `json:"-"`
CustomEndpoint string `json:"customEndpoint"` EndpointBurst int `json:"-"`
EndpointRPS int `json:"-"`
EndpointBurst int `json:"-"` // Faro config
AllInstrumentationsEnabeld bool `json:"allInstrumentationEnabeld"` Enabled bool `json:"enabled"`
ErrorInstrumentalizationEnabled bool `json:"errorInstrumentalizationEnabled"` CustomEndpoint string `json:"customEndpoint"`
ConsoleInstrumentalizationEnabled bool `json:"consoleInstrumentalizationEnabled"` ApiKey string `json:"apiKey"`
WebVitalsInstrumentalizationEnabled bool `json:"webVitalsInstrumentalizationEnabled"` InternalLoggerLevel int `json:"internalLoggerLevel"`
TracingInstrumentalizationEnabled bool `json:"tracingInstrumentalizationEnabled"` ConsoleInstrumentalizationEnabled bool `json:"consoleInstrumentalizationEnabled"`
InternalLoggerLevel int `json:"internalLoggerLevel"` PerformanceInstrumentalizationEnabled bool `json:"performanceInstrumentalizationEnabled"`
ApiKey string `json:"apiKey"` CSPInstrumentalizationEnabled bool `json:"cspInstrumentalizationEnabled"`
TracingInstrumentalizationEnabled bool `json:"tracingInstrumentalizationEnabled"`
WebVitalsAttributionEnabled bool `json:"webVitalsAttributionEnabled"`
} }
func (cfg *Cfg) readGrafanaJavascriptAgentConfig() { func (cfg *Cfg) readGrafanaJavascriptAgentConfig() {
raw := cfg.Raw.Section("log.frontend") raw := cfg.Raw.Section("log.frontend")
cfg.GrafanaJavascriptAgent = GrafanaJavascriptAgent{ cfg.GrafanaJavascriptAgent = GrafanaJavascriptAgent{
Enabled: raw.Key("enabled").MustBool(true), EndpointRPS: raw.Key("log_endpoint_requests_per_second_limit").MustInt(3),
CustomEndpoint: raw.Key("custom_endpoint").MustString("/log-grafana-javascript-agent"), EndpointBurst: raw.Key("log_endpoint_burst_limit").MustInt(15),
EndpointRPS: raw.Key("log_endpoint_requests_per_second_limit").MustInt(3),
EndpointBurst: raw.Key("log_endpoint_burst_limit").MustInt(15), // Faro config
AllInstrumentationsEnabeld: raw.Key("instrumentations_all_enabled").MustBool(false), Enabled: raw.Key("enabled").MustBool(false),
ErrorInstrumentalizationEnabled: raw.Key("instrumentations_errors_enabled").MustBool(true), CustomEndpoint: raw.Key("custom_endpoint").MustString("/log-grafana-javascript-agent"),
ConsoleInstrumentalizationEnabled: raw.Key("instrumentations_console_enabled").MustBool(true), ApiKey: raw.Key("api_key").String(),
WebVitalsInstrumentalizationEnabled: raw.Key("instrumentations_webvitals_enabled").MustBool(true), InternalLoggerLevel: raw.Key("internal_logger_level").MustInt(0),
TracingInstrumentalizationEnabled: raw.Key("instrumentations_tracing_enabled").MustBool(true), ConsoleInstrumentalizationEnabled: raw.Key("instrumentations_console_enabled").MustBool(true),
InternalLoggerLevel: raw.Key("internal_logger_level").MustInt(0), PerformanceInstrumentalizationEnabled: raw.Key("instrumentations_performance_enabled").MustBool(true),
ApiKey: raw.Key("api_key").String(), CSPInstrumentalizationEnabled: raw.Key("instrumentations_csp_enabled").MustBool(true),
TracingInstrumentalizationEnabled: raw.Key("instrumentations_tracing_enabled").MustBool(true),
WebVitalsAttributionEnabled: raw.Key("web_vitals_attribution_enabled").MustBool(true),
} }
} }
@@ -2,7 +2,15 @@ import { BuildInfo } from '@grafana/data';
import { GrafanaEdition } from '@grafana/data/internal'; import { GrafanaEdition } from '@grafana/data/internal';
import { Faro, Instrumentation } from '@grafana/faro-core'; import { Faro, Instrumentation } from '@grafana/faro-core';
import * as faroWebSdkModule from '@grafana/faro-web-sdk'; import * as faroWebSdkModule from '@grafana/faro-web-sdk';
import { BrowserConfig, FetchTransport, SessionInstrumentation } from '@grafana/faro-web-sdk'; import {
BrowserConfig,
FetchTransport,
SessionInstrumentation,
UserActionInstrumentation,
ErrorsInstrumentation,
WebVitalsInstrumentation,
ViewInstrumentation,
} from '@grafana/faro-web-sdk';
import { TracingInstrumentation } from '@grafana/faro-web-tracing'; import { TracingInstrumentation } from '@grafana/faro-web-tracing';
import { config } from '@grafana/runtime'; import { config } from '@grafana/runtime';
@@ -71,21 +79,16 @@ describe('GrafanaJavascriptAgentEchoBackend', () => {
}; };
const options: GrafanaJavascriptAgentBackendOptions = { const options: GrafanaJavascriptAgentBackendOptions = {
buildInfo,
app: {
version: '1.0',
},
allInstrumentationsEnabled: true,
errorInstrumentalizationEnabled: true,
consoleInstrumentalizationEnabled: true,
webVitalsInstrumentalizationEnabled: true,
tracingInstrumentalizationEnabled: true,
customEndpoint: '/log-grafana-javascript-agent', customEndpoint: '/log-grafana-javascript-agent',
user: {
email: 'darth.vader@sith.glx', webVitalsAttribution: true,
id: '504', consoleInstrumentalizationEnabled: true,
orgId: 1, performanceInstrumentalizationEnabled: true,
}, cspInstrumentalizationEnabled: true,
tracingInstrumentalizationEnabled: true,
buildInfo: buildInfo,
userIdentifier: 'abc123',
ignoreUrls: [], ignoreUrls: [],
}; };
@@ -116,13 +119,13 @@ describe('GrafanaJavascriptAgentEchoBackend', () => {
//assert //assert
expect(initializeFaroMock).toHaveBeenCalledTimes(1); expect(initializeFaroMock).toHaveBeenCalledTimes(1);
expect(mockedSetUser).toHaveBeenCalledTimes(1); expect(initializeFaroMock).toHaveBeenCalledWith(
expect(mockedSetUser).toHaveBeenCalledWith({ expect.objectContaining({
id: '504', user: {
attributes: { id: 'abc123',
orgId: '1', },
}, })
}); );
}); });
test('will ensure the performance of TRACKING_URLS', async () => { test('will ensure the performance of TRACKING_URLS', async () => {
@@ -139,22 +142,39 @@ describe('GrafanaJavascriptAgentEchoBackend', () => {
it('correctly set instrumentation based on options', async () => { it('correctly set instrumentation based on options', async () => {
let opts = { let opts = {
...options, ...options,
allInstrumentationsEnabled: false,
errorInstrumentalizationEnabled: false,
consoleInstrumentalizationEnabled: false, consoleInstrumentalizationEnabled: false,
webVitalsInstrumentalizationEnabled: false, performanceInstrumentalizationEnabled: false,
cspInstrumentalizationEnabled: false,
tracingInstrumentalizationEnabled: false, tracingInstrumentalizationEnabled: false,
}; };
new GrafanaJavascriptAgentBackend(opts); new GrafanaJavascriptAgentBackend(opts);
expect(initializeFaroMock.mock.calls[0][0].instrumentations?.length).toEqual(1);
expect(initializeFaroMock.mock.calls[0][0].instrumentations?.[0]).toBeInstanceOf(SessionInstrumentation); let lastInstrumentations = initializeFaroMock.mock.calls.at(-1)?.[0].instrumentations;
expect(lastInstrumentations).toHaveLength(5);
expect(lastInstrumentations).toEqual(
expect.arrayContaining([
expect.any(SessionInstrumentation),
expect.any(UserActionInstrumentation),
expect.any(ErrorsInstrumentation),
expect.any(WebVitalsInstrumentation),
expect.any(ViewInstrumentation),
])
);
opts.tracingInstrumentalizationEnabled = true; opts.tracingInstrumentalizationEnabled = true;
new GrafanaJavascriptAgentBackend(opts); new GrafanaJavascriptAgentBackend(opts);
expect(initializeFaroMock.mock.calls[1][0].instrumentations?.length).toEqual(2); lastInstrumentations = initializeFaroMock.mock.calls.at(-1)?.[0].instrumentations;
expect(initializeFaroMock.mock.calls[1][0].instrumentations?.[0]).toBeInstanceOf(TracingInstrumentation); expect(lastInstrumentations).toHaveLength(6);
expect(initializeFaroMock.mock.calls[1][0].instrumentations?.[1]).toBeInstanceOf(SessionInstrumentation); expect(lastInstrumentations).toEqual(
expect.arrayContaining([
expect.any(SessionInstrumentation),
expect.any(UserActionInstrumentation),
expect.any(ErrorsInstrumentation),
expect.any(WebVitalsInstrumentation),
expect.any(ViewInstrumentation),
expect.any(TracingInstrumentation),
])
);
}); });
it('should use a beforeSend handler', () => { it('should use a beforeSend handler', () => {
@@ -1,23 +1,18 @@
import { BuildInfo, escapeRegex } from '@grafana/data'; import { BuildInfo, escapeRegex } from '@grafana/data';
import { BaseTransport, defaultInternalLoggerLevel } from '@grafana/faro-core'; import { BaseTransport, defaultInternalLoggerLevel, InternalLoggerLevel } from '@grafana/faro-core';
import { import {
initializeFaro, initializeFaro,
BrowserConfig, BrowserConfig,
ErrorsInstrumentation,
ConsoleInstrumentation,
WebVitalsInstrumentation,
SessionInstrumentation,
FetchTransport, FetchTransport,
type Instrumentation,
getWebInstrumentations, getWebInstrumentations,
Config, type Instrumentation,
} from '@grafana/faro-web-sdk'; } from '@grafana/faro-web-sdk';
import { TracingInstrumentation } from '@grafana/faro-web-tracing'; import { TracingInstrumentation } from '@grafana/faro-web-tracing';
import { EchoBackend, EchoEvent, EchoEventType } from '@grafana/runtime'; import { EchoBackend, EchoEvent, EchoEventType } from '@grafana/runtime';
import { EchoSrvTransport } from './EchoSrvTransport'; import { EchoSrvTransport } from './EchoSrvTransport';
import { beforeSendHandler } from './beforeSendHandler'; import { beforeSendHandler } from './beforeSendHandler';
import { GrafanaJavascriptAgentEchoEvent, User } from './types'; import { GrafanaJavascriptAgentEchoEvent } from './types';
function isCrossOriginIframe() { function isCrossOriginIframe() {
try { try {
@@ -27,15 +22,19 @@ function isCrossOriginIframe() {
} }
} }
export interface GrafanaJavascriptAgentBackendOptions extends BrowserConfig { export interface GrafanaJavascriptAgentBackendOptions {
buildInfo: BuildInfo; apiKey?: string;
customEndpoint: string; customEndpoint?: string;
user: User; internalLoggerLevel?: InternalLoggerLevel;
allInstrumentationsEnabled: boolean;
errorInstrumentalizationEnabled: boolean; webVitalsAttribution: boolean;
consoleInstrumentalizationEnabled: boolean; consoleInstrumentalizationEnabled: boolean;
webVitalsInstrumentalizationEnabled: boolean; performanceInstrumentalizationEnabled: boolean;
cspInstrumentalizationEnabled: boolean;
tracingInstrumentalizationEnabled: boolean; tracingInstrumentalizationEnabled: boolean;
buildInfo: BuildInfo;
userIdentifier: string;
ignoreUrls: RegExp[]; ignoreUrls: RegExp[];
} }
@@ -49,62 +48,52 @@ export class GrafanaJavascriptAgentBackend
implements EchoBackend<GrafanaJavascriptAgentEchoEvent, GrafanaJavascriptAgentBackendOptions> implements EchoBackend<GrafanaJavascriptAgentEchoEvent, GrafanaJavascriptAgentBackendOptions>
{ {
supportedEvents = [EchoEventType.GrafanaJavascriptAgent]; supportedEvents = [EchoEventType.GrafanaJavascriptAgent];
private faroInstance;
constructor(public options: GrafanaJavascriptAgentBackendOptions) { constructor(public options: GrafanaJavascriptAgentBackendOptions) {
// configure instrumentations. // configure instrumentations.
const instrumentations: Instrumentation[] = []; const instrumentations: Instrumentation[] = [
...getWebInstrumentations({
const ignoreUrls = [ captureConsole: options.consoleInstrumentalizationEnabled,
new RegExp(`.*${escapeRegex(options.customEndpoint)}.*`), enablePerformanceInstrumentation: options.performanceInstrumentalizationEnabled,
...TRACKING_URLS, enableContentSecurityPolicyInstrumentation: options.cspInstrumentalizationEnabled,
...options.ignoreUrls, }),
]; ];
if (options.tracingInstrumentalizationEnabled) {
instrumentations.push(new TracingInstrumentation());
}
const ignoreUrls = [...TRACKING_URLS, ...options.ignoreUrls];
if (options.customEndpoint) {
ignoreUrls.unshift(new RegExp(`.*${escapeRegex(options.customEndpoint)}.*`));
}
const transports: BaseTransport[] = [new EchoSrvTransport({ ignoreUrls })]; const transports: BaseTransport[] = [new EchoSrvTransport({ ignoreUrls })];
const consoleInstrumentationOptions: Config['consoleInstrumentation'] =
options.allInstrumentationsEnabled || options.consoleInstrumentalizationEnabled
? {
serializeErrors: true,
}
: {};
// If in cross origin iframe, default to writing to instance logging endpoint // If in cross origin iframe, default to writing to instance logging endpoint
if (options.customEndpoint && !isCrossOriginIframe()) { if (options.customEndpoint && !isCrossOriginIframe()) {
transports.push(new FetchTransport({ url: options.customEndpoint, apiKey: options.apiKey })); transports.push(new FetchTransport({ url: options.customEndpoint, apiKey: options.apiKey }));
} }
if (options.errorInstrumentalizationEnabled) {
instrumentations.push(new ErrorsInstrumentation());
}
if (options.consoleInstrumentalizationEnabled) {
instrumentations.push(new ConsoleInstrumentation());
}
if (options.webVitalsInstrumentalizationEnabled) {
instrumentations.push(new WebVitalsInstrumentation());
}
if (options.tracingInstrumentalizationEnabled) {
instrumentations.push(new TracingInstrumentation());
}
// session instrumentation must be added!
instrumentations.push(new SessionInstrumentation());
// initialize GrafanaJavascriptAgent so it can set up its hooks and start collecting errors // initialize GrafanaJavascriptAgent so it can set up its hooks and start collecting errors
const grafanaJavaScriptAgentOptions: BrowserConfig = { const grafanaJavaScriptAgentOptions: BrowserConfig = {
globalObjectKey: options.globalObjectKey || 'faro',
preventGlobalExposure: options.preventGlobalExposure || false,
app: { app: {
name: 'grafana-frontend', name: 'grafana-frontend',
version: options.buildInfo.version, version: options.buildInfo.version,
environment: options.buildInfo.env, environment: options.buildInfo.env,
}, },
instrumentations: options.allInstrumentationsEnabled
? [...getWebInstrumentations(), new TracingInstrumentation()] user: {
: instrumentations, id: options.userIdentifier,
consoleInstrumentation: consoleInstrumentationOptions, },
trackWebVitalsAttribution: options.webVitalsInstrumentalizationEnabled || options.allInstrumentationsEnabled,
instrumentations: instrumentations,
transports, transports,
consoleInstrumentation: {
serializeErrors: true,
},
trackWebVitalsAttribution: options.webVitalsAttribution,
ignoreErrors: [ ignoreErrors: [
'ResizeObserver loop limit exceeded', 'ResizeObserver loop limit exceeded',
'ResizeObserver loop completed', 'ResizeObserver loop completed',
@@ -118,19 +107,11 @@ export class GrafanaJavascriptAgentBackend
batching: { batching: {
sendTimeout: 1000, sendTimeout: 1000,
}, },
internalLoggerLevel: options.internalLoggerLevel || defaultInternalLoggerLevel,
beforeSend: beforeSendHandler, beforeSend: beforeSendHandler,
internalLoggerLevel: options.internalLoggerLevel ?? defaultInternalLoggerLevel,
}; };
this.faroInstance = initializeFaro(grafanaJavaScriptAgentOptions);
if (options.user) { initializeFaro(grafanaJavaScriptAgentOptions);
this.faroInstance.api.setUser({
id: options.user.id,
attributes: {
orgId: String(options.user.orgId) || '',
},
});
}
} }
// noop because the EchoSrvTransport registered in Faro will already broadcast all signals emitted by the Faro API // noop because the EchoSrvTransport registered in Faro will already broadcast all signals emitted by the Faro API
+10 -9
View File
@@ -97,17 +97,18 @@ async function initFaroBackend() {
registerEchoBackend( registerEchoBackend(
new GrafanaJavascriptAgentBackend({ new GrafanaJavascriptAgentBackend({
...config.grafanaJavascriptAgent,
app: {
version: config.buildInfo.version,
environment: config.buildInfo.env,
},
buildInfo: config.buildInfo, buildInfo: config.buildInfo,
user: { userIdentifier: contextSrv.user.analytics.identifier,
id: String(contextSrv.user?.id),
email: contextSrv.user?.email,
},
ignoreUrls: rudderstackUrls, ignoreUrls: rudderstackUrls,
apiKey: config.grafanaJavascriptAgent.apiKey,
customEndpoint: config.grafanaJavascriptAgent.customEndpoint,
consoleInstrumentalizationEnabled: config.grafanaJavascriptAgent.consoleInstrumentalizationEnabled,
performanceInstrumentalizationEnabled: config.grafanaJavascriptAgent.performanceInstrumentalizationEnabled,
cspInstrumentalizationEnabled: config.grafanaJavascriptAgent.cspInstrumentalizationEnabled,
tracingInstrumentalizationEnabled: config.grafanaJavascriptAgent.tracingInstrumentalizationEnabled,
webVitalsAttribution: config.grafanaJavascriptAgent.webVitalsAttribution,
internalLoggerLevel: config.grafanaJavascriptAgent.internalLoggerLevel,
}) })
); );
} }