diff --git a/.github/component_owners.yml b/.github/component_owners.yml index ed94624ee2..e9d657e9d8 100644 --- a/.github/component_owners.yml +++ b/.github/component_owners.yml @@ -44,6 +44,9 @@ components: - rauno56 plugins/web/opentelemetry-instrumentation-document-load: - obecny + plugins/web/opentelemetry-instrumentation-long-task: + - mhennoch + - t2t2 plugins/web/opentelemetry-instrumentation-user-interaction: - obecny propagators/opentelemetry-propagator-aws-xray: diff --git a/plugins/web/opentelemetry-instrumentation-long-task/.eslintignore b/plugins/web/opentelemetry-instrumentation-long-task/.eslintignore new file mode 100644 index 0000000000..378eac25d3 --- /dev/null +++ b/plugins/web/opentelemetry-instrumentation-long-task/.eslintignore @@ -0,0 +1 @@ +build diff --git a/plugins/web/opentelemetry-instrumentation-long-task/.eslintrc.js b/plugins/web/opentelemetry-instrumentation-long-task/.eslintrc.js new file mode 100644 index 0000000000..6ad6c9f216 --- /dev/null +++ b/plugins/web/opentelemetry-instrumentation-long-task/.eslintrc.js @@ -0,0 +1,9 @@ +module.exports = { + "env": { + "mocha": true, + "commonjs": true, + "browser": true, + "jquery": true + }, + ...require('../../../eslint.config.js') +} diff --git a/plugins/web/opentelemetry-instrumentation-long-task/README.md b/plugins/web/opentelemetry-instrumentation-long-task/README.md new file mode 100644 index 0000000000..6a6659ee97 --- /dev/null +++ b/plugins/web/opentelemetry-instrumentation-long-task/README.md @@ -0,0 +1,59 @@ +# OpenTelemetry Long Task Instrumentation for web + +[![NPM Published Version][npm-img]][npm-url] +[![dependencies][dependencies-image]][dependencies-url] +[![devDependencies][devDependencies-image]][devDependencies-url] +[![Apache License][license-image]][license-image] + +This instrumentation creates spans from tasks that take more than 50 milliseconds using the [Long Task API][mdn-long-task]. +All of the data reported via [`PerformanceLongTaskTiming`][mdn-performance-long-task-timing] is included as span attributes. + +Compatible with OpenTelemetry JS API and SDK `1.0+`. + +## Installation + +```bash +npm install --save @opentelemetry/instrumentation-long-task +``` + +## Usage + +```js +import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'; +import { WebTracerProvider } from '@opentelemetry/sdk-trace-web'; +import { LongTaskInstrumentation } from '@opentelemetry/instrumentation-long-task'; +import { registerInstrumentations } from '@opentelemetry/instrumentation'; + +const provider = new WebTracerProvider(); + +provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter())); + +registerInstrumentations({ + tracerProvider: provider, + instrumentations: [ + new LongTaskInstrumentation(), + ], +}); +``` + +## Useful links + +- For more information on OpenTelemetry, visit: +- For more about OpenTelemetry JavaScript: +- For help or feedback on this project, join us in [GitHub Discussions][discussions-url] + +## License + +Apache 2.0 - See [LICENSE][license-url] for more information. + +[discussions-url]: https://github.com/open-telemetry/opentelemetry-js/discussions +[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/main/LICENSE +[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat +[dependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js-contrib.svg?path=plugins%2Fweb%2Fopentelemetry-instrumentation-long-task +[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib?path=plugins%2Fweb%2Fopentelemetry-instrumentation-long-task +[devDependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js-contrib.svg?path=plugins%2Fweb%2Fopentelemetry-instrumentation-long-task&type=dev +[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js-contrib?path=plugins%2Fweb%2Fopentelemetry-instrumentation-long-task&type=dev +[npm-url]: https://www.npmjs.com/package/@opentelemetry/instrumentation-long-task +[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Finstrumentation-long-task.svg +[mdn-long-task]: https://developer.mozilla.org/en-US/docs/Web/API/Long_Tasks_API +[mdn-performance-long-task-timing]: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceLongTaskTiming diff --git a/plugins/web/opentelemetry-instrumentation-long-task/karma.conf.js b/plugins/web/opentelemetry-instrumentation-long-task/karma.conf.js new file mode 100644 index 0000000000..4a4bd49791 --- /dev/null +++ b/plugins/web/opentelemetry-instrumentation-long-task/karma.conf.js @@ -0,0 +1,25 @@ +/*! + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const karmaWebpackConfig = require('../../../karma.webpack'); +const karmaBaseConfig = require('../../../karma.base'); + +module.exports = (config) => { + config.set(Object.assign({}, karmaBaseConfig, { + frameworks: karmaBaseConfig.frameworks.concat(['jquery-1.8.3']), + webpack: karmaWebpackConfig, + })) +}; diff --git a/plugins/web/opentelemetry-instrumentation-long-task/package.json b/plugins/web/opentelemetry-instrumentation-long-task/package.json new file mode 100644 index 0000000000..98454993bd --- /dev/null +++ b/plugins/web/opentelemetry-instrumentation-long-task/package.json @@ -0,0 +1,91 @@ +{ + "name": "@opentelemetry/instrumentation-long-task", + "version": "0.27.0", + "description": "OpenTelemetry long task API automatic instrumentation package.", + "main": "build/src/index.js", + "module": "build/esm/index.js", + "types": "build/src/index.d.ts", + "repository": "open-telemetry/opentelemetry-js-contrib", + "scripts": { + "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --ext .ts --fix", + "clean": "tsc --build --clean tsconfig.json tsconfig.esm.json", + "codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../", + "precompile": "tsc --version && lerna run version --scope @opentelemetry/instrumentation-user-interaction --include-filtered-dependencies", + "prewatch": "npm run precompile", + "version:update": "node ../../../scripts/version-update.js", + "compile": "npm run version:update && tsc --build tsconfig.json tsconfig.esm.json", + "prepare": "npm run compile", + "tdd": "karma start", + "test:browser": "nyc karma start --single-run", + "watch": "tsc --build --watch tsconfig.json tsconfig.esm.json" + }, + "keywords": [ + "opentelemetry", + "web", + "tracing", + "profiling", + "metrics", + "stats" + ], + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + }, + "files": [ + "build/esm/**/*.js", + "build/esm/**/*.map", + "build/esm/**/*.d.ts", + "build/src/**/*.js", + "build/src/**/*.map", + "build/src/**/*.d.ts", + "doc", + "LICENSE", + "README.md" + ], + "publishConfig": { + "access": "public" + }, + "devDependencies": { + "@babel/core": "7.15.0", + "@opentelemetry/api": "1.0.2", + "@opentelemetry/sdk-trace-base": "1.0.1", + "@types/jquery": "3.5.6", + "@types/mocha": "7.0.2", + "@types/node": "14.17.9", + "@types/sinon": "10.0.2", + "@types/webpack-env": "1.16.2", + "babel-loader": "8.2.2", + "codecov": "3.8.3", + "gts": "3.1.0", + "istanbul-instrumenter-loader": "3.0.1", + "karma": "5.2.3", + "karma-chrome-launcher": "3.1.0", + "karma-coverage-istanbul-reporter": "3.0.3", + "karma-jquery": "0.2.4", + "karma-mocha": "2.0.1", + "karma-spec-reporter": "0.0.32", + "karma-webpack": "4.0.2", + "mocha": "7.2.0", + "nyc": "15.1.0", + "rimraf": "3.0.2", + "sinon": "11.1.2", + "ts-loader": "8.3.0", + "ts-mocha": "8.0.0", + "typescript": "4.3.5", + "webpack": "4.46.0", + "webpack-cli": "4.7.2", + "webpack-merge": "5.8.0", + "zone.js": "0.11.4" + }, + "dependencies": { + "@opentelemetry/core": "^1.0.0", + "@opentelemetry/instrumentation": "^0.27.0", + "@opentelemetry/sdk-trace-web": "^1.0.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.2" + }, + "sideEffects": false +} diff --git a/plugins/web/opentelemetry-instrumentation-long-task/src/index.ts b/plugins/web/opentelemetry-instrumentation-long-task/src/index.ts new file mode 100644 index 0000000000..24c76056a1 --- /dev/null +++ b/plugins/web/opentelemetry-instrumentation-long-task/src/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './instrumentation'; diff --git a/plugins/web/opentelemetry-instrumentation-long-task/src/instrumentation.ts b/plugins/web/opentelemetry-instrumentation-long-task/src/instrumentation.ts new file mode 100644 index 0000000000..1bebc4d70c --- /dev/null +++ b/plugins/web/opentelemetry-instrumentation-long-task/src/instrumentation.ts @@ -0,0 +1,135 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hrTime } from '@opentelemetry/core'; +import { + InstrumentationBase, + InstrumentationConfig, +} from '@opentelemetry/instrumentation'; +import { VERSION } from './version'; + +// Currently missing in typescript DOM definitions +interface PerformanceLongTaskTiming extends PerformanceEntry { + attribution: TaskAttributionTiming[]; +} + +interface TaskAttributionTiming extends PerformanceEntry { + containerType: string; + containerSrc: string; + containerId: string; + containerName: string; +} + +const LONGTASK_PERFORMANCE_TYPE = 'longtask'; + +export class LongTaskInstrumentation extends InstrumentationBase { + readonly component: string = 'long-task'; + readonly version: string = VERSION; + moduleName = this.component; + + private _observer?: PerformanceObserver; + + /** + * + * @param config + */ + constructor(config: InstrumentationConfig = {}) { + super('@opentelemetry/instrumentation-long-task', VERSION, config); + } + + init() {} + + private isSupported() { + if ( + typeof PerformanceObserver === 'undefined' || + !PerformanceObserver.supportedEntryTypes + ) { + return false; + } + + return PerformanceObserver.supportedEntryTypes.includes( + LONGTASK_PERFORMANCE_TYPE + ); + } + + private _createSpanFromEntry(entry: PerformanceLongTaskTiming) { + const span = this.tracer.startSpan(LONGTASK_PERFORMANCE_TYPE, { + startTime: hrTime(entry.startTime), + }); + span.setAttribute('component', this.component); + span.setAttribute('longtask.name', entry.name); + span.setAttribute('longtask.entry_type', entry.entryType); + span.setAttribute('longtask.duration', entry.duration); + + if (Array.isArray(entry.attribution)) { + entry.attribution.forEach((attribution, index) => { + const prefix = + entry.attribution.length > 1 + ? `longtask.attribution[${index}]` + : 'longtask.attribution'; + span.setAttribute(`${prefix}.name`, attribution.name); + span.setAttribute(`${prefix}.entry_type`, attribution.entryType); + span.setAttribute(`${prefix}.start_time`, attribution.startTime); + span.setAttribute(`${prefix}.duration`, attribution.duration); + span.setAttribute( + `${prefix}.container_type`, + attribution.containerType + ); + span.setAttribute(`${prefix}.container_src`, attribution.containerSrc); + span.setAttribute(`${prefix}.container_id`, attribution.containerId); + span.setAttribute( + `${prefix}.container_name`, + attribution.containerName + ); + }); + } + + span.end(hrTime(entry.startTime + entry.duration)); + } + + override enable() { + if (!this.isSupported()) { + this._diag.debug('Environment not supported'); + return; + } + + if (this._observer) { + // Already enabled + return; + } + + this._observer = new PerformanceObserver(list => { + list + .getEntries() + .forEach(entry => + this._createSpanFromEntry(entry as PerformanceLongTaskTiming) + ); + }); + this._observer.observe({ + type: LONGTASK_PERFORMANCE_TYPE, + buffered: true, + }); + } + + override disable() { + if (!this._observer) { + return; + } + + this._observer.disconnect(); + this._observer = undefined; + } +} diff --git a/plugins/web/opentelemetry-instrumentation-long-task/test/compatibility.test.ts b/plugins/web/opentelemetry-instrumentation-long-task/test/compatibility.test.ts new file mode 100644 index 0000000000..d3404d19ae --- /dev/null +++ b/plugins/web/opentelemetry-instrumentation-long-task/test/compatibility.test.ts @@ -0,0 +1,122 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { trace } from '@opentelemetry/api'; +import { registerInstrumentations } from '@opentelemetry/instrumentation'; +import * as tracing from '@opentelemetry/sdk-trace-base'; +import { WebTracerProvider } from '@opentelemetry/sdk-trace-web'; +import { LongTaskInstrumentation } from '../src'; +import { DummySpanExporter } from './util'; + +/* eslint-disable node/no-unsupported-features/es-builtins */ +const _globalThis: typeof globalThis = + typeof globalThis === 'object' + ? globalThis + : typeof self === 'object' + ? self + : typeof window === 'object' + ? window + : typeof global === 'object' + ? global + : ({} as typeof globalThis); +/* eslint-enable node/no-unsupported-features/es-builtins */ + +describe("LongTaskInstrumentation doesn't throw in unsupported environments", () => { + let webTracerProvider: WebTracerProvider; + let dummySpanExporter: DummySpanExporter; + + before(() => { + webTracerProvider = new WebTracerProvider(); + dummySpanExporter = new DummySpanExporter(); + webTracerProvider.addSpanProcessor( + new tracing.SimpleSpanProcessor(dummySpanExporter) + ); + webTracerProvider.register(); + }); + + after(() => { + trace.disable(); + }); + + // Do cleanup for environment changes here so even with test fails won't affect other tests + const perfObsDesc = Object.getOwnPropertyDescriptor( + _globalThis, + 'PerformanceObserver' + ); + const supportedDesc = Object.getOwnPropertyDescriptor( + PerformanceObserver, + 'supportedEntryTypes' + ); + afterEach(() => { + Object.defineProperty(_globalThis, 'PerformanceObserver', perfObsDesc!); + Object.defineProperty( + PerformanceObserver, + 'supportedEntryTypes', + supportedDesc! + ); + }); + + // tests based on different browser targets in + // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver#browser_compatibility + it('No support for PerformanceObserver', async () => { + // @ts-expect-error Non-optional in types + delete _globalThis.PerformanceObserver; + + const longTaskInstrumentation = new LongTaskInstrumentation({ + enabled: false, + }); + + const deregister = registerInstrumentations({ + instrumentations: [longTaskInstrumentation], + }); + + deregister(); + }); + + it('No supportedEntryTypes', async () => { + // @ts-expect-error Non-optional in types + delete PerformanceObserver.supportedEntryTypes; + + const longTaskInstrumentation = new LongTaskInstrumentation({ + enabled: false, + }); + + const deregister = registerInstrumentations({ + instrumentations: [longTaskInstrumentation], + }); + + deregister(); + }); + + it('longtask not supported', async () => { + Object.defineProperty(PerformanceObserver, 'supportedEntryTypes', { + get() { + return []; + }, + configurable: true, + enumerable: false, + }); + + const longTaskInstrumentation = new LongTaskInstrumentation({ + enabled: false, + }); + + const deregister = registerInstrumentations({ + instrumentations: [longTaskInstrumentation], + }); + + deregister(); + }); +}); diff --git a/plugins/web/opentelemetry-instrumentation-long-task/test/index-webpack.ts b/plugins/web/opentelemetry-instrumentation-long-task/test/index-webpack.ts new file mode 100644 index 0000000000..061a48ccfa --- /dev/null +++ b/plugins/web/opentelemetry-instrumentation-long-task/test/index-webpack.ts @@ -0,0 +1,20 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const testsContext = require.context('.', true, /test$/); +testsContext.keys().forEach(testsContext); + +const srcContext = require.context('.', true, /src$/); +srcContext.keys().forEach(srcContext); diff --git a/plugins/web/opentelemetry-instrumentation-long-task/test/longTask.test.ts b/plugins/web/opentelemetry-instrumentation-long-task/test/longTask.test.ts new file mode 100644 index 0000000000..fabb02e469 --- /dev/null +++ b/plugins/web/opentelemetry-instrumentation-long-task/test/longTask.test.ts @@ -0,0 +1,104 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { trace } from '@opentelemetry/api'; +import { hrTimeToMilliseconds, hrTimeToNanoseconds } from '@opentelemetry/core'; +import { registerInstrumentations } from '@opentelemetry/instrumentation'; +import * as tracing from '@opentelemetry/sdk-trace-base'; +import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; +import { WebTracerProvider } from '@opentelemetry/sdk-trace-web'; +import * as assert from 'assert'; +import * as sinon from 'sinon'; +import { LongTaskInstrumentation } from '../src'; +import { DummySpanExporter } from './util'; + +const LONGTASK_DURATION = 50 * 1.1; // add 10% margin +function generateLongTask() { + const startingTimestamp = performance.now(); + while (performance.now() - startingTimestamp < LONGTASK_DURATION) {} +} + +describe('LongTaskInstrumentation', () => { + let longTaskInstrumentation: LongTaskInstrumentation; + let sandbox: sinon.SinonSandbox; + let webTracerProvider: WebTracerProvider; + let dummySpanExporter: DummySpanExporter; + let exportSpy: sinon.SinonStub; + let deregister: () => void; + + beforeEach(() => { + sandbox = sinon.createSandbox(); + webTracerProvider = new WebTracerProvider(); + dummySpanExporter = new DummySpanExporter(); + exportSpy = sandbox.stub(dummySpanExporter, 'export'); + webTracerProvider.addSpanProcessor( + new tracing.SimpleSpanProcessor(dummySpanExporter) + ); + webTracerProvider.register(); + + longTaskInstrumentation = new LongTaskInstrumentation({ + enabled: false, + }); + + deregister = registerInstrumentations({ + instrumentations: [longTaskInstrumentation], + }); + }); + + afterEach(() => { + deregister(); + sandbox.restore(); + exportSpy.restore(); + trace.disable(); + }); + + it('should report long taking tasks', async () => { + let taskStart: number; + await new Promise(resolve => { + // Resolve promise when export gets called + exportSpy.callsFake(() => { + if (!taskStart) { + // Hasn't generated expected longtask yet + return; + } + resolve(); + }); + setTimeout(() => { + // Cleanup any past longtasks + exportSpy.resetHistory(); + taskStart = performance.timeOrigin + performance.now(); + generateLongTask(); + }, 1); + }); + + assert.strictEqual(exportSpy.args.length, 1, 'should export once'); + assert.strictEqual( + exportSpy.args[0][0].length, + 1, + 'should export one span' + ); + const span: ReadableSpan = exportSpy.args[0][0][0]; + + // Span should match expected longtask timings + assert.ok( + hrTimeToMilliseconds(span.startTime) <= Math.ceil(taskStart!), + 'span start should be when task started' + ); + assert.ok( + hrTimeToNanoseconds(span.duration) > LONGTASK_DURATION, + "span duration should be longtask's" + ); + }); +}); diff --git a/plugins/web/opentelemetry-instrumentation-long-task/test/util.ts b/plugins/web/opentelemetry-instrumentation-long-task/test/util.ts new file mode 100644 index 0000000000..ce8179e5ae --- /dev/null +++ b/plugins/web/opentelemetry-instrumentation-long-task/test/util.ts @@ -0,0 +1,24 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import * as tracing from '@opentelemetry/sdk-trace-base'; + +export class DummySpanExporter implements tracing.SpanExporter { + export(spans: tracing.ReadableSpan[]) {} + + shutdown() { + return Promise.resolve(); + } +} diff --git a/plugins/web/opentelemetry-instrumentation-long-task/tsconfig.esm.json b/plugins/web/opentelemetry-instrumentation-long-task/tsconfig.esm.json new file mode 100644 index 0000000000..d903fa3086 --- /dev/null +++ b/plugins/web/opentelemetry-instrumentation-long-task/tsconfig.esm.json @@ -0,0 +1,12 @@ +{ + "extends": "../../../tsconfig.base.esm.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "build/esm", + "tsBuildInfoFile": "build/esm/tsconfig.esm.tsbuildinfo" + }, + "files": [ "node_modules/zone.js/dist/zone.js.d.ts"], + "include": [ + "src/**/*.ts" + ] +} diff --git a/plugins/web/opentelemetry-instrumentation-long-task/tsconfig.json b/plugins/web/opentelemetry-instrumentation-long-task/tsconfig.json new file mode 100644 index 0000000000..28be80d266 --- /dev/null +++ b/plugins/web/opentelemetry-instrumentation-long-task/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.base", + "compilerOptions": { + "rootDir": ".", + "outDir": "build" + }, + "include": [ + "src/**/*.ts", + "test/**/*.ts" + ] +}