Skip to content

Commit

Permalink
feat(otel-node): add fs instrumentation (#601)
Browse files Browse the repository at this point in the history
  • Loading branch information
david-luna authored Feb 12, 2025
1 parent 697f766 commit acdcab5
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 6 deletions.
5 changes: 3 additions & 2 deletions packages/opentelemetry-node/docs/supported-technologies.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@ requires:
| `@opentelemetry/instrumentation-cassandra-driver` | `cassandra-driver` version range `>=4.4.0 <5` | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-cassandra#readme) |
| `@opentelemetry/instrumentation-express` | `express` version range `^4.0.0` | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-express#readme) |
| `@opentelemetry/instrumentation-fastify` | `fastify` version range `>=3 <5` | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-fastify#readme) |
| `@opentelemetry/instrumentation-fs` | `fs` module for suppported Node.js versions | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/instrumentation-fs#readme) |
| `@opentelemetry/instrumentation-generic-pool` | `generic-pool` version range `2 - 2.3, ^2.4, >=3` | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-generic-pool#readme) |
| `@opentelemetry/instrumentation-graphql` | `graphql` version range `>=14.0.0 <17` | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-graphql#readme) |
| `@opentelemetry/instrumentation-grpc` | `@grpc/grpc-js` version range `^1.0.0` | [README](https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-grpc#readme) |
| `@opentelemetry/instrumentation-hapi` | `@hapi/hapi >=17.0.0 <21` | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-hapi#readme) |
| `@opentelemetry/instrumentation-http` | `http` module for Node.js `>=14` | [README](https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-http#readme) |
| `@opentelemetry/instrumentation-http` | `http` module for suppported Node.js versions | [README](https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-http#readme) |
| `@opentelemetry/instrumentation-ioredis` | `ioredis` version range `>=2 <6` | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-ioredis#readme) |
| `@opentelemetry/instrumentation-kafkajs` | `kafkajs` version range `>=0.1.0 <3` | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/instrumentation-kafkajs#readme) |
| `@opentelemetry/instrumentation-knex` | `knex` version range `>=0.10.0` | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-knex#readme) |
Expand All @@ -58,7 +59,7 @@ requires:
| `@opentelemetry/instrumentation-mysql` | `mysql` version range `>=2.0.0 <3` | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/plugins/node/opentelemetry-instrumentation-mysql#readme) |
| `@opentelemetry/instrumentation-mysql2` | `mysql2` version range `>=1.4.2 <4` | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/plugins/node/opentelemetry-instrumentation-mysql2#readme) |
| `@opentelemetry/instrumentation-nestjs-core` | `@nestjs/core` version range `>=4.0.0` | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-nestjs-core#readme) |
| `@opentelemetry/instrumentation-net` | `net` module for Node.js `>=14` | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-net#readme) |
| `@opentelemetry/instrumentation-net` | `net` module for suppported Node.js versions | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-net#readme) |
| `@opentelemetry/instrumentation-pino` | `pino` version range `>=5.14.0 <10` | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-pino#readme) |
| `@opentelemetry/instrumentation-pg` | `pg` version range `>=8 <9` | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-pg#readme) |
| `@opentelemetry/instrumentation-redis-4` | `redis` version range `^4.0.0` | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-redis-4#readme) |
Expand Down
16 changes: 12 additions & 4 deletions packages/opentelemetry-node/lib/instrumentations.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
* "@opentelemetry/instrumentation-dns": import('@opentelemetry/instrumentation-dns').DnsInstrumentationConfig | InstrumentationFactory,
* "@opentelemetry/instrumentation-express": import('@opentelemetry/instrumentation-express').ExpressInstrumentationConfig | InstrumentationFactory,
* "@opentelemetry/instrumentation-fastify": import('@opentelemetry/instrumentation-fastify').FastifyInstrumentationConfig | InstrumentationFactory,
* "@opentelemetry/instrumentation-fs": import('@opentelemetry/instrumentation-fs').FsInstrumentationConfig | InstrumentationFactory,
* "@opentelemetry/instrumentation-generic-pool": import('@opentelemetry/instrumentation').InstrumentationConfig | InstrumentationFactory,
* "@opentelemetry/instrumentation-graphql": import('@opentelemetry/instrumentation-graphql').GraphQLInstrumentation | InstrumentationFactory,
* "@opentelemetry/instrumentation-grpc": import('@opentelemetry/instrumentation-grpc').GrpcInstrumentationConfig | InstrumentationFactory,
Expand Down Expand Up @@ -77,6 +78,7 @@ const {CucumberInstrumentation} = require('@opentelemetry/instrumentation-cucumb
const {DataloaderInstrumentation} = require('@opentelemetry/instrumentation-dataloader');
const {DnsInstrumentation} = require('@opentelemetry/instrumentation-dns');
const {ExpressInstrumentation} = require('@opentelemetry/instrumentation-express');
const {FsInstrumentation} = require('@opentelemetry/instrumentation-fs');
const {FastifyInstrumentation} = require('@opentelemetry/instrumentation-fastify');
const {GenericPoolInstrumentation} = require('@opentelemetry/instrumentation-generic-pool');
const {GraphQLInstrumentation} = require('@opentelemetry/instrumentation-graphql');
Expand Down Expand Up @@ -130,6 +132,7 @@ const INSTRUMENTATIONS = {
'@opentelemetry/instrumentation-dns': (cfg) => new DnsInstrumentation(cfg),
'@opentelemetry/instrumentation-express': (cfg) => new ExpressInstrumentation(cfg),
'@opentelemetry/instrumentation-fastify': (cfg) => new FastifyInstrumentation(cfg),
'@opentelemetry/instrumentation-fs': (cfg) => new FsInstrumentation(cfg),
'@opentelemetry/instrumentation-generic-pool': (cfg) => new GenericPoolInstrumentation(cfg),
'@opentelemetry/instrumentation-graphql': (cfg) => new GraphQLInstrumentation(cfg),
'@opentelemetry/instrumentation-grpc': (cfg) => new GrpcInstrumentation(cfg),
Expand Down Expand Up @@ -272,19 +275,24 @@ function getInstrumentations(opts = {}) {
const isFactory = typeof opts[name] === 'function';
const isObject = typeof opts[name] === 'object';
const instrFactory = isFactory ? opts[name] : INSTRUMENTATIONS[name];
const instrConfig = isObject ? opts[name] : undefined;
let instrConfig = isObject ? opts[name] : undefined;

// We should instantiate a instrumentation:
// - if set via OTEL_NODE_ENABLED_INSTRUMENTATIONS
// - overriding any config that might be passed
// NOTE: factories are not overwritten
// - otherwise
// - of there is no config passed (elastic SDK will use its defaults)
// - if there is no config passed (elastic SDK will use its defaults)
// - if the configuration passed is not disabling it
let instr;

if (instrConfig && enabledFromEnv) {
instrConfig.enabled = true;
if (enabledFromEnv) {
instrConfig = {...instrConfig, enabled: true};
} else if (name === '@opentelemetry/instrumentation-fs') {
// if `fs` not present in envvar instrumentation is disabled
// unless an explicit config says the opposite
// ref: https://github.com/open-telemetry/opentelemetry-js-contrib/pull/2467
instrConfig = {enabled: false, ...instrConfig};
}

if (!instrConfig || instrConfig.enabled !== false) {
Expand Down
25 changes: 25 additions & 0 deletions packages/opentelemetry-node/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/opentelemetry-node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
"@opentelemetry/instrumentation-dns": "^0.43.0",
"@opentelemetry/instrumentation-express": "^0.47.0",
"@opentelemetry/instrumentation-fastify": "^0.44.0",
"@opentelemetry/instrumentation-fs": "^0.19.0",
"@opentelemetry/instrumentation-generic-pool": "^0.43.0",
"@opentelemetry/instrumentation-graphql": "^0.47.0",
"@opentelemetry/instrumentation-grpc": "^0.57.1",
Expand Down
44 changes: 44 additions & 0 deletions packages/opentelemetry-node/test/fixtures/use-fs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you 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.
*/

// Usage: node -r @elastic/opentelemetry-node use-fs.js

const {join} = require('path');
const {stat} = require('fs');
const {trace} = require('@opentelemetry/api');

const path = join(__dirname, 'use-fs.js');

async function main() {
await new Promise((resolve, reject) => {
stat(path, (err, st) => {
if (err) {
reject(err);
} else {
resolve(st);
}
});
});
}

const tracer = trace.getTracer('test');
tracer.startActiveSpan('manual-span', async (span) => {
await main();
span.end();
});
85 changes: 85 additions & 0 deletions packages/opentelemetry-node/test/instr-fs.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you 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.
*/

// Test that 'express' instrumentation generates the telemetry we expect.

const test = require('tape');
const {runTestFixtures} = require('./testutils');

/** @type {import('./testutils').TestFixture[]} */
const testFixtures = [
{
name: 'use-fs (default disabled)',
args: ['./fixtures/use-fs.js'],
cwd: __dirname,
env: {
NODE_OPTIONS: '--require=@elastic/opentelemetry-node',
},
// verbose: true,
checkTelemetry: (t, col) => {
// We expect spans like this
// ------ trace 6dc0c7 (2 spans) ------
// span 3d5f2a "manual-span" (1.2ms, SPAN_KIND_INTERNAL)
const spans = col.sortedSpans;
t.equal(spans.length, 1);

t.equal(spans[0].name, 'manual-span');
t.equal(spans[0].kind, 'SPAN_KIND_INTERNAL');
},
},
{
name: 'use-fs (enabled via env var)',
args: ['./fixtures/use-fs.js'],
cwd: __dirname,
env: {
NODE_OPTIONS: '--require=@elastic/opentelemetry-node',
OTEL_NODE_ENABLED_INSTRUMENTATIONS: 'fs',
},
// verbose: true,
checkTelemetry: (t, col) => {
// We expect spans like this
// ------ trace 7c87d0 (1 span) ------
// span 1ecc98 "fs statSync" (0.0ms, SPAN_KIND_INTERNAL)
// ------ trace 281967 (1 span) ------
// span 7bab63 "fs statSync" (0.0ms, SPAN_KIND_INTERNAL)
// ------ trace 8b214a (1 span) ------
// span 417068 "fs readFileSync" (0.1ms, SPAN_KIND_INTERNAL)
// ------ trace d61bc6 (1 span) ------
// span a6f9cc "fs statSync" (0.1ms, SPAN_KIND_INTERNAL)
// ------ trace 292114 (2 spans) ------
// span c66b96 "manual-span" (6.6ms, SPAN_KIND_INTERNAL)
// +1ms `- span 5b7d1c "fs stat" (6.3ms, SPAN_KIND_INTERNAL)
const spans = col.sortedSpans;
t.equal(spans.length, 18);

t.strictEqual(
spans.filter(
(s) => s.scope.name === '@opentelemetry/instrumentation-fs'
).length,
17
);
t.ok(spans.every((s) => s.kind === 'SPAN_KIND_INTERNAL'));
},
},
];

test('fs instrumentation', (suite) => {
runTestFixtures(suite, testFixtures);
suite.end();
});
1 change: 1 addition & 0 deletions packages/opentelemetry-node/types/instrumentations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type InstrumentaionsMap = {
"@opentelemetry/instrumentation-dns": import('@opentelemetry/instrumentation-dns').DnsInstrumentationConfig | InstrumentationFactory;
"@opentelemetry/instrumentation-express": import('@opentelemetry/instrumentation-express').ExpressInstrumentationConfig | InstrumentationFactory;
"@opentelemetry/instrumentation-fastify": import('@opentelemetry/instrumentation-fastify').FastifyInstrumentationConfig | InstrumentationFactory;
"@opentelemetry/instrumentation-fs": import('@opentelemetry/instrumentation-fs').FsInstrumentationConfig | InstrumentationFactory;
"@opentelemetry/instrumentation-generic-pool": import('@opentelemetry/instrumentation').InstrumentationConfig | InstrumentationFactory;
"@opentelemetry/instrumentation-graphql": import('@opentelemetry/instrumentation-graphql').GraphQLInstrumentation | InstrumentationFactory;
"@opentelemetry/instrumentation-grpc": import('@opentelemetry/instrumentation-grpc').GrpcInstrumentationConfig | InstrumentationFactory;
Expand Down

0 comments on commit acdcab5

Please sign in to comment.