-
Notifications
You must be signed in to change notification settings - Fork 932
feat: ESM support for instrumentation #3698
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
Changes from all commits
43fd59e
e5215fe
3c51c6d
8444af3
e4478d9
1434b27
a533f9f
a43089b
85a2e8f
e0b5c44
63477c5
1188c02
33e544c
bfe51f5
7110c37
3ddb3a9
3f3d9a2
2936a16
4a10129
50363c5
c9922c3
b722486
4ac1ee1
a346531
1ca6b55
4401576
86b6837
da694c7
1612855
e924c99
b894bcd
68c43c9
a2a74f8
a529c8c
ddc8dc5
42eb5ba
4f71df8
6a052b1
58d34c0
33409da
1f017b0
16109d3
bcaef1c
c590efc
59047bd
0167a10
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Overview | ||
|
||
This is a simple example that demonstrates tracing HTTP request, with an app written in TypeScript and transpiled to ES Modules. | ||
|
||
## Installation | ||
|
||
```sh | ||
# from this directory | ||
npm install | ||
npm run build | ||
npm start | ||
``` | ||
|
||
In a separate terminal, `curl localhost:3000`. | ||
|
||
See two spans in the console (one manual, one for http instrumentation) | ||
|
||
## Useful links | ||
|
||
- For more information on OpenTelemetry, visit: <https://opentelemetry.io/> | ||
- For more information on OpenTelemetry for Node.js, visit: <https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-trace-node> | ||
|
||
## LICENSE | ||
|
||
Apache License 2.0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { registerInstrumentations } from '@opentelemetry/instrumentation'; | ||
import { trace, DiagConsoleLogger, DiagLogLevel, diag } from '@opentelemetry/api'; | ||
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'; | ||
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; | ||
import { | ||
ConsoleSpanExporter, | ||
SimpleSpanProcessor, | ||
} from '@opentelemetry/sdk-trace-base'; | ||
import { Resource } from '@opentelemetry/resources'; | ||
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'; | ||
import http from 'http'; | ||
Flarna marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG); | ||
const tracerProvider = new NodeTracerProvider({ | ||
resource: new Resource({ | ||
[SemanticResourceAttributes.SERVICE_NAME]: 'esm-http-ts-example', | ||
}), | ||
}); | ||
const exporter = new ConsoleSpanExporter(); | ||
const processor = new SimpleSpanProcessor(exporter); | ||
tracerProvider.addSpanProcessor(processor); | ||
tracerProvider.register(); | ||
|
||
registerInstrumentations({ | ||
instrumentations: [new HttpInstrumentation()], | ||
}); | ||
|
||
const hostname = '0.0.0.0'; | ||
const port = 3000; | ||
|
||
const server = http.createServer((req, res) => { | ||
res.statusCode = 200; | ||
res.setHeader('Content-Type', 'text/plain'); | ||
const tracer = trace.getTracer('esm-tracer'); | ||
tracer.startActiveSpan('manual', span => { | ||
span.end(); | ||
}); | ||
res.end('Hello, World!\n'); | ||
}); | ||
|
||
server.listen(port, hostname, () => { | ||
console.log(`Server running at http://${hostname}:${port}/`); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{ | ||
"name": "esm-http-ts", | ||
"private": true, | ||
"version": "0.38.0", | ||
"description": "Example of HTTP integration with OpenTelemetry using ESM and TypeScript", | ||
"main": "build/index.js", | ||
"type": "module", | ||
"scripts": { | ||
"build": "tsc --build", | ||
"start": "node --experimental-loader=@opentelemetry/instrumentation/hook.mjs ./build/index.js" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+ssh://[email protected]/open-telemetry/opentelemetry-js.git" | ||
}, | ||
"keywords": [ | ||
"opentelemetry", | ||
"http", | ||
"tracing", | ||
"esm", | ||
"typescript" | ||
], | ||
"engines": { | ||
"node": ">=14" | ||
}, | ||
"author": "OpenTelemetry Authors", | ||
"license": "Apache-2.0", | ||
"bugs": { | ||
"url": "https://github.com/open-telemetry/opentelemetry-js/issues" | ||
}, | ||
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/examples/", | ||
"dependencies": { | ||
"@opentelemetry/api": "1.4.0", | ||
"@opentelemetry/exporter-trace-otlp-proto": "0.38.0", | ||
"@opentelemetry/instrumentation": "0.38.0", | ||
"@opentelemetry/instrumentation-http": "0.38.0", | ||
"@opentelemetry/resources": "1.9.1", | ||
"@opentelemetry/sdk-trace-base": "1.9.1", | ||
"@opentelemetry/sdk-trace-node": "1.9.1", | ||
"@opentelemetry/semantic-conventions": "1.9.1" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{ | ||
"compilerOptions": { | ||
/* Language and Environment */ | ||
"target": "ES2020" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, | ||
Flarna marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/* Modules */ | ||
"module": "ESNext" /* Specify what module code is generated. */, | ||
"rootDir": "." /* Specify the root folder within your source files. */, | ||
"moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */, | ||
"resolveJsonModule": true /* Enable importing .json files. */, | ||
|
||
/* Emit */ | ||
"outDir": "build" /* Specify an output folder for all emitted files. */, | ||
|
||
/* Interop Constraints */ | ||
"allowSyntheticDefaultImports": true /* Allow 'import x from y' when a module doesn't have a default export. */, | ||
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, | ||
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, | ||
|
||
/* Completeness */ | ||
"skipLibCheck": true /* Skip type checking all .d.ts files. */ | ||
Flarna marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}, | ||
"include": ["**/*.ts", "**/*.js", "*.config.js"], | ||
"exclude": ["node_modules"] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -219,12 +219,18 @@ If nothing is specified the global registered provider is used. Usually this is | |
There might be usecase where someone has the need for more providers within an application. Please note that special care must be takes in such setups | ||
to avoid leaking information from one provider to the other because there are a lot places where e.g. the global `ContextManager` or `Propagator` is used. | ||
|
||
## Instrumentation for ES Modules In NodeJS (experimental) | ||
|
||
As the module loading mechanism for ESM is different than CJS, you need to select a custom loader so instrumentation can load hook on the esm module it want to patch. To do so, you must provide the `--experimental-loader=@opentelemetry/instrumentation/hook.mjs` flag to the `node` binary. Alternatively you can set the `NODE_OPTIONS` environment variable to `NODE_OPTIONS="--experimental-loader=@opentelemetry/instrumentation/hook.mjs"`. | ||
As the ESM module loader from NodeJS is experimental, so is our support for it. Feel free to provide feedback or report issues about it. | ||
Flarna marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
**Note**: ESM Instrumentation is not yet supported for Node 20. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please update the limitations section below which tells There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what does this mean? How can one use ESM without import? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It means that the limitations section requires changes in this PR because it removes one of them. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. huh, super, thanks for the clarification :) a panic mode was already about to arise :D |
||
## Limitations | ||
|
||
Instrumentations for external modules (e.g. express, mongodb,...) hooks the `require` call. Therefore following conditions need to be met that this mechanism can work: | ||
Instrumentations for external modules (e.g. express, mongodb,...) hooks the `require` call or `import` statement. Therefore following conditions need to be met that this mechanism can work: | ||
|
||
* `require` is used. ECMA script modules (using `import`) is not supported as of now | ||
* Instrumentations are registered **before** the module to instrument is `require`ed | ||
* Instrumentations are registered **before** the module to instrument is `require`ed (CJS only) | ||
* modules are not included in a bundle. Tools like `esbuild`, `webpack`, ... usually have some mechanism to exclude specific modules from bundling | ||
|
||
## License | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/*! | ||
* Copyright 2021 Datadog, Inc. | ||
* Copyright The OpenTelemetry Authors | ||
pkanal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* | ||
* 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. | ||
*/ | ||
|
||
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2.0 License. | ||
// | ||
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc. | ||
|
||
import { | ||
load, | ||
resolve, | ||
getFormat, | ||
getSource, | ||
} from 'import-in-the-middle/hook.mjs'; | ||
export { load, resolve, getFormat, getSource }; |
Uh oh!
There was an error while loading. Please reload this page.