Skip to content

Commit 7912989

Browse files
committed
build: Switch @sentry/tracing to using eslint
1 parent 1d4b9cd commit 7912989

20 files changed

+262
-234
lines changed

.eslintignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# THIS IS A TEMPORARY FILE
22
# THIS WILL BE REMOVED AFTER WE FINISH ESLINT UPGRADE
33

4-
packages/tracing/**/*
54
packages/typescript/**/*

packages/tracing/.eslintrc.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
module.exports = {
2+
root: true,
3+
env: {
4+
es6: true,
5+
},
6+
parserOptions: {
7+
ecmaVersion: 2018,
8+
},
9+
extends: ['../../.eslintrc.js'],
10+
ignorePatterns: ['build/**/*', 'dist/**/*', 'esm/**/*', 'examples/**/*', 'scripts/**/*'],
11+
overrides: [
12+
{
13+
files: ['*.ts', '*.tsx', '*.d.ts'],
14+
parserOptions: {
15+
project: './tsconfig.json',
16+
},
17+
},
18+
{
19+
files: ['test/**/*'],
20+
rules: {
21+
'@typescript-eslint/no-explicit-any': 'off',
22+
'@typescript-eslint/no-non-null-assertion': 'off',
23+
},
24+
},
25+
],
26+
};

packages/tracing/package.json

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,12 @@
5252
"build:watch:esm": "tsc -p tsconfig.esm.json -w --preserveWatchOutput",
5353
"clean": "rimraf dist coverage build esm",
5454
"link:yarn": "yarn link",
55-
"lint": "run-s lint:prettier lint:tslint",
55+
"lint": "run-s lint:prettier lint:eslint",
5656
"lint:prettier": "prettier-check \"{src,test}/**/*.ts\"",
57-
"lint:tslint": "tslint -t stylish -p .",
58-
"lint:tslint:json": "tslint --format json -p . | tee lint-results.json",
59-
"fix": "run-s fix:tslint fix:prettier",
57+
"lint:eslint": "eslint . --cache --cache-location '../../eslintcache/' --format stylish",
58+
"fix": "run-s fix:eslint fix:prettier",
6059
"fix:prettier": "prettier --write \"{src,test}/**/*.ts\"",
61-
"fix:tslint": "tslint --fix -t stylish -p .",
60+
"fix:eslint": "eslint . --format stylish --fix",
6261
"test": "jest",
6362
"test:watch": "jest --watch"
6463
},

packages/tracing/src/browser/backgroundtab.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { getGlobalObject, logger } from '@sentry/utils';
22

33
import { IdleTransaction } from '../idletransaction';
44
import { SpanStatus } from '../spanstatus';
5-
65
import { getActiveTransaction } from './utils';
76

87
const global = getGlobalObject<Window>();

packages/tracing/src/browser/browsertracing.ts

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { startIdleTransaction } from '../hubextensions';
66
import { DEFAULT_IDLE_TIMEOUT, IdleTransaction } from '../idletransaction';
77
import { Span } from '../span';
88
import { SpanStatus } from '../spanstatus';
9-
109
import { registerBackgroundTabDetection } from './backgroundtab';
1110
import { registerErrorInstrumentation } from './errors';
1211
import { MetricsInstrumentation } from './metrics';
@@ -45,24 +44,6 @@ export interface BrowserTracingOptions extends RequestInstrumentationOptions {
4544
*/
4645
startTransactionOnPageLoad: boolean;
4746

48-
/**
49-
* beforeNavigate is called before a pageload/navigation transaction is created and allows for users
50-
* to set custom transaction context. Defaults behaviour is to return `window.location.pathname`.
51-
*
52-
* If undefined is returned, a pageload/navigation transaction will not be created.
53-
*/
54-
beforeNavigate(context: TransactionContext): TransactionContext | undefined;
55-
56-
/**
57-
* Instrumentation that creates routing change transactions. By default creates
58-
* pageload and navigation transactions.
59-
*/
60-
routingInstrumentation<T extends TransactionType>(
61-
startTransaction: (context: TransactionContext) => T | undefined,
62-
startTransactionOnPageLoad?: boolean,
63-
startTransactionOnLocationChange?: boolean,
64-
): void;
65-
6647
/**
6748
* The maximum duration of a transaction before it will be marked as "deadline_exceeded".
6849
* If you never want to mark a transaction set it to 0.
@@ -80,6 +61,24 @@ export interface BrowserTracingOptions extends RequestInstrumentationOptions {
8061
* Default: true
8162
*/
8263
markBackgroundTransactions: boolean;
64+
65+
/**
66+
* beforeNavigate is called before a pageload/navigation transaction is created and allows for users
67+
* to set custom transaction context. Defaults behaviour is to return `window.location.pathname`.
68+
*
69+
* If undefined is returned, a pageload/navigation transaction will not be created.
70+
*/
71+
beforeNavigate(context: TransactionContext): TransactionContext | undefined;
72+
73+
/**
74+
* Instrumentation that creates routing change transactions. By default creates
75+
* pageload and navigation transactions.
76+
*/
77+
routingInstrumentation<T extends TransactionType>(
78+
startTransaction: (context: TransactionContext) => T | undefined,
79+
startTransactionOnPageLoad?: boolean,
80+
startTransactionOnLocationChange?: boolean,
81+
): void;
8382
}
8483

8584
/**
@@ -154,6 +153,7 @@ export class BrowserTracing implements Integration {
154153
);
155154
}
156155

156+
// eslint-disable-next-line @typescript-eslint/unbound-method
157157
const {
158158
routingInstrumentation,
159159
startTransactionOnLocationChange,
@@ -188,6 +188,7 @@ export class BrowserTracing implements Integration {
188188
return undefined;
189189
}
190190

191+
// eslint-disable-next-line @typescript-eslint/unbound-method
191192
const { beforeNavigate, idleTimeout, maxTransactionDuration } = this.options;
192193

193194
// if beforeNavigate returns undefined, we should not start a transaction.

packages/tracing/src/browser/errors.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { addInstrumentationHandler, logger } from '@sentry/utils';
22

33
import { SpanStatus } from '../spanstatus';
4-
54
import { getActiveTransaction } from './utils';
65

76
/**

packages/tracing/src/browser/metrics.ts

Lines changed: 71 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
12
import { SpanContext } from '@sentry/types';
23
import { getGlobalObject, logger } from '@sentry/utils';
34

45
import { Span } from '../span';
56
import { Transaction } from '../transaction';
6-
77
import { msToSec } from './utils';
88

99
const global = getGlobalObject<Window>();
@@ -14,71 +14,6 @@ export class MetricsInstrumentation {
1414

1515
private _performanceCursor: number = 0;
1616

17-
private _forceLCP = () => {
18-
/* No-op, replaced later if LCP API is available. */
19-
return;
20-
};
21-
22-
/** Starts tracking the Largest Contentful Paint on the current page. */
23-
private _trackLCP(): void {
24-
// Based on reference implementation from https://web.dev/lcp/#measure-lcp-in-javascript.
25-
// Use a try/catch instead of feature detecting `largest-contentful-paint`
26-
// support, since some browsers throw when using the new `type` option.
27-
// https://bugs.webkit.org/show_bug.cgi?id=209216
28-
try {
29-
// Keep track of whether (and when) the page was first hidden, see:
30-
// https://github.com/w3c/page-visibility/issues/29
31-
// NOTE: ideally this check would be performed in the document <head>
32-
// to avoid cases where the visibility state changes before this code runs.
33-
let firstHiddenTime = document.visibilityState === 'hidden' ? 0 : Infinity;
34-
document.addEventListener(
35-
'visibilitychange',
36-
event => {
37-
firstHiddenTime = Math.min(firstHiddenTime, event.timeStamp);
38-
},
39-
{ once: true },
40-
);
41-
42-
const updateLCP = (entry: PerformanceEntry) => {
43-
// Only include an LCP entry if the page wasn't hidden prior to
44-
// the entry being dispatched. This typically happens when a page is
45-
// loaded in a background tab.
46-
if (entry.startTime < firstHiddenTime) {
47-
// NOTE: the `startTime` value is a getter that returns the entry's
48-
// `renderTime` value, if available, or its `loadTime` value otherwise.
49-
// The `renderTime` value may not be available if the element is an image
50-
// that's loaded cross-origin without the `Timing-Allow-Origin` header.
51-
this._lcp = {
52-
// @ts-ignore
53-
...(entry.id && { elementId: entry.id }),
54-
// @ts-ignore
55-
...(entry.size && { elementSize: entry.size }),
56-
value: entry.startTime,
57-
};
58-
}
59-
};
60-
61-
// Create a PerformanceObserver that calls `updateLCP` for each entry.
62-
const po = new PerformanceObserver(entryList => {
63-
entryList.getEntries().forEach(updateLCP);
64-
});
65-
66-
// Observe entries of type `largest-contentful-paint`, including buffered entries,
67-
// i.e. entries that occurred before calling `observe()` below.
68-
po.observe({
69-
buffered: true,
70-
// @ts-ignore
71-
type: 'largest-contentful-paint',
72-
});
73-
74-
this._forceLCP = () => {
75-
po.takeRecords().forEach(updateLCP);
76-
};
77-
} catch (e) {
78-
// Do nothing if the browser doesn't support this API.
79-
}
80-
}
81-
8217
public constructor() {
8318
if (global && global.performance) {
8419
if (global.performance.mark) {
@@ -112,7 +47,7 @@ export class MetricsInstrumentation {
11247
let entryScriptSrc: string | undefined;
11348

11449
if (global.document) {
115-
// tslint:disable-next-line: prefer-for-of
50+
// eslint-disable-next-line @typescript-eslint/prefer-for-of
11651
for (let i = 0; i < document.scripts.length; i++) {
11752
// We go through all scripts on the page and look for 'data-entry'
11853
// We remember the name and measure the time between this script finished loading and
@@ -144,20 +79,22 @@ export class MetricsInstrumentation {
14479
break;
14580
case 'mark':
14681
case 'paint':
147-
case 'measure':
82+
case 'measure': {
14883
const startTimestamp = addMeasureSpans(transaction, entry, startTime, duration, timeOrigin);
14984
if (tracingInitMarkStartTime === undefined && entry.name === 'sentry-tracing-init') {
15085
tracingInitMarkStartTime = startTimestamp;
15186
}
15287
break;
153-
case 'resource':
88+
}
89+
case 'resource': {
15490
const resourceName = (entry.name as string).replace(window.location.origin, '');
15591
const endTimestamp = addResourceSpans(transaction, entry, resourceName, startTime, duration, timeOrigin);
15692
// We remember the entry script end time to calculate the difference to the first init mark
15793
if (entryScriptStartTimestamp === undefined && (entryScriptSrc || '').indexOf(resourceName) > -1) {
15894
entryScriptStartTimestamp = endTimestamp;
15995
}
16096
break;
97+
}
16198
default:
16299
// Ignore other entry types.
163100
}
@@ -174,6 +111,71 @@ export class MetricsInstrumentation {
174111

175112
this._performanceCursor = Math.max(performance.getEntries().length - 1, 0);
176113
}
114+
115+
private _forceLCP: () => void = () => {
116+
/* No-op, replaced later if LCP API is available. */
117+
return;
118+
};
119+
120+
/** Starts tracking the Largest Contentful Paint on the current page. */
121+
private _trackLCP(): void {
122+
// Based on reference implementation from https://web.dev/lcp/#measure-lcp-in-javascript.
123+
// Use a try/catch instead of feature detecting `largest-contentful-paint`
124+
// support, since some browsers throw when using the new `type` option.
125+
// https://bugs.webkit.org/show_bug.cgi?id=209216
126+
try {
127+
// Keep track of whether (and when) the page was first hidden, see:
128+
// https://github.com/w3c/page-visibility/issues/29
129+
// NOTE: ideally this check would be performed in the document <head>
130+
// to avoid cases where the visibility state changes before this code runs.
131+
let firstHiddenTime = document.visibilityState === 'hidden' ? 0 : Infinity;
132+
document.addEventListener(
133+
'visibilitychange',
134+
event => {
135+
firstHiddenTime = Math.min(firstHiddenTime, event.timeStamp);
136+
},
137+
{ once: true },
138+
);
139+
140+
const updateLCP = (entry: PerformanceEntry): void => {
141+
// Only include an LCP entry if the page wasn't hidden prior to
142+
// the entry being dispatched. This typically happens when a page is
143+
// loaded in a background tab.
144+
if (entry.startTime < firstHiddenTime) {
145+
// NOTE: the `startTime` value is a getter that returns the entry's
146+
// `renderTime` value, if available, or its `loadTime` value otherwise.
147+
// The `renderTime` value may not be available if the element is an image
148+
// that's loaded cross-origin without the `Timing-Allow-Origin` header.
149+
this._lcp = {
150+
// @ts-ignore can't access id on entry
151+
...(entry.id && { elementId: entry.id }),
152+
// @ts-ignore can't access id on entry
153+
...(entry.size && { elementSize: entry.size }),
154+
value: entry.startTime,
155+
};
156+
}
157+
};
158+
159+
// Create a PerformanceObserver that calls `updateLCP` for each entry.
160+
const po = new PerformanceObserver(entryList => {
161+
entryList.getEntries().forEach(updateLCP);
162+
});
163+
164+
// Observe entries of type `largest-contentful-paint`, including buffered entries,
165+
// i.e. entries that occurred before calling `observe()` below.
166+
po.observe({
167+
buffered: true,
168+
// @ts-ignore type does not exist on obj
169+
type: 'largest-contentful-paint',
170+
});
171+
172+
this._forceLCP = () => {
173+
po.takeRecords().forEach(updateLCP);
174+
};
175+
} catch (e) {
176+
// Do nothing if the browser doesn't support this API.
177+
}
178+
}
177179
}
178180

179181
/** Instrument navigation entries */

packages/tracing/src/browser/request.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { addInstrumentationHandler, isInstanceOf, isMatchingPattern } from '@sentry/utils';
22

33
import { Span } from '../span';
4-
54
import { getActiveTransaction } from './utils';
65

76
export const DEFAULT_TRACING_ORIGINS = ['localhost', /^\//];
@@ -41,6 +40,7 @@ export interface RequestInstrumentationOptions {
4140

4241
/** Data returned from fetch callback */
4342
export interface FetchData {
43+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
4444
args: any[];
4545
fetchData?: {
4646
method: string;
@@ -59,11 +59,12 @@ interface XHRData {
5959
method: string;
6060
url: string;
6161
status_code: number;
62+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
6263
data: Record<string, any>;
6364
};
6465
__sentry_xhr_span_id__?: string;
6566
__sentry_own_request__: boolean;
66-
setRequestHeader?: Function;
67+
setRequestHeader?: (key: string, val: string) => void;
6768
};
6869
startTimestamp: number;
6970
endTimestamp?: number;
@@ -158,6 +159,7 @@ export function _fetchCallback(
158159
spans[span.spanId] = span;
159160

160161
const request = (handlerData.args[0] = handlerData.args[0] as string | Request);
162+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
161163
const options = (handlerData.args[1] = (handlerData.args[1] as { [key: string]: any }) || {});
162164
let headers = options.headers;
163165
if (isInstanceOf(request, Request)) {

0 commit comments

Comments
 (0)