mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Chore: Switch Grafana to using faro libraries (#58186)
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { BaseTransport, TransportItem } from '@grafana/agent-core';
|
||||
import { getEchoSrv, EchoEventType } from '@grafana/runtime';
|
||||
import { BaseTransport, TransportItem } from '@grafana/faro-core';
|
||||
import { getEchoSrv, EchoEventType, config } from '@grafana/runtime';
|
||||
export class EchoSrvTransport extends BaseTransport {
|
||||
readonly name: string = 'EchoSrvTransport';
|
||||
readonly version: string = config.buildInfo.version;
|
||||
send(event: TransportItem) {
|
||||
getEchoSrv().addEvent({
|
||||
type: EchoEventType.GrafanaJavascriptAgent,
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { BaseTransport } from '@grafana/agent-core';
|
||||
import { FetchTransport, initializeAgent } from '@grafana/agent-web';
|
||||
import { BuildInfo } from '@grafana/data';
|
||||
import { GrafanaEdition } from '@grafana/data/src/types/config';
|
||||
import { BaseTransport, Instrumentation, InternalLoggerLevel } from '@grafana/faro-core';
|
||||
import { FetchTransport, initializeFaro } from '@grafana/faro-web-sdk';
|
||||
import { EchoEventType, EchoMeta } from '@grafana/runtime';
|
||||
|
||||
import { GrafanaJavascriptAgentBackend, GrafanaJavascriptAgentBackendOptions } from './GrafanaJavascriptAgentBackend';
|
||||
import { GrafanaJavascriptAgentEchoEvent } from './types';
|
||||
|
||||
jest.mock('@grafana/agent-web', () => {
|
||||
const originalModule = jest.requireActual('@grafana/agent-web');
|
||||
jest.mock('@grafana/faro-web-sdk', () => {
|
||||
const originalModule = jest.requireActual('@grafana/faro-web-sdk');
|
||||
return {
|
||||
__esModule: true,
|
||||
...originalModule,
|
||||
initializeAgent: jest.fn(),
|
||||
initializeFaro: jest.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -52,8 +52,8 @@ describe('GrafanaJavascriptAgentEchoBackend', () => {
|
||||
|
||||
it('will set up FetchTransport if customEndpoint is provided', async () => {
|
||||
// arrange
|
||||
const originalModule = jest.requireActual('@grafana/agent-web');
|
||||
jest.mocked(initializeAgent).mockImplementation(originalModule.initializeAgent);
|
||||
const originalModule = jest.requireActual('@grafana/faro-web-sdk');
|
||||
jest.mocked(initializeFaro).mockImplementation(originalModule.initializeFaro);
|
||||
|
||||
//act
|
||||
const backend = new GrafanaJavascriptAgentBackend(options);
|
||||
@@ -66,6 +66,19 @@ describe('GrafanaJavascriptAgentEchoBackend', () => {
|
||||
it('will initialize GrafanaJavascriptAgent and set user', async () => {
|
||||
// arrange
|
||||
const mockedSetUser = jest.fn();
|
||||
const mockedInstrumentationsForConfig: Instrumentation[] = [];
|
||||
const mockedInstrumentations = {
|
||||
add: jest.fn(),
|
||||
instrumentations: mockedInstrumentationsForConfig,
|
||||
remove: jest.fn(),
|
||||
};
|
||||
const mockedInternalLogger = {
|
||||
prefix: 'Faro',
|
||||
debug: jest.fn(),
|
||||
info: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
error: jest.fn(),
|
||||
};
|
||||
const mockedAgent = () => {
|
||||
return {
|
||||
api: {
|
||||
@@ -75,24 +88,38 @@ describe('GrafanaJavascriptAgentEchoBackend', () => {
|
||||
pushError: jest.fn(),
|
||||
pushMeasurement: jest.fn(),
|
||||
pushTraces: jest.fn(),
|
||||
pushEvent: jest.fn(),
|
||||
initOTEL: jest.fn(),
|
||||
getOTEL: jest.fn(),
|
||||
getTraceContext: jest.fn(),
|
||||
changeStacktraceParser: jest.fn(),
|
||||
getStacktraceParser: jest.fn(),
|
||||
isOTELInitialized: jest.fn(),
|
||||
setSession: jest.fn(),
|
||||
getSession: jest.fn(),
|
||||
resetUser: jest.fn(),
|
||||
resetSession: jest.fn(),
|
||||
},
|
||||
config: {
|
||||
globalObjectKey: '',
|
||||
instrumentations: [],
|
||||
preventGlobalExposure: false,
|
||||
transports: [],
|
||||
instrumentations: mockedInstrumentationsForConfig,
|
||||
metas: [],
|
||||
parseStacktrace: jest.fn(),
|
||||
app: jest.fn(),
|
||||
paused: false,
|
||||
dedupe: true,
|
||||
isolate: false,
|
||||
internalLoggerLevel: InternalLoggerLevel.ERROR,
|
||||
unpatchedConsole: { ...console },
|
||||
},
|
||||
metas: {
|
||||
add: jest.fn(),
|
||||
remove: jest.fn(),
|
||||
value: {},
|
||||
addListener: jest.fn(),
|
||||
removeListener: jest.fn(),
|
||||
},
|
||||
transports: {
|
||||
add: jest.fn(),
|
||||
@@ -100,18 +127,27 @@ describe('GrafanaJavascriptAgentEchoBackend', () => {
|
||||
transports: [],
|
||||
pause: jest.fn(),
|
||||
unpause: jest.fn(),
|
||||
addBeforeSendHooks: jest.fn(),
|
||||
addIgnoreErrorsPatterns: jest.fn(),
|
||||
getBeforeSendHooks: jest.fn(),
|
||||
isPaused: jest.fn(),
|
||||
remove: jest.fn(),
|
||||
removeBeforeSendHooks: jest.fn(),
|
||||
},
|
||||
pause: jest.fn(),
|
||||
unpause: jest.fn(),
|
||||
instrumentations: mockedInstrumentations,
|
||||
internalLogger: mockedInternalLogger,
|
||||
unpatchedConsole: { ...console },
|
||||
};
|
||||
};
|
||||
jest.mocked(initializeAgent).mockImplementation(mockedAgent);
|
||||
jest.mocked(initializeFaro).mockImplementation(mockedAgent);
|
||||
|
||||
//act
|
||||
new GrafanaJavascriptAgentBackend(options);
|
||||
|
||||
//assert
|
||||
expect(initializeAgent).toHaveBeenCalledTimes(1);
|
||||
expect(initializeFaro).toHaveBeenCalledTimes(1);
|
||||
expect(mockedSetUser).toHaveBeenCalledTimes(1);
|
||||
expect(mockedSetUser).toHaveBeenCalledWith({
|
||||
id: '504',
|
||||
@@ -124,6 +160,19 @@ describe('GrafanaJavascriptAgentEchoBackend', () => {
|
||||
it('will forward events to transports', async () => {
|
||||
//arrange
|
||||
const mockedSetUser = jest.fn();
|
||||
const mockedInstrumentationsForConfig: Instrumentation[] = [];
|
||||
const mockedInstrumentations = {
|
||||
add: jest.fn(),
|
||||
instrumentations: mockedInstrumentationsForConfig,
|
||||
remove: jest.fn(),
|
||||
};
|
||||
const mockedInternalLogger = {
|
||||
prefix: 'Faro',
|
||||
debug: jest.fn(),
|
||||
info: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
error: jest.fn(),
|
||||
};
|
||||
const mockedAgent = () => {
|
||||
return {
|
||||
api: {
|
||||
@@ -133,24 +182,38 @@ describe('GrafanaJavascriptAgentEchoBackend', () => {
|
||||
pushError: jest.fn(),
|
||||
pushMeasurement: jest.fn(),
|
||||
pushTraces: jest.fn(),
|
||||
pushEvent: jest.fn(),
|
||||
initOTEL: jest.fn(),
|
||||
getOTEL: jest.fn(),
|
||||
getTraceContext: jest.fn(),
|
||||
changeStacktraceParser: jest.fn(),
|
||||
getStacktraceParser: jest.fn(),
|
||||
isOTELInitialized: jest.fn(),
|
||||
setSession: jest.fn(),
|
||||
getSession: jest.fn(),
|
||||
resetUser: jest.fn(),
|
||||
resetSession: jest.fn(),
|
||||
},
|
||||
config: {
|
||||
globalObjectKey: '',
|
||||
instrumentations: [],
|
||||
preventGlobalExposure: false,
|
||||
transports: [],
|
||||
instrumentations: mockedInstrumentationsForConfig,
|
||||
metas: [],
|
||||
parseStacktrace: jest.fn(),
|
||||
app: jest.fn(),
|
||||
paused: false,
|
||||
dedupe: true,
|
||||
isolate: false,
|
||||
internalLoggerLevel: InternalLoggerLevel.ERROR,
|
||||
unpatchedConsole: { ...console },
|
||||
},
|
||||
metas: {
|
||||
add: jest.fn(),
|
||||
remove: jest.fn(),
|
||||
value: {},
|
||||
addListener: jest.fn(),
|
||||
removeListener: jest.fn(),
|
||||
},
|
||||
transports: {
|
||||
add: jest.fn(),
|
||||
@@ -158,13 +221,22 @@ describe('GrafanaJavascriptAgentEchoBackend', () => {
|
||||
transports: [],
|
||||
pause: jest.fn(),
|
||||
unpause: jest.fn(),
|
||||
addBeforeSendHooks: jest.fn(),
|
||||
addIgnoreErrorsPatterns: jest.fn(),
|
||||
getBeforeSendHooks: jest.fn(),
|
||||
isPaused: jest.fn(),
|
||||
remove: jest.fn(),
|
||||
removeBeforeSendHooks: jest.fn(),
|
||||
},
|
||||
pause: jest.fn(),
|
||||
unpause: jest.fn(),
|
||||
instrumentations: mockedInstrumentations,
|
||||
internalLogger: mockedInternalLogger,
|
||||
unpatchedConsole: { ...console },
|
||||
};
|
||||
};
|
||||
|
||||
jest.mocked(initializeAgent).mockImplementation(mockedAgent);
|
||||
jest.mocked(initializeFaro).mockImplementation(mockedAgent);
|
||||
const backend = new GrafanaJavascriptAgentBackend({
|
||||
...options,
|
||||
preventGlobalExposure: true,
|
||||
@@ -195,8 +267,8 @@ describe('GrafanaJavascriptAgentEchoBackend', () => {
|
||||
// // use actual GrafanaJavascriptAgent & mock window.fetch
|
||||
|
||||
// // arrange
|
||||
// const originalModule = jest.requireActual('@grafana/agent-web');
|
||||
// jest.mocked(initializeAgent).mockImplementation(originalModule.initializeAgent);
|
||||
// const originalModule = jest.requireActual('@grafana/faro-web-sdk');
|
||||
// jest.mocked(initializeFaro).mockImplementation(originalModule.initializeFaro);
|
||||
// const fetchSpy = (window.fetch = jest.fn());
|
||||
// fetchSpy.mockResolvedValue({ status: 200 } as Response);
|
||||
// const echo = new Echo({ debug: true });
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { BaseTransport } from '@grafana/agent-core';
|
||||
import { BuildInfo } from '@grafana/data';
|
||||
import { BaseTransport } from '@grafana/faro-core';
|
||||
import {
|
||||
initializeAgent,
|
||||
initializeFaro,
|
||||
defaultMetas,
|
||||
BrowserConfig,
|
||||
ErrorsInstrumentation,
|
||||
ConsoleInstrumentation,
|
||||
WebVitalsInstrumentation,
|
||||
FetchTransport,
|
||||
} from '@grafana/agent-web';
|
||||
import { BuildInfo } from '@grafana/data';
|
||||
} from '@grafana/faro-web-sdk';
|
||||
import { EchoBackend, EchoEvent, EchoEventType } from '@grafana/runtime';
|
||||
|
||||
import { EchoSrvTransport } from './EchoSrvTransport';
|
||||
@@ -27,7 +27,7 @@ export class GrafanaJavascriptAgentBackend
|
||||
implements EchoBackend<GrafanaJavascriptAgentEchoEvent, GrafanaJavascriptAgentBackendOptions>
|
||||
{
|
||||
supportedEvents = [EchoEventType.GrafanaJavascriptAgent];
|
||||
private agentInstance;
|
||||
private faroInstance;
|
||||
transports: BaseTransport[];
|
||||
|
||||
constructor(public options: GrafanaJavascriptAgentBackendOptions) {
|
||||
@@ -51,7 +51,7 @@ export class GrafanaJavascriptAgentBackend
|
||||
|
||||
// initialize GrafanaJavascriptAgent so it can set up its hooks and start collecting errors
|
||||
const grafanaJavaScriptAgentOptions: BrowserConfig = {
|
||||
globalObjectKey: options.globalObjectKey || 'grafanaAgent',
|
||||
globalObjectKey: options.globalObjectKey || 'faro',
|
||||
preventGlobalExposure: options.preventGlobalExposure || false,
|
||||
app: {
|
||||
version: options.buildInfo.version,
|
||||
@@ -74,10 +74,10 @@ export class GrafanaJavascriptAgentBackend
|
||||
},
|
||||
],
|
||||
};
|
||||
this.agentInstance = initializeAgent(grafanaJavaScriptAgentOptions);
|
||||
this.faroInstance = initializeFaro(grafanaJavaScriptAgentOptions);
|
||||
|
||||
if (options.user) {
|
||||
this.agentInstance.api.setUser({
|
||||
this.faroInstance.api.setUser({
|
||||
id: options.user.id,
|
||||
attributes: {
|
||||
orgId: String(options.user.orgId) || '',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { agent, LogLevel as GrafanaLogLevel } from '@grafana/agent-web';
|
||||
import { faro, LogLevel as GrafanaLogLevel } from '@grafana/faro-web-sdk';
|
||||
import { config } from '@grafana/runtime/src';
|
||||
|
||||
export const LogMessages = {
|
||||
@@ -15,7 +15,7 @@ export const LogMessages = {
|
||||
// logInfo from '@grafana/runtime' should be used, but it doesn't handle Grafana JS Agent and Sentry correctly
|
||||
export function logInfo(message: string, context: Record<string, string | number> = {}) {
|
||||
if (config.grafanaJavascriptAgent.enabled) {
|
||||
agent.api.pushLog([message], {
|
||||
faro.api.pushLog([message], {
|
||||
level: GrafanaLogLevel.INFO,
|
||||
context: { ...context, module: 'Alerting' },
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user