forked from open-telemetry/opentelemetry-js-contrib
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Long Tasks instrumentation (open-telemetry#757)
Co-authored-by: Valentin Marchaud <[email protected]>
- Loading branch information
Showing
14 changed files
with
633 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
plugins/web/opentelemetry-instrumentation-long-task/.eslintignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
build |
9 changes: 9 additions & 0 deletions
9
plugins/web/opentelemetry-instrumentation-long-task/.eslintrc.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
module.exports = { | ||
"env": { | ||
"mocha": true, | ||
"commonjs": true, | ||
"browser": true, | ||
"jquery": true | ||
}, | ||
...require('../../../eslint.config.js') | ||
} |
59 changes: 59 additions & 0 deletions
59
plugins/web/opentelemetry-instrumentation-long-task/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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: <https://opentelemetry.io/> | ||
- For more about OpenTelemetry JavaScript: <https://github.com/open-telemetry/opentelemetry-js> | ||
- 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 |
25 changes: 25 additions & 0 deletions
25
plugins/web/opentelemetry-instrumentation-long-task/karma.conf.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
})) | ||
}; |
91 changes: 91 additions & 0 deletions
91
plugins/web/opentelemetry-instrumentation-long-task/package.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
17 changes: 17 additions & 0 deletions
17
plugins/web/opentelemetry-instrumentation-long-task/src/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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'; |
135 changes: 135 additions & 0 deletions
135
plugins/web/opentelemetry-instrumentation-long-task/src/instrumentation.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |
Oops, something went wrong.