From 45f36220d3014dfb8d59ba44c32a9b7384b68fde Mon Sep 17 00:00:00 2001 From: Trent Mick Date: Wed, 25 Jun 2025 15:06:10 -0700 Subject: [PATCH] chore(examples): lint examples/express using shared top-level eslint config Refs: https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2891 --- examples/express/.eslintrc.js | 26 ++++++++++++++ examples/express/package.json | 2 ++ examples/express/src/client.ts | 65 +++++++++++++++++++++++----------- examples/express/src/server.ts | 47 ++++++++++++++++-------- examples/express/src/tracer.ts | 59 +++++++++++++++++++++++------- 5 files changed, 153 insertions(+), 46 deletions(-) create mode 100644 examples/express/.eslintrc.js diff --git a/examples/express/.eslintrc.js b/examples/express/.eslintrc.js new file mode 100644 index 0000000000..53452072e2 --- /dev/null +++ b/examples/express/.eslintrc.js @@ -0,0 +1,26 @@ +/* + * 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. + */ + +'use strict'; + +const baseConfig = require('../../eslint.config'); + +module.exports = { + ...baseConfig, + env: { + node: true, + }, +}; diff --git a/examples/express/package.json b/examples/express/package.json index 8713e11db8..240f647c8a 100644 --- a/examples/express/package.json +++ b/examples/express/package.json @@ -4,6 +4,8 @@ "version": "0.1.0", "description": "Example of Express integration with OpenTelemetry", "scripts": { + "lint": "eslint . --ext=ts,js,mjs", + "lint:fix": "eslint . --ext=ts,js,mjs --fix", "server": "ts-node src/server.ts", "client": "ts-node src/client.ts", "compile": "tsc -p ." diff --git a/examples/express/src/client.ts b/examples/express/src/client.ts index 6a39414d09..b23ed83f62 100644 --- a/examples/express/src/client.ts +++ b/examples/express/src/client.ts @@ -1,32 +1,57 @@ -'use strict'; +/* + * 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. + */ -// eslint-disable-next-line import/order -import { setupTracing } from "./tracer"; -const tracer = setupTracing('example-express-client'); +// eslint-disable-next-line import/order, import/extensions +import { setupTracing } from './tracer'; import * as api from '@opentelemetry/api'; -import { default as axios } from 'axios'; +import * as axios from 'axios'; + +const tracer = setupTracing('example-express-client'); -function makeRequest() { +async function makeRequest() { const span = tracer.startSpan('client.makeRequest()', { kind: api.SpanKind.CLIENT, }); - api.context.with(api.trace.setSpan(api.ROOT_CONTEXT, span), async () => { - try { - const res = await axios.get('http://localhost:8080/run_test'); - console.log('status:', res.statusText); - span.setStatus({ code: api.SpanStatusCode.OK }); - } catch (e) { - if (e instanceof Error) { - console.log('failed:', e.message); - span.setStatus({ code: api.SpanStatusCode.ERROR, message: e.message }); + await api.context.with( + api.trace.setSpan(api.ROOT_CONTEXT, span), + async () => { + try { + const res = await axios.get('http://localhost:8080/run_test'); + console.log('status:', res.statusText); + span.setStatus({ code: api.SpanStatusCode.OK }); + } catch (e) { + 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.' + ); + setTimeout(() => { + console.log('Completed.'); + }, 5000); } - span.end(); - console.log('Sleeping 5 seconds before shutdown to ensure all records are flushed.'); - setTimeout(() => { console.log('Completed.'); }, 5000); - }); + ); } -makeRequest(); +makeRequest().catch(err => console.log(err)); diff --git a/examples/express/src/server.ts b/examples/express/src/server.ts index ad111a2c92..424d79790e 100644 --- a/examples/express/src/server.ts +++ b/examples/express/src/server.ts @@ -1,11 +1,28 @@ -import { setupTracing } from './tracer' +/* + * 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. + */ -setupTracing('example-express-server'); +// eslint-disable-next-line import/order, import/extensions +import { setupTracing } from './tracer'; // Require in rest of modules import * as express from 'express'; -import { default as axios } from 'axios'; -import { RequestHandler } from "express"; +import * as axios from 'axios'; +import { RequestHandler } from 'express'; + +setupTracing('example-express-server'); // Setup express const app = express(); @@ -32,19 +49,21 @@ const authMiddleware: RequestHandler = (req, res, next) => { }; app.use(express.json()); -app.get('/health', (req, res) => res.status(200).send("HEALTHY")); // endpoint that is called by framework/cluster +app.get('/health', (req, res) => res.status(200).send('HEALTHY')); // endpoint that is called by framework/cluster app.get('/run_test', async (req, res) => { // Calls another endpoint of the same API, somewhat mimicking an external API call - const createdCat = await axios.post(`http://localhost:${PORT}/cats`, { - name: 'Tom', - friends: [ - 'Jerry', - ], - }, { - headers: { - Authorization: 'secret_token', + const createdCat = await axios.post( + `http://localhost:${PORT}/cats`, + { + name: 'Tom', + friends: ['Jerry'], }, - }); + { + headers: { + Authorization: 'secret_token', + }, + } + ); return res.status(201).send(createdCat.data); }); diff --git a/examples/express/src/tracer.ts b/examples/express/src/tracer.ts index d7122604cc..92e7a39ecd 100644 --- a/examples/express/src/tracer.ts +++ b/examples/express/src/tracer.ts @@ -1,24 +1,49 @@ -'use strict'; +/* + * 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, SamplingDecision, SpanKind, Attributes } from '@opentelemetry/api'; +import { + trace, + SamplingDecision, + SpanKind, + Attributes, +} from '@opentelemetry/api'; import { registerInstrumentations } from '@opentelemetry/instrumentation'; import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; -import { Sampler, AlwaysOnSampler, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'; +import { + Sampler, + AlwaysOnSampler, + SimpleSpanProcessor, +} from '@opentelemetry/sdk-trace-base'; import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto'; import { Resource } from '@opentelemetry/resources'; -import { ATTR_SERVICE_NAME, ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions'; +import { + ATTR_SERVICE_NAME, + ATTR_HTTP_ROUTE, +} from '@opentelemetry/semantic-conventions'; import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express'; import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'; +// eslint-disable-next-line import/prefer-default-export export const setupTracing = (serviceName: string) => { const exporter = new OTLPTraceExporter({}); const provider = new NodeTracerProvider({ resource: new Resource({ [ATTR_SERVICE_NAME]: serviceName, }), - spanProcessors: [ - new SimpleSpanProcessor(exporter), - ], + spanProcessors: [new SimpleSpanProcessor(exporter)], sampler: filterSampler(ignoreHealthCheck, new AlwaysOnSampler()), }); registerInstrumentations({ @@ -36,7 +61,11 @@ export const setupTracing = (serviceName: string) => { return trace.getTracer(serviceName); }; -type FilterFunction = (spanName: string, spanKind: SpanKind, attributes: Attributes) => boolean; +type FilterFunction = ( + spanName: string, + spanKind: SpanKind, + attributes: Attributes +) => boolean; function filterSampler(filterFn: FilterFunction, parent: Sampler): Sampler { return { @@ -48,10 +77,16 @@ function filterSampler(filterFn: FilterFunction, parent: Sampler): Sampler { }, toString() { return `FilterSampler(${parent.toString()})`; - } - } + }, + }; } -function ignoreHealthCheck(spanName: string, spanKind: SpanKind, attributes: Attributes) { - return spanKind !== SpanKind.SERVER || attributes[ATTR_HTTP_ROUTE] !== "/health"; +function ignoreHealthCheck( + spanName: string, + spanKind: SpanKind, + attributes: Attributes +) { + return ( + spanKind !== SpanKind.SERVER || attributes[ATTR_HTTP_ROUTE] !== '/health' + ); }