Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Console instrumentation: send a Faro error for console.error logs #703

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 30 additions & 27 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,34 @@

## Next

- Improvement (`@grafana/faro-web-sdk`): The console instrumentation now sends an `Error` signal
instead of a `Log` signal for `console.error()` calls (#703).

## 1.10.2

- Fix (`@grafana/faro-web-tracing`): Enhance the xhr instrumentation to handle both URL objects and
strings seamlessly (#695).

## 1.10.1

- Enhancement (`@grafana/faro-web-sdk`): Isolated Faro instances now exclude the default collector
- Improvement (`@grafana/faro-web-sdk`): Isolated Faro instances now exclude the default collector
URLs of other instances by default (#684).
- Enhancement (`@grafana/faro-web-sdk`): The `pushError` API now automatically includes `error.cause`
- Improvement (`@grafana/faro-web-sdk`): The `pushError` API now automatically includes `error.cause`
in the Faro exception context (#688).

- Fix (`@grafana/faro-transport-otlp-http [experimental]`): add `service.namespace` attribute if set
(#687).

### Breaking

- Change (`@grafana/faro-transport-otlp-http [experimental]`): update semantic attributes
- Improvement (`@grafana/faro-transport-otlp-http [experimental]`): update semantic attributes
for browser (#684).
- `browser.user_agent` is replaced by `user_agent.original`
- `browser.os` is replaced by `browser.platform`

## 1.10.0

- Change (`@grafana/faro-web-sdk`): don't automatically send a `view_change` event for the default
- Improvement (`@grafana/faro-web-sdk`): don't automatically send a `view_change` event for the default
view (#647)

- Dependencies (`@grafana/faro-web-tracing`): upgrade otel deps (#670)
Expand Down Expand Up @@ -55,24 +58,24 @@

## 1.9.0

- Enhancement (`@grafana/faro-web-sdk`): Provide and option to pass a correction timestamp via the
- Improvement (`@grafana/faro-web-sdk`): Provide and option to pass a correction timestamp via the
Faro API (#658).

- Fix (`@grafana/faro-web-sdk`): Adjust the timestamp of a navigation or resource event to reflect
the actual time the event occurred, rather than the signal creation time. (#658).

- Change: (`@grafana/faro-web-tracing`) The underlying XHR and Fetch instrumentation are now
- Improvement: (`@grafana/faro-web-tracing`) The underlying XHR and Fetch instrumentation are now
configured to ignore network events by default. This behavior can be enabled back through the
options in the WebTracing class.

## 1.8.2

- Enhancement (`@grafana/faro-web-tracing`): ensure that span status is always set to error for
- Improvement (`@grafana/faro-web-tracing`): ensure that span status is always set to error for
erroneous xhr requests (#644).

## 1.8.1

- Enhancement (`@grafana/faro-web-tracing`): ensure that span status is always set to error for
- Improvement (`@grafana/faro-web-tracing`): ensure that span status is always set to error for
erroneous fetch requests (#641).

## 1.8.0
Expand All @@ -81,9 +84,9 @@
- Feature (`@grafana/faro-web-sdk`): set span context for navigation events (#608).
- Feature (`@grafana/faro-react`): add helper functions to initialize React Router integration (#622).

- Enhancement (`@grafana/faro-web-sdk`): Auto extend a session if the Faro receiver indicates that a
- Improvement (`@grafana/faro-web-sdk`): Auto extend a session if the Faro receiver indicates that a
session is invalid (#591).
- Enhancement (`@grafana/faro-web-tracing`): provide the `app.namespace` attribute in the app meta
- Improvement (`@grafana/faro-web-tracing`): provide the `app.namespace` attribute in the app meta
which is attached as `service.namespace` to the resource attributes object (#627).

- Dependencies (`@grafana/faro-web-tracing`): upgrade otel deps (#621).
Expand All @@ -106,32 +109,32 @@

## 1.7.1

- Enhancement (`@grafana/faro-core`): Config has now a parameter `logArgsSerializer` to set a custom serializer for
- Improvement (`@grafana/faro-core`): Config has now a parameter `logArgsSerializer` to set a custom serializer for
log arguments (#564). This is useful if log message args are complex and might produce `[object Object]` in the logs.
- Fix (`@grafana/faro-web-tracing`): Fix an import issue causing builds to fail (#581).
- Fix (`@grafana/faro-react`): Fix type issues in react data route wrapper `withFaroRouterInstrumentation` (#584).

## 1.7.0

- Enhancement (`@grafana/faro-web-sdk`): provide option to globally
- Improvement (`@grafana/faro-web-sdk`): provide option to globally
exclude endpoint URLs from being tracked. This applies to the following instrumentations:
performance, xhr, fetch and web-tracing (#554).
- Update (`faro demo`): Update Demo to pin docker images and replace Cortex by Mimir (#563).
- Enhancement (`faro demo`): Migrate demo Grafana agent to Grafana alloy
- Improvement (`faro demo`): Migrate demo Grafana agent to Grafana alloy

## 1.6.0

- Docs(`@grafana/faro-web-sdk`, `@grafana/faro-web-tracing`): Remove pre-release warning (#550).
- Change (`@grafana/faro-web-tracing`): Remove redundant DocumentLoadInstrumentation.
- Improvement (`@grafana/faro-web-tracing`): Remove redundant DocumentLoadInstrumentation.
Faro tracks page load data by default (#551).
- Change(`@grafana/faro-web-sdk`): Performance instrumentation only tracks resource entries initiated
- Improvement(`@grafana/faro-web-sdk`): Performance instrumentation only tracks resource entries initiated
by calls to the `fetch` method or `xhr-html requests`. To track all resource entries set
`trackResources: true` (#560).

## 1.5.1

- Feature(`@grafana/faro-web-sdk`): Add parsing time to FaroNavigationTiming (#541).
- Change ()(`@grafana/faro-web-sdk`): Get rid of structureClone. It caused breakage in some
- Improvement ()(`@grafana/faro-web-sdk`): Get rid of structureClone. It caused breakage in some
sandboxed environments because of injected proxy objects (#536).
- Feat(`@grafana/faro-web-sdk`): Add K6 test ID to K6 meta if available in window.k6 object (#531).

Expand All @@ -152,16 +155,16 @@

## 1.4.1

- Enhancement (`@grafana/faro-web-tracing`): Dedupe Faro trace events (#507).
- Improvement (`@grafana/faro-web-tracing`): Dedupe Faro trace events (#507).

## 1.4.0

- Feat (`@grafana/faro-web-sdk`): Enable Faro Navigation and Resource timings instrumentation by default (#482).
- Enhancement (`@grafana/faro-web-tracing`): Send a dedicated Faro event for traces of kind=client (#499).
- Improvement (`@grafana/faro-web-tracing`): Send a dedicated Faro event for traces of kind=client (#499).

## 1.3.9

- Enhancement (`@grafana/faro-web-sdk`): add `duration` property in `faro.performance.resource` timings and
- Improvement (`@grafana/faro-web-sdk`): add `duration` property in `faro.performance.resource` timings and
rename property `totalNavigationTime` to `duration` in `faro.performance.navigation` timings (#490).
- Fix (`@grafana/faro-web-sdk`): crash when navigator.userAgentData is undefined (#494).

Expand All @@ -171,17 +174,17 @@

## 1.3.7

- Enhancement (`@grafana/faro-web-sdk`): add response time to performance timings (#465).
- Improvement (`@grafana/faro-web-sdk`): add response time to performance timings (#465).
- Deps (`@grafana/faro-web-tracing`): Update `instrumentation-document-load` which prevents build.
from breaking (#467).

## 1.3.6

- Feature preview (`@grafana/faro-web-sdk`): instrument navigation and resource timings. As long as
this feature is in preview it is disabled by default (#434)
- Enhancement (`@grafana/faro-web-tracing`): Automatically add the value of the MetaApp environment
- Improvement (`@grafana/faro-web-tracing`): Automatically add the value of the MetaApp environment
property to the resource attributes `deployment.environment` property (#453)
- Change (`@grafana/faro-web-sdk`): change storage key prefix for Faro session to use reverse domain
- Improvement (`@grafana/faro-web-sdk`): change storage key prefix for Faro session to use reverse domain
notation (#432)
- Fix (`@grafana/faro-core`): make check for presence of Event more robust (#436)

Expand Down Expand Up @@ -229,16 +232,16 @@
- Deps: upgrade OTEL dependencies, remove outdated resolutions (#391).
- Fix (Web Tracing): send otel timings, like timeUnixNano, as string instead in LongBits format (#391).
- Feat: session based sampling (#385).
- Change: Send better attributes with the view and route transition events to contain information about
- Improvement: Send better attributes with the view and route transition events to contain information about
the previous route or view (`from*`) and the destination route or view (`to*`) (#397).
- Breaking❗️: React Instrumentation, the route transition event is renamed from `routeChange` to
`route_change`. The `url` and `route` attributes sent with the event are renamed to `toRoute` and
`toUrl`.(#397).

## 1.2.8

- Change: Custom x-faro-session-id header will now be added to legacy sessions as well (#384).
- Change: Lower maxSessionPersistenceTime for tracked sessions and export tooling to make it easier
- Improvement: Custom x-faro-session-id header will now be added to legacy sessions as well (#384).
- Improvement: Lower maxSessionPersistenceTime for tracked sessions and export tooling to make it easier
to manually remove a persisted session (#387)

## 1.2.7
Expand All @@ -249,8 +252,8 @@

- Feat: Add x-faro-session header to identify client session id to server
for fetch and xhr instrumentations (#377)
- Change (): Always send x-faro-session-id header, independent of the chosen session management (#381).
- Change: If new session management is used, send dedicated session lifecycle events to reflect if a
- Improvement (): Always send x-faro-session-id header, independent of the chosen session management (#381).
- Improvement: If new session management is used, send dedicated session lifecycle events to reflect if a
new session is started, a session is resume or extended (#380)

## 1.2.5
Expand Down
15 changes: 10 additions & 5 deletions cypress/e2e/demo/logs.cy.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { LogEvent, LogLevel } from '@grafana/faro-core';
import { ExceptionEvent, LogEvent, LogLevel } from '@grafana/faro-core';

context('Logs', () => {
context('Console logs', () => {
[LogLevel.INFO, LogLevel.WARN, LogLevel.ERROR].forEach((level) => {
it(`will capture ${level} level`, () => {
cy.interceptCollector((body) => {
const item = body.logs?.find(
(item: LogEvent) => item?.level === level && item?.message === `This is a console ${level} message`
);
let item =
level === 'error'
? body.exceptions?.find((item: ExceptionEvent) => item?.value === `This is a console ${level} message`)
: body.logs?.find(
(item: LogEvent) => item?.level === level && item?.message === `This is a console ${level} message`
);

console.log('item :>> ', item);

return item != null ? 'log' : undefined;
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { ExceptionEvent, initializeFaro, TransportItem } from '@grafana/faro-core';
import { mockConfig, MockTransport } from '@grafana/faro-core/src/testUtils';

import { makeCoreConfig } from '../../config';

import { ConsoleInstrumentation } from './instrumentation';

describe('ConsoleInstrumentation', () => {
afterEach(() => {
jest.resetAllMocks();
jest.restoreAllMocks();
});

it('send a faro error when console.error is called', () => {
const mockTransport = new MockTransport();

initializeFaro(
makeCoreConfig(
mockConfig({
transports: [mockTransport],
instrumentations: [new ConsoleInstrumentation()],
unpatchedConsole: {
error: jest.fn(),
} as unknown as Console,
})
)!
);

console.error('console.error no 1');
console.error('with object', { foo: 'bar', baz: 'bam' });

expect(mockTransport.items).toHaveLength(2);

expect((mockTransport.items[0] as TransportItem<ExceptionEvent>)?.payload.type).toBe('Error');
expect((mockTransport.items[0] as TransportItem<ExceptionEvent>)?.payload.value).toBe('console.error no 1');
expect((mockTransport.items[1] as TransportItem<ExceptionEvent>)?.payload.type).toBe('Error');
expect((mockTransport.items[1] as TransportItem<ExceptionEvent>)?.payload.value).toBe(
'with object {"foo":"bar","baz":"bam"}'
);
});
});
10 changes: 8 additions & 2 deletions packages/web-sdk/src/instrumentations/console/instrumentation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { allLogLevels, BaseInstrumentation, LogLevel, VERSION } from '@grafana/faro-core';
import { allLogLevels, BaseInstrumentation, isArray, isObject, LogLevel, VERSION } from '@grafana/faro-core';

import type { ConsoleInstrumentationOptions } from './types';

Expand All @@ -21,7 +21,13 @@ export class ConsoleInstrumentation extends BaseInstrumentation {
/* eslint-disable-next-line no-console */
console[level] = (...args) => {
try {
this.api.pushLog(args, { level });
if (level === LogLevel.ERROR) {
this.api.pushError(
new Error(args.map((arg) => (isObject(arg) || isArray(arg) ? JSON.stringify(arg) : arg)).join(' '))
);
} else {
this.api.pushLog(args, { level });
}
} catch (err) {
this.logError(err);
} finally {
Expand Down