diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index d3e4fbfd2a..62ef100ed4 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -153,6 +153,8 @@ jobs: run: npx lerna bootstrap --no-ci --hoist --nohoist='zone.js' --nohoist='mocha' --nohoist='ts-mocha' - name: Unit tests run: npm run test:ci:changed -- ${{ matrix.lerna-extra-args }} + - name: Build examples + run: npm run compile:examples - name: Report Coverage if: matrix.node == '14' uses: codecov/codecov-action@v3 diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000000..4d5f4befce --- /dev/null +++ b/examples/README.md @@ -0,0 +1,40 @@ +# Instrumentation Examples + +:warning: Note: We are working on migrating these examples to their respective package directories. + +For instance, examples of using `express` instrumentation have moved from this directory to [plugins/node/opentelemetry-instrumentation-express](https://github.com/open-telemetry/opentelemetry-js/tree/main/plugins/node/opentelemetry-instrumentation-express). + +## Instructions for Migrating an Example + +* [ ] Move the files + * [ ] Choose an instrumentation package to migrate examples for. + * [ ] Move the examples from `./examples/[name]` to `./plugins/[node or web]]/opentelemetry-instrumentation-[name]/examples`. +* [ ] Update the `package.json` in the examples folder + * [ ] Remove the `@opentelemetry/instrumentation-[name]` dependency. + * [ ] Install `typescript` and `ts-node` in the examples directory. + * [ ] Replace usage of `node` in scripts with `ts-node`. + * [ ] Add a script for compiling the code in scripts: `"compile": "tsc -p ."` +* [ ] Add a tsconfig.json file in the examples folder. (Example below) +* [ ] Update the code + * [ ] Change code to use a relative import of the library. + * [ ] Add types to the code +* [ ] Update the instrumentation package's `package.json` + * [ ] Add a script `"compile:examples": "cd examples && npm run compile",`. +* [ ] Test the updated code + * [ ] Test building the examples by running `npm run compile:examples` + * [ ] Test that the actual exapmle code runs as expected + +Example tsconfig.json file: + +```json +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "noEmit": true, + "rootDir": ".", + }, + "include": [ + "src/**/*.ts", + ] +} +``` diff --git a/examples/express/package.json b/examples/express/package.json deleted file mode 100644 index c2a7168eb9..0000000000 --- a/examples/express/package.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "express-example", - "private": true, - "version": "0.23.0", - "description": "Example of Express integration with OpenTelemetry", - "main": "index.js", - "scripts": { - "zipkin:server": "cross-env EXPORTER=zipkin node ./server.js", - "zipkin:client": "cross-env EXPORTER=zipkin node ./client.js", - "jaeger:server": "cross-env EXPORTER=jaeger node ./server.js", - "jaeger:client": "cross-env EXPORTER=jaeger node ./client.js" - }, - "repository": { - "type": "git", - "url": "git+ssh://git@github.com/open-telemetry/opentelemetry-js.git" - }, - "keywords": [ - "opentelemetry", - "express", - "tracing" - ], - "engines": { - "node": ">=8" - }, - "author": "OpenTelemetry Authors", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/open-telemetry/opentelemetry-js/issues" - }, - "dependencies": { - "@opentelemetry/api": "^1.0.2", - "@opentelemetry/exporter-jaeger": "^0.25.0", - "@opentelemetry/exporter-zipkin": "^0.25.0", - "@opentelemetry/instrumentation": "^0.25.0", - "@opentelemetry/instrumentation-express": "^0.23.0", - "@opentelemetry/instrumentation-http": "^0.25.0", - "@opentelemetry/resources": "^0.25.0", - "@opentelemetry/semantic-conventions": "^0.25.0", - "@opentelemetry/sdk-trace-node": "^0.25.0", - "@opentelemetry/sdk-trace-base": "^0.25.0", - "axios": "^0.21.1", - "cross-env": "^7.0.3", - "express": "^4.17.1" - }, - "homepage": "https://github.com/open-telemetry/opentelemetry-js#readme", - "devDependencies": {} -} diff --git a/lerna.json b/lerna.json index 5de7bde090..151338fed3 100644 --- a/lerna.json +++ b/lerna.json @@ -4,7 +4,9 @@ "packages/*", "metapackages/*", "plugins/node/*", + "plugins/node/*/examples", "plugins/web/*", + "plugins/web/*/examples", "propagators/*", "detectors/node/*" ], diff --git a/package.json b/package.json index 1b31958f61..3a0b1df174 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "precompile": "tsc --version && npm run version:update", "version:update": "lerna run version:update", "compile": "lerna run compile", + "compile:examples": "lerna run compile:examples", "prewatch": "npm run precompile", "test": "lerna run test", "test:ci:changed": "lerna run test --since origin/main", diff --git a/plugins/node/opentelemetry-instrumentation-express/.eslintignore b/plugins/node/opentelemetry-instrumentation-express/.eslintignore index 378eac25d3..514cc95d43 100644 --- a/plugins/node/opentelemetry-instrumentation-express/.eslintignore +++ b/plugins/node/opentelemetry-instrumentation-express/.eslintignore @@ -1 +1,2 @@ build +examples diff --git a/examples/express/README.md b/plugins/node/opentelemetry-instrumentation-express/examples/README.md similarity index 100% rename from examples/express/README.md rename to plugins/node/opentelemetry-instrumentation-express/examples/README.md diff --git a/examples/express/images/jaeger.jpg b/plugins/node/opentelemetry-instrumentation-express/examples/images/jaeger.jpg similarity index 100% rename from examples/express/images/jaeger.jpg rename to plugins/node/opentelemetry-instrumentation-express/examples/images/jaeger.jpg diff --git a/examples/express/images/zipkin.jpg b/plugins/node/opentelemetry-instrumentation-express/examples/images/zipkin.jpg similarity index 100% rename from examples/express/images/zipkin.jpg rename to plugins/node/opentelemetry-instrumentation-express/examples/images/zipkin.jpg diff --git a/plugins/node/opentelemetry-instrumentation-express/examples/package.json b/plugins/node/opentelemetry-instrumentation-express/examples/package.json new file mode 100644 index 0000000000..9deb18b543 --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-express/examples/package.json @@ -0,0 +1,52 @@ +{ + "name": "express-example", + "private": true, + "version": "0.28.0", + "description": "Example of Express integration with OpenTelemetry", + "main": "index.js", + "scripts": { + "zipkin:server": "cross-env EXPORTER=zipkin ts-node src/server.ts", + "zipkin:client": "cross-env EXPORTER=zipkin ts-node src/client.ts", + "jaeger:server": "cross-env EXPORTER=jaeger ts-node src/server.ts", + "jaeger:client": "cross-env EXPORTER=jaeger ts-node src/client.ts", + "compile": "tsc -p ." + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/open-telemetry/opentelemetry-js.git" + }, + "keywords": [ + "opentelemetry", + "express", + "tracing" + ], + "engines": { + "node": ">=8" + }, + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/open-telemetry/opentelemetry-js/issues" + }, + "dependencies": { + "@opentelemetry/api": "^1.0.4", + "@opentelemetry/exporter-jaeger": "^1.1.1", + "@opentelemetry/exporter-zipkin": "^1.1.1", + "@opentelemetry/instrumentation": "^0.27.0", + "@opentelemetry/instrumentation-express": "^0.28.0", + "@opentelemetry/instrumentation-http": "^0.27.0", + "@opentelemetry/resources": "^1.1.1", + "@opentelemetry/sdk-trace-base": "^1.1.1", + "@opentelemetry/sdk-trace-node": "^1.1.1", + "@opentelemetry/semantic-conventions": "^1.1.1", + "axios": "^0.21.1", + "cross-env": "^7.0.3", + "express": "^4.17.1" + }, + "homepage": "https://github.com/open-telemetry/opentelemetry-js#readme", + "devDependencies": { + "@types/express": "^4.17.13", + "ts-node": "^10.6.0", + "typescript": "^4.6.2" + } +} diff --git a/examples/express/client.js b/plugins/node/opentelemetry-instrumentation-express/examples/src/client.ts similarity index 65% rename from examples/express/client.js rename to plugins/node/opentelemetry-instrumentation-express/examples/src/client.ts index a162932b56..6a39414d09 100644 --- a/examples/express/client.js +++ b/plugins/node/opentelemetry-instrumentation-express/examples/src/client.ts @@ -1,9 +1,11 @@ 'use strict'; // eslint-disable-next-line import/order -const tracer = require('./tracer')('example-express-client'); -const api = require('@opentelemetry/api'); -const axios = require('axios').default; +import { setupTracing } from "./tracer"; +const tracer = setupTracing('example-express-client'); + +import * as api from '@opentelemetry/api'; +import { default as axios } from 'axios'; function makeRequest() { const span = tracer.startSpan('client.makeRequest()', { @@ -16,8 +18,10 @@ function makeRequest() { console.log('status:', res.statusText); span.setStatus({ code: api.SpanStatusCode.OK }); } catch (e) { - console.log('failed:', e.message); - span.setStatus({ code: api.SpanStatusCode.ERROR, message: e.message }); + if (e instanceof Error) { + console.log('failed:', e.message); + span.setStatus({ code: api.SpanStatusCode.ERROR, message: e.message }); + } } span.end(); console.log('Sleeping 5 seconds before shutdown to ensure all records are flushed.'); diff --git a/examples/express/server.js b/plugins/node/opentelemetry-instrumentation-express/examples/src/server.ts similarity index 80% rename from examples/express/server.js rename to plugins/node/opentelemetry-instrumentation-express/examples/src/server.ts index 79921205f7..37cec8819e 100644 --- a/examples/express/server.js +++ b/plugins/node/opentelemetry-instrumentation-express/examples/src/server.ts @@ -1,11 +1,11 @@ -'use strict'; +import { setupTracing } from './tracer' -// eslint-disable-next-line -require('./tracer')('example-express-server'); +setupTracing('example-express-server'); // Require in rest of modules -const express = require('express'); -const axios = require('axios').default; +import * as express from 'express'; +import { default as axios } from 'axios'; +import { RequestHandler } from "express"; // Setup express const app = express(); @@ -13,7 +13,7 @@ const PORT = 8080; const getCrudController = () => { const router = express.Router(); - const resources = []; + const resources: any[] = []; router.get('/', (req, res) => res.send(resources)); router.post('/', (req, res) => { resources.push(req.body); @@ -22,7 +22,7 @@ const getCrudController = () => { return router; }; -const authMiddleware = (req, res, next) => { +const authMiddleware: RequestHandler = (req, res, next) => { const { authorization } = req.headers; if (authorization && authorization.includes('secret_token')) { next(); diff --git a/examples/express/tracer.js b/plugins/node/opentelemetry-instrumentation-express/examples/src/tracer.ts similarity index 54% rename from examples/express/tracer.js rename to plugins/node/opentelemetry-instrumentation-express/examples/src/tracer.ts index e41f857348..ccc05682b6 100644 --- a/examples/express/tracer.js +++ b/plugins/node/opentelemetry-instrumentation-express/examples/src/tracer.ts @@ -1,26 +1,28 @@ 'use strict'; +import { Sampler, SpanKind } from "@opentelemetry/api"; + const opentelemetry = require('@opentelemetry/api'); // Not functionally required but gives some insight what happens behind the scenes const { diag, DiagConsoleLogger, DiagLogLevel } = opentelemetry; diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.INFO); -const { AlwaysOnSampler } = require('@opentelemetry/core'); -const { registerInstrumentations } = require('@opentelemetry/instrumentation'); -const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node'); -const { SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base'); -const { JaegerExporter } = require('@opentelemetry/exporter-jaeger'); -const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin'); -const { Resource } = require('@opentelemetry/resources'); -const { SemanticAttributes, SemanticResourceAttributes: ResourceAttributesSC } = require('@opentelemetry/semantic-conventions'); +import { AlwaysOnSampler } from '@opentelemetry/core'; +import { registerInstrumentations } from '@opentelemetry/instrumentation'; +import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; +import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'; +import { JaegerExporter } from '@opentelemetry/exporter-jaeger'; +import { ZipkinExporter } from '@opentelemetry/exporter-zipkin'; +import { Resource } from '@opentelemetry/resources'; +import { SemanticAttributes, SemanticResourceAttributes as ResourceAttributesSC } from '@opentelemetry/semantic-conventions'; +import { SpanAttributes } from "@opentelemetry/api/build/src/trace/attributes"; -const Exporter = (process.env.EXPORTER || '') - .toLowerCase().startsWith('z') ? ZipkinExporter : JaegerExporter; -const { ExpressInstrumentation } = require('@opentelemetry/instrumentation-express'); +const Exporter = (process.env.EXPORTER || '').toLowerCase().startsWith('z') ? ZipkinExporter : JaegerExporter; +import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express'; const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http'); -module.exports = (serviceName) => { +export const setupTracing = (serviceName: string) => { const provider = new NodeTracerProvider({ resource: new Resource({ [ResourceAttributesSC.SERVICE_NAME]: serviceName, @@ -45,10 +47,12 @@ module.exports = (serviceName) => { // Initialize the OpenTelemetry APIs to use the NodeTracerProvider bindings provider.register(); - return opentelemetry.trace.getTracer('express-example'); + return opentelemetry.trace.getTracer(serviceName); }; -function filterSampler(filterFn, parent) { +type FilterFunction = (spanName: string, spanKind: SpanKind, attributes: SpanAttributes) => boolean; + +function filterSampler(filterFn: FilterFunction, parent: Sampler): Sampler { return { shouldSample(ctx, tid, spanName, spanKind, attr, links) { if (!filterFn(spanName, spanKind, attr)) { @@ -62,6 +66,6 @@ function filterSampler(filterFn, parent) { } } -function ignoreHealthCheck(spanName, spanKind, attributes) { +function ignoreHealthCheck(spanName: string, spanKind: SpanKind, attributes: SpanAttributes) { return spanKind !== opentelemetry.SpanKind.SERVER || attributes[SemanticAttributes.HTTP_ROUTE] !== "/health"; } diff --git a/plugins/node/opentelemetry-instrumentation-express/examples/tsconfig.json b/plugins/node/opentelemetry-instrumentation-express/examples/tsconfig.json new file mode 100644 index 0000000000..5a768b7e2c --- /dev/null +++ b/plugins/node/opentelemetry-instrumentation-express/examples/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "noEmit": true, + "rootDir": ".", + }, + "include": [ + "src/**/*.ts", + ] +} diff --git a/plugins/node/opentelemetry-instrumentation-express/package.json b/plugins/node/opentelemetry-instrumentation-express/package.json index ba25f229c6..eac4ecaa1e 100644 --- a/plugins/node/opentelemetry-instrumentation-express/package.json +++ b/plugins/node/opentelemetry-instrumentation-express/package.json @@ -16,6 +16,7 @@ "prewatch": "npm run precompile", "version:update": "node ../../../scripts/version-update.js", "compile": "tsc -p .", + "compile:examples": "cd examples && npm run compile", "prepare": "npm run compile", "watch": "tsc -w" },