From 30b1121a4ae4bddcd7cca67b5891a869dc517bb6 Mon Sep 17 00:00:00 2001 From: Trent Mick Date: Tue, 17 Dec 2024 08:17:38 -0800 Subject: [PATCH] feat(opentelemetry-node): add @elastic/opentelemetry-instrumentation-openai (#480) --- .github/workflows/test-edot.yml | 7 + examples/openai-chat.js | 36 + examples/package-lock.json | 799 +++++++++++++++--- examples/package.json | 4 +- packages/instrumentation-openai/LICENSE | 202 +++++ packages/instrumentation-openai/package.json | 4 + packages/mockotlpserver/lib/http.js | 13 +- packages/opentelemetry-node/CHANGELOG.md | 5 + .../docs/supported-technologies.md | 1 + .../lib/elastic-node-sdk.js | 6 +- .../lib/instrumentations.js | 3 + .../opentelemetry-node/lib/metrics/host.js | 13 +- packages/opentelemetry-node/package-lock.json | 340 +++++++- packages/opentelemetry-node/package.json | 4 +- ...DE_ENABLE_DISABLE_INSTRUMENTATIONS.test.js | 4 +- .../test/docker-compose.yaml | 14 +- .../test/fixtures/use-elastic-openai.js | 36 + .../test/instr-elastic-openai.test.js | 130 +++ .../test/instr-mongodb.test.js | 2 +- .../opentelemetry-node/test/test-services.env | 7 +- packages/opentelemetry-node/test/testutils.js | 46 + .../types/instrumentations.d.ts | 1 + .../types/metrics/host.d.ts | 8 +- scripts/gen-notice.sh | 3 + 24 files changed, 1562 insertions(+), 126 deletions(-) create mode 100644 examples/openai-chat.js create mode 100644 packages/instrumentation-openai/LICENSE create mode 100644 packages/opentelemetry-node/test/fixtures/use-elastic-openai.js create mode 100644 packages/opentelemetry-node/test/instr-elastic-openai.test.js diff --git a/.github/workflows/test-edot.yml b/.github/workflows/test-edot.yml index 9c76001a..11ea3392 100644 --- a/.github/workflows/test-edot.yml +++ b/.github/workflows/test-edot.yml @@ -54,6 +54,13 @@ jobs: ports: - 27017:27017 + ollama: + # A light fork of Ollama to float some in-progress contributions related + # to more closely matching OpenAI behavior. + image: ghcr.io/elastic/ollama/ollama:testing + ports: + - 11434:11434 + postgres: image: postgres:16 ports: diff --git a/examples/openai-chat.js b/examples/openai-chat.js new file mode 100644 index 00000000..5c35287f --- /dev/null +++ b/examples/openai-chat.js @@ -0,0 +1,36 @@ +/* + * 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: +// OPENAI_API_KEY=sk-... \ +// node -r @elastic/opentelemetry-node openai-chat.js + +const {OpenAI} = require('openai'); + +async function main() { + const openai = new OpenAI(); + const result = await openai.chat.completions.create({ + model: 'gpt-4o-mini', + messages: [ + {role: 'user', content: 'Why is the sky blue? Answer briefly.'}, + ], + }); + console.log(result.choices[0]?.message?.content); +} +main(); diff --git a/examples/package-lock.json b/examples/package-lock.json index c44082ec..83a842d6 100644 --- a/examples/package-lock.json +++ b/examples/package-lock.json @@ -13,7 +13,9 @@ "@opentelemetry/api": "^1.9.0", "@opentelemetry/instrumentation-express": "^0.45.0", "bunyan": "^1.8.15", - "express": "^4.19.2" + "express": "^4.19.2", + "openai": "^4.76.3", + "pino-pretty": "^13.0.0" } }, "../packages/opentelemetry-node": { @@ -21,55 +23,56 @@ "version": "0.5.0", "license": "Apache-2.0", "dependencies": { + "@elastic/opentelemetry-instrumentation-openai": "^0.4.0", "@opentelemetry/core": "1.27.0", - "@opentelemetry/exporter-logs-otlp-grpc": "^0.54.0", - "@opentelemetry/exporter-logs-otlp-http": "^0.54.0", - "@opentelemetry/exporter-logs-otlp-proto": "^0.54.0", - "@opentelemetry/exporter-metrics-otlp-grpc": "^0.54.0", - "@opentelemetry/exporter-metrics-otlp-http": "^0.54.0", - "@opentelemetry/exporter-metrics-otlp-proto": "^0.54.0", + "@opentelemetry/exporter-logs-otlp-grpc": "^0.56.0", + "@opentelemetry/exporter-logs-otlp-http": "^0.56.0", + "@opentelemetry/exporter-logs-otlp-proto": "^0.56.0", + "@opentelemetry/exporter-metrics-otlp-grpc": "^0.56.0", + "@opentelemetry/exporter-metrics-otlp-http": "^0.56.0", + "@opentelemetry/exporter-metrics-otlp-proto": "^0.56.0", "@opentelemetry/host-metrics": "^0.35.0", - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/instrumentation-aws-sdk": "^0.46.0", - "@opentelemetry/instrumentation-bunyan": "^0.42.0", - "@opentelemetry/instrumentation-connect": "^0.40.0", - "@opentelemetry/instrumentation-cucumber": "^0.10.0", - "@opentelemetry/instrumentation-dataloader": "^0.13.0", - "@opentelemetry/instrumentation-dns": "^0.40.0", - "@opentelemetry/instrumentation-express": "^0.44.0", - "@opentelemetry/instrumentation-fastify": "^0.41.0", - "@opentelemetry/instrumentation-generic-pool": "^0.40.0", - "@opentelemetry/instrumentation-grpc": "^0.54.0", - "@opentelemetry/instrumentation-hapi": "^0.42.0", - "@opentelemetry/instrumentation-http": "^0.54.0", - "@opentelemetry/instrumentation-ioredis": "^0.44.0", - "@opentelemetry/instrumentation-knex": "^0.41.0", - "@opentelemetry/instrumentation-koa": "^0.44.0", - "@opentelemetry/instrumentation-lru-memoizer": "^0.41.0", - "@opentelemetry/instrumentation-memcached": "^0.40.0", - "@opentelemetry/instrumentation-mongodb": "^0.48.0", - "@opentelemetry/instrumentation-nestjs-core": "^0.41.0", - "@opentelemetry/instrumentation-net": "^0.40.0", - "@opentelemetry/instrumentation-pg": "^0.47.0", - "@opentelemetry/instrumentation-pino": "^0.43.0", - "@opentelemetry/instrumentation-redis": "^0.43.0", - "@opentelemetry/instrumentation-redis-4": "^0.43.0", - "@opentelemetry/instrumentation-restify": "^0.42.0", - "@opentelemetry/instrumentation-router": "^0.41.0", - "@opentelemetry/instrumentation-runtime-node": "^0.9.0", - "@opentelemetry/instrumentation-socket.io": "^0.43.0", - "@opentelemetry/instrumentation-tedious": "^0.15.0", - "@opentelemetry/instrumentation-undici": "^0.7.0", - "@opentelemetry/instrumentation-winston": "^0.41.0", + "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation-aws-sdk": "^0.48.0", + "@opentelemetry/instrumentation-bunyan": "^0.44.0", + "@opentelemetry/instrumentation-connect": "^0.42.0", + "@opentelemetry/instrumentation-cucumber": "^0.12.0", + "@opentelemetry/instrumentation-dataloader": "^0.15.0", + "@opentelemetry/instrumentation-dns": "^0.42.0", + "@opentelemetry/instrumentation-express": "^0.46.0", + "@opentelemetry/instrumentation-fastify": "^0.43.0", + "@opentelemetry/instrumentation-generic-pool": "^0.42.0", + "@opentelemetry/instrumentation-grpc": "^0.56.0", + "@opentelemetry/instrumentation-hapi": "^0.44.0", + "@opentelemetry/instrumentation-http": "^0.56.0", + "@opentelemetry/instrumentation-ioredis": "^0.46.0", + "@opentelemetry/instrumentation-knex": "^0.43.0", + "@opentelemetry/instrumentation-koa": "^0.46.0", + "@opentelemetry/instrumentation-lru-memoizer": "^0.43.0", + "@opentelemetry/instrumentation-memcached": "^0.42.0", + "@opentelemetry/instrumentation-mongodb": "^0.50.0", + "@opentelemetry/instrumentation-nestjs-core": "^0.43.0", + "@opentelemetry/instrumentation-net": "^0.42.0", + "@opentelemetry/instrumentation-pg": "^0.49.0", + "@opentelemetry/instrumentation-pino": "^0.45.0", + "@opentelemetry/instrumentation-redis": "^0.45.0", + "@opentelemetry/instrumentation-redis-4": "^0.45.0", + "@opentelemetry/instrumentation-restify": "^0.44.0", + "@opentelemetry/instrumentation-router": "^0.43.0", + "@opentelemetry/instrumentation-runtime-node": "^0.11.0", + "@opentelemetry/instrumentation-socket.io": "^0.45.0", + "@opentelemetry/instrumentation-tedious": "^0.17.0", + "@opentelemetry/instrumentation-undici": "^0.9.0", + "@opentelemetry/instrumentation-winston": "^0.43.0", "@opentelemetry/resource-detector-alibaba-cloud": "^0.29.1", "@opentelemetry/resource-detector-aws": "^1.6.1", - "@opentelemetry/resource-detector-azure": "^0.2.11", + "@opentelemetry/resource-detector-azure": "^0.4.0", "@opentelemetry/resource-detector-container": "^0.5.0", - "@opentelemetry/resource-detector-gcp": "^0.29.11", + "@opentelemetry/resource-detector-gcp": "^0.31.0", "@opentelemetry/resources": "^1.26.0", - "@opentelemetry/sdk-logs": "^0.54.0", - "@opentelemetry/sdk-node": "^0.54.0", - "@opentelemetry/winston-transport": "^0.7.0", + "@opentelemetry/sdk-logs": "^0.56.0", + "@opentelemetry/sdk-node": "^0.56.0", + "@opentelemetry/winston-transport": "^0.9.0", "safe-stable-stringify": "^2.4.3" }, "devDependencies": { @@ -90,13 +93,14 @@ "ioredis": "^5.4.1", "module-details-from-path": "^1.0.3", "mongodb": "^6.9.0", + "openai": "^4.76.3", "pg": "^8.13.0", "pino": "^9.4.0", "redis": "^4.7.0", "semver": "^7.6.3", "tape": "^5.9.0", "tedious": "^18.6.1", - "undici": "^6.19.8", + "undici": "^7.1.0", "winston": "^3.13.1" }, "engines": { @@ -183,11 +187,39 @@ "node": ">=14" } }, + "node_modules/@types/node": { + "version": "18.19.68", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.68.tgz", + "integrity": "sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, "node_modules/@types/shimmer": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==" }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -219,11 +251,36 @@ "acorn": "^8" } }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -311,6 +368,23 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==" }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -349,6 +423,15 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -373,6 +456,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -416,6 +507,15 @@ "node": ">= 0.8" } }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", @@ -448,6 +548,14 @@ "node": ">= 0.6" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, "node_modules/express": { "version": "4.21.0", "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", @@ -489,6 +597,18 @@ "node": ">= 0.10.0" } }, + "node_modules/fast-copy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", + "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", + "license": "MIT" + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "license": "MIT" + }, "node_modules/finalhandler": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", @@ -506,6 +626,36 @@ "node": ">= 0.8" } }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data-encoder": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==" + }, + "node_modules/formdata-node": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", + "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", + "dependencies": { + "node-domexception": "1.0.0", + "web-streams-polyfill": "4.0.0-beta.3" + }, + "engines": { + "node": ">= 12.20" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -620,6 +770,12 @@ "node": ">= 0.4" } }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "license": "MIT" + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -635,6 +791,14 @@ "node": ">= 0.8" } }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dependencies": { + "ms": "^2.0.0" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -695,6 +859,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -765,7 +938,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "optional": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -838,6 +1010,43 @@ "node": ">= 0.6" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/object-inspect": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", @@ -849,6 +1058,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -864,11 +1082,35 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "optional": true, "dependencies": { "wrappy": "1" } }, + "node_modules/openai": { + "version": "4.76.3", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.76.3.tgz", + "integrity": "sha512-BISkI90m8zT7BAMljK0j00TzOoLvmc7AulPxv6EARa++3+hhIK5G6z4xkITurEaA9bvDhQ09kSNKA3DL+rDMwA==", + "dependencies": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7" + }, + "bin": { + "openai": "bin/cli" + }, + "peerDependencies": { + "zod": "^3.23.8" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -896,6 +1138,39 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" }, + "node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-pretty": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.0.0.tgz", + "integrity": "sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==", + "license": "MIT", + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.2", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pump": "^3.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^4.0.1", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -908,6 +1183,16 @@ "node": ">= 0.10" } }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/qs": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", @@ -1037,6 +1322,12 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "license": "BSD-3-Clause" + }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -1141,6 +1432,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sonic-boom": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -1149,6 +1458,18 @@ "node": ">= 0.8" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -1168,6 +1489,11 @@ "node": ">=0.6" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -1180,6 +1506,11 @@ "node": ">= 0.6" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -1204,11 +1535,32 @@ "node": ">= 0.8" } }, + "node_modules/web-streams-polyfill": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", + "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "optional": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" } }, "dependencies": { @@ -1220,59 +1572,60 @@ "@aws-sdk/client-sns": "^3.658.1", "@aws-sdk/client-sqs": "^3.658.1", "@elastic/mockotlpserver": "../mockotlpserver", + "@elastic/opentelemetry-instrumentation-openai": "^0.4.0", "@grpc/grpc-js": "^1.11.1", "@grpc/proto-loader": "^0.7.13", "@hapi/hapi": "^21.3.10", "@opentelemetry/api": "^1.3.0", "@opentelemetry/core": "1.27.0", - "@opentelemetry/exporter-logs-otlp-grpc": "^0.54.0", - "@opentelemetry/exporter-logs-otlp-http": "^0.54.0", - "@opentelemetry/exporter-logs-otlp-proto": "^0.54.0", - "@opentelemetry/exporter-metrics-otlp-grpc": "^0.54.0", - "@opentelemetry/exporter-metrics-otlp-http": "^0.54.0", - "@opentelemetry/exporter-metrics-otlp-proto": "^0.54.0", + "@opentelemetry/exporter-logs-otlp-grpc": "^0.56.0", + "@opentelemetry/exporter-logs-otlp-http": "^0.56.0", + "@opentelemetry/exporter-logs-otlp-proto": "^0.56.0", + "@opentelemetry/exporter-metrics-otlp-grpc": "^0.56.0", + "@opentelemetry/exporter-metrics-otlp-http": "^0.56.0", + "@opentelemetry/exporter-metrics-otlp-proto": "^0.56.0", "@opentelemetry/host-metrics": "^0.35.0", - "@opentelemetry/instrumentation": "^0.54.0", - "@opentelemetry/instrumentation-aws-sdk": "^0.46.0", - "@opentelemetry/instrumentation-bunyan": "^0.42.0", - "@opentelemetry/instrumentation-connect": "^0.40.0", - "@opentelemetry/instrumentation-cucumber": "^0.10.0", - "@opentelemetry/instrumentation-dataloader": "^0.13.0", - "@opentelemetry/instrumentation-dns": "^0.40.0", - "@opentelemetry/instrumentation-express": "^0.44.0", - "@opentelemetry/instrumentation-fastify": "^0.41.0", - "@opentelemetry/instrumentation-generic-pool": "^0.40.0", - "@opentelemetry/instrumentation-grpc": "^0.54.0", - "@opentelemetry/instrumentation-hapi": "^0.42.0", - "@opentelemetry/instrumentation-http": "^0.54.0", - "@opentelemetry/instrumentation-ioredis": "^0.44.0", - "@opentelemetry/instrumentation-knex": "^0.41.0", - "@opentelemetry/instrumentation-koa": "^0.44.0", - "@opentelemetry/instrumentation-lru-memoizer": "^0.41.0", - "@opentelemetry/instrumentation-memcached": "^0.40.0", - "@opentelemetry/instrumentation-mongodb": "^0.48.0", - "@opentelemetry/instrumentation-nestjs-core": "^0.41.0", - "@opentelemetry/instrumentation-net": "^0.40.0", - "@opentelemetry/instrumentation-pg": "^0.47.0", - "@opentelemetry/instrumentation-pino": "^0.43.0", - "@opentelemetry/instrumentation-redis": "^0.43.0", - "@opentelemetry/instrumentation-redis-4": "^0.43.0", - "@opentelemetry/instrumentation-restify": "^0.42.0", - "@opentelemetry/instrumentation-router": "^0.41.0", - "@opentelemetry/instrumentation-runtime-node": "^0.9.0", - "@opentelemetry/instrumentation-socket.io": "^0.43.0", - "@opentelemetry/instrumentation-tedious": "^0.15.0", - "@opentelemetry/instrumentation-undici": "^0.7.0", - "@opentelemetry/instrumentation-winston": "^0.41.0", + "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation-aws-sdk": "^0.48.0", + "@opentelemetry/instrumentation-bunyan": "^0.44.0", + "@opentelemetry/instrumentation-connect": "^0.42.0", + "@opentelemetry/instrumentation-cucumber": "^0.12.0", + "@opentelemetry/instrumentation-dataloader": "^0.15.0", + "@opentelemetry/instrumentation-dns": "^0.42.0", + "@opentelemetry/instrumentation-express": "^0.46.0", + "@opentelemetry/instrumentation-fastify": "^0.43.0", + "@opentelemetry/instrumentation-generic-pool": "^0.42.0", + "@opentelemetry/instrumentation-grpc": "^0.56.0", + "@opentelemetry/instrumentation-hapi": "^0.44.0", + "@opentelemetry/instrumentation-http": "^0.56.0", + "@opentelemetry/instrumentation-ioredis": "^0.46.0", + "@opentelemetry/instrumentation-knex": "^0.43.0", + "@opentelemetry/instrumentation-koa": "^0.46.0", + "@opentelemetry/instrumentation-lru-memoizer": "^0.43.0", + "@opentelemetry/instrumentation-memcached": "^0.42.0", + "@opentelemetry/instrumentation-mongodb": "^0.50.0", + "@opentelemetry/instrumentation-nestjs-core": "^0.43.0", + "@opentelemetry/instrumentation-net": "^0.42.0", + "@opentelemetry/instrumentation-pg": "^0.49.0", + "@opentelemetry/instrumentation-pino": "^0.45.0", + "@opentelemetry/instrumentation-redis": "^0.45.0", + "@opentelemetry/instrumentation-redis-4": "^0.45.0", + "@opentelemetry/instrumentation-restify": "^0.44.0", + "@opentelemetry/instrumentation-router": "^0.43.0", + "@opentelemetry/instrumentation-runtime-node": "^0.11.0", + "@opentelemetry/instrumentation-socket.io": "^0.45.0", + "@opentelemetry/instrumentation-tedious": "^0.17.0", + "@opentelemetry/instrumentation-undici": "^0.9.0", + "@opentelemetry/instrumentation-winston": "^0.43.0", "@opentelemetry/resource-detector-alibaba-cloud": "^0.29.1", "@opentelemetry/resource-detector-aws": "^1.6.1", - "@opentelemetry/resource-detector-azure": "^0.2.11", + "@opentelemetry/resource-detector-azure": "^0.4.0", "@opentelemetry/resource-detector-container": "^0.5.0", - "@opentelemetry/resource-detector-gcp": "^0.29.11", + "@opentelemetry/resource-detector-gcp": "^0.31.0", "@opentelemetry/resources": "^1.26.0", - "@opentelemetry/sdk-logs": "^0.54.0", - "@opentelemetry/sdk-node": "^0.54.0", - "@opentelemetry/winston-transport": "^0.7.0", + "@opentelemetry/sdk-logs": "^0.56.0", + "@opentelemetry/sdk-node": "^0.56.0", + "@opentelemetry/winston-transport": "^0.9.0", "@types/tape": "^5.6.4", "bunyan": "^1.8.15", "dotenv": "^16.4.5", @@ -1281,6 +1634,7 @@ "ioredis": "^5.4.1", "module-details-from-path": "^1.0.3", "mongodb": "^6.9.0", + "openai": "^4.76.3", "pg": "^8.13.0", "pino": "^9.4.0", "redis": "^4.7.0", @@ -1288,7 +1642,7 @@ "semver": "^7.6.3", "tape": "^5.9.0", "tedious": "^18.6.1", - "undici": "^6.19.8", + "undici": "^7.1.0", "winston": "^3.13.1" } }, @@ -1341,11 +1695,36 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz", "integrity": "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==" }, + "@types/node": { + "version": "18.19.68", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.68.tgz", + "integrity": "sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw==", + "requires": { + "undici-types": "~5.26.4" + } + }, + "@types/node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==", + "requires": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, "@types/shimmer": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==" }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -1366,11 +1745,29 @@ "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", "requires": {} }, + "agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "requires": { + "humanize-ms": "^1.2.1" + } + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==" + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1439,6 +1836,19 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==" }, + "colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1468,6 +1878,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==" + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1486,6 +1901,11 @@ "gopd": "^1.0.1" } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1515,6 +1935,14 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, "es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", @@ -1538,6 +1966,11 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, "express": { "version": "4.21.0", "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", @@ -1576,6 +2009,16 @@ "vary": "~1.1.2" } }, + "fast-copy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", + "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==" + }, + "fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" + }, "finalhandler": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", @@ -1590,6 +2033,30 @@ "unpipe": "~1.0.0" } }, + "form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "form-data-encoder": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==" + }, + "formdata-node": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", + "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", + "requires": { + "node-domexception": "1.0.0", + "web-streams-polyfill": "4.0.0-beta.3" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -1664,6 +2131,11 @@ "function-bind": "^1.1.2" } }, + "help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" + }, "http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -1676,6 +2148,14 @@ "toidentifier": "1.0.1" } }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "requires": { + "ms": "^2.0.0" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1723,6 +2203,11 @@ "hasown": "^2.0.2" } }, + "joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==" + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -1768,8 +2253,7 @@ "minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "optional": true + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, "mkdirp": { "version": "0.5.6", @@ -1824,11 +2308,29 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" + }, + "node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, "object-inspect": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==" }, + "on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==" + }, "on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -1841,11 +2343,24 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "optional": true, "requires": { "wrappy": "1" } }, + "openai": { + "version": "4.76.3", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.76.3.tgz", + "integrity": "sha512-BISkI90m8zT7BAMljK0j00TzOoLvmc7AulPxv6EARa++3+hhIK5G6z4xkITurEaA9bvDhQ09kSNKA3DL+rDMwA==", + "requires": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7" + } + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -1867,6 +2382,34 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" }, + "pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "requires": { + "split2": "^4.0.0" + } + }, + "pino-pretty": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.0.0.tgz", + "integrity": "sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==", + "requires": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.2", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pump": "^3.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^4.0.1", + "strip-json-comments": "^3.1.1" + } + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -1876,6 +2419,15 @@ "ipaddr.js": "1.9.1" } }, + "pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "qs": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", @@ -1960,6 +2512,11 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" + }, "semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -2042,11 +2599,29 @@ "object-inspect": "^1.13.1" } }, + "sonic-boom": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "requires": { + "atomic-sleep": "^1.0.0" + } + }, + "split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==" + }, "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + }, "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -2057,6 +2632,11 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -2066,6 +2646,11 @@ "mime-types": "~2.1.24" } }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -2081,11 +2666,29 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" }, + "web-streams-polyfill": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", + "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "optional": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" } } } diff --git a/examples/package.json b/examples/package.json index 787c0485..1e93c829 100644 --- a/examples/package.json +++ b/examples/package.json @@ -11,6 +11,8 @@ "@opentelemetry/api": "^1.9.0", "@opentelemetry/instrumentation-express": "^0.45.0", "bunyan": "^1.8.15", - "express": "^4.19.2" + "express": "^4.19.2", + "openai": "^4.76.3", + "pino-pretty": "^13.0.0" } } diff --git a/packages/instrumentation-openai/LICENSE b/packages/instrumentation-openai/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/packages/instrumentation-openai/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/packages/instrumentation-openai/package.json b/packages/instrumentation-openai/package.json index 6c96cc72..483f4107 100644 --- a/packages/instrumentation-openai/package.json +++ b/packages/instrumentation-openai/package.json @@ -49,6 +49,10 @@ "test:all-integration-tests": "npm run test:integration-openai && npm run test:integration-azure && npm run test:integration-ollama" }, "files": [ + "CHANGELOG.md", + "LICENSE", + "NOTICE.md", + "README.md", "build/src/**/*.js", "build/src/**/*.js.map", "build/src/**/*.d.ts" diff --git a/packages/mockotlpserver/lib/http.js b/packages/mockotlpserver/lib/http.js index d9e8fd76..862f6b43 100644 --- a/packages/mockotlpserver/lib/http.js +++ b/packages/mockotlpserver/lib/http.js @@ -49,7 +49,11 @@ function diagChFromReqUrl(reqUrl) { } // helper functions -function badRequest(res, errMsg='Invalid or no data received', errCode=400) { +function badRequest( + res, + errMsg = 'Invalid or no data received', + errCode = 400 +) { res.writeHead(400); res.end( JSON.stringify({ @@ -133,7 +137,10 @@ class HttpService extends Service { this._server = http.createServer((req, res) => { const contentType = req.headers['content-type']; if (!parsersMap[contentType]) { - return badRequest(res, `unexpected request Content-Type: "${contentType}"`) + return badRequest( + res, + `unexpected request Content-Type: "${contentType}"` + ); } const chunks = []; @@ -154,7 +161,7 @@ class HttpService extends Service { let resBody = null; if (contentType === 'application/json') { resBody = JSON.stringify({ - ok: 1 + ok: 1, }); } res.writeHead(200); diff --git a/packages/opentelemetry-node/CHANGELOG.md b/packages/opentelemetry-node/CHANGELOG.md index 2764d115..a7006033 100644 --- a/packages/opentelemetry-node/CHANGELOG.md +++ b/packages/opentelemetry-node/CHANGELOG.md @@ -1,5 +1,10 @@ # @elastic/opentelemetry-node Changelog +## Unreleased + +- feat: Add `@elastic/opentelemetry-instrumentation-openai` to the default set + of instrumentations. See + ## v0.5.0 - chore: Bump `@opentelemetry/*` dependencies (#419, #411, #403) diff --git a/packages/opentelemetry-node/docs/supported-technologies.md b/packages/opentelemetry-node/docs/supported-technologies.md index c9ff289a..cd8294f6 100644 --- a/packages/opentelemetry-node/docs/supported-technologies.md +++ b/packages/opentelemetry-node/docs/supported-technologies.md @@ -35,6 +35,7 @@ requires: | Name | Packages instrumented | Reference | |---|---|---| +| `@elastic/opentelemetry-instrumentation-openai` | `openai` version range `>=4.19.0 <5` | [README](https://github.com/elastic/elastic-otel-node/tree/main/packages/instrumentation-openai#readme) | | `@opentelemetry/instrumentation-aws-sdk` | `aws-sdk` v2 and `@aws-sdk/client-*` v3 | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-aws-sdk#readme) | | `@opentelemetry/instrumentation-bunyan` | `bunyan` version range `^1.0.0` | [README](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-bunyan#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) | diff --git a/packages/opentelemetry-node/lib/elastic-node-sdk.js b/packages/opentelemetry-node/lib/elastic-node-sdk.js index 2e791de9..dcc4f8b5 100644 --- a/packages/opentelemetry-node/lib/elastic-node-sdk.js +++ b/packages/opentelemetry-node/lib/elastic-node-sdk.js @@ -79,9 +79,9 @@ class ElasticNodeSDK extends NodeSDK { const {OTLPLogExporter} = require( `@opentelemetry/exporter-logs-otlp-${logExporterType}` ); - defaultConfig.logRecordProcessor = new BatchLogRecordProcessor( - new OTLPLogExporter() - ); + defaultConfig.logRecordProcessors = [ + new BatchLogRecordProcessor(new OTLPLogExporter()), + ]; // Default metrics exporter. // Currently NodeSDK does not handle `OTEL_METRICS_EXPORTER` diff --git a/packages/opentelemetry-node/lib/instrumentations.js b/packages/opentelemetry-node/lib/instrumentations.js index 68b14ec2..df3b88ce 100644 --- a/packages/opentelemetry-node/lib/instrumentations.js +++ b/packages/opentelemetry-node/lib/instrumentations.js @@ -24,6 +24,7 @@ * @returns {Instrumentation} * * @typedef {{ + * "@elastic/opentelemetry-instrumentation-openai": import('@elastic/opentelemetry-instrumentation-openai').OpenAIInstrumentationConfig | InstrumentationFactory, * "@opentelemetry/instrumentation-aws-sdk": import('@opentelemetry/instrumentation-aws-sdk').AwsSdkInstrumentationConfig | InstrumentationFactory, * "@opentelemetry/instrumentation-bunyan": import('@opentelemetry/instrumentation-bunyan').BunyanInstrumentationConfig | InstrumentationFactory, * "@opentelemetry/instrumentation-connect": import('@opentelemetry/instrumentation').InstrumentationConfig | InstrumentationFactory, @@ -59,6 +60,7 @@ */ /* eslint-disable prettier/prettier */ +const {OpenAIInstrumentation} = require('@elastic/opentelemetry-instrumentation-openai'); const {AwsInstrumentation} = require('@opentelemetry/instrumentation-aws-sdk'); const {BunyanInstrumentation} = require('@opentelemetry/instrumentation-bunyan'); const {ConnectInstrumentation} = require('@opentelemetry/instrumentation-connect'); @@ -103,6 +105,7 @@ const { getEnvVar } = require('./environment'); // the user's config and can default to something else if needed. /** @type {Record Instrumentation>} */ const INSTRUMENTATIONS = { + '@elastic/opentelemetry-instrumentation-openai': (cfg) => new OpenAIInstrumentation(cfg), '@opentelemetry/instrumentation-aws-sdk': (cfg) => new AwsInstrumentation(cfg), '@opentelemetry/instrumentation-bunyan': (cfg) => new BunyanInstrumentation(cfg), '@opentelemetry/instrumentation-connect': (cfg) => new ConnectInstrumentation(cfg), diff --git a/packages/opentelemetry-node/lib/metrics/host.js b/packages/opentelemetry-node/lib/metrics/host.js index b0820ef7..ac2d7cde 100644 --- a/packages/opentelemetry-node/lib/metrics/host.js +++ b/packages/opentelemetry-node/lib/metrics/host.js @@ -17,15 +17,18 @@ * under the License. */ -const {metrics} = require('@opentelemetry/sdk-node'); -const {Aggregation, View} = metrics; +const {metrics} = require('@opentelemetry/api'); +const {metrics: metricsSdk} = require('@opentelemetry/sdk-node'); +const {Aggregation, View} = metricsSdk; const {HostMetrics} = require('@opentelemetry/host-metrics'); /** @type {HostMetrics} */ let hostMetricsInstance; function enableHostMetrics() { - // @ts-ignore - config interface expects a `name` property but there is a default value - hostMetricsInstance = new HostMetrics({}); + hostMetricsInstance = new HostMetrics({ + // Pass in default meterProvider to avoid a log.warn('No meter provider, using default'). + meterProvider: metrics.getMeterProvider(), + }); hostMetricsInstance.start(); } @@ -33,7 +36,7 @@ function enableHostMetrics() { // - sends a lot of data. Ref: https://github.com/elastic/elastic-otel-node/issues/51 // - not displayed by Kibana in metrics dashboard. Ref: https://github.com/elastic/kibana/pull/199353 // - recommendation is to use OTEL collector to get and export them -/** @type {metrics.View[]} */ +/** @type {metricsSdk.View[]} */ const HOST_METRICS_VIEWS = [ new View({ instrumentName: 'system.*', diff --git a/packages/opentelemetry-node/package-lock.json b/packages/opentelemetry-node/package-lock.json index 6dab8312..a879fdda 100644 --- a/packages/opentelemetry-node/package-lock.json +++ b/packages/opentelemetry-node/package-lock.json @@ -9,6 +9,7 @@ "version": "0.5.0", "license": "Apache-2.0", "dependencies": { + "@elastic/opentelemetry-instrumentation-openai": "^0.4.0", "@opentelemetry/core": "1.27.0", "@opentelemetry/exporter-logs-otlp-grpc": "^0.56.0", "@opentelemetry/exporter-logs-otlp-http": "^0.56.0", @@ -78,6 +79,7 @@ "ioredis": "^5.4.1", "module-details-from-path": "^1.0.3", "mongodb": "^6.9.0", + "openai": "^4.76.3", "pg": "^8.13.0", "pino": "^9.4.0", "redis": "^4.7.0", @@ -1612,6 +1614,46 @@ "resolved": "../mockotlpserver", "link": true }, + "node_modules/@elastic/opentelemetry-instrumentation-openai": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@elastic/opentelemetry-instrumentation-openai/-/opentelemetry-instrumentation-openai-0.4.0.tgz", + "integrity": "sha512-o9lxtoozYqW4yP9WP8DL7HVb1buy5GAE/mCRN5AXDuVWPflENFOfBnbgyS3wI/9TXDk6oIBEtAw/cwJYsiPQaA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "^0.56.0", + "@opentelemetry/instrumentation": "^0.56.0", + "debug": "^4.3.6" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@elastic/opentelemetry-instrumentation-openai/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@elastic/opentelemetry-instrumentation-openai/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, "node_modules/@fastify/ajv-compiler": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-4.0.1.tgz", @@ -4521,13 +4563,25 @@ } }, "node_modules/@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "version": "18.19.68", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.68.tgz", + "integrity": "sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw==", + "license": "MIT", "dependencies": { "undici-types": "~5.26.4" } }, + "node_modules/@types/node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, "node_modules/@types/pg": { "version": "8.6.1", "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", @@ -4703,6 +4757,19 @@ "optional": true, "peer": true }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dev": true, + "license": "MIT", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/ajv": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", @@ -4843,6 +4910,13 @@ "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, "node_modules/atomic-sleep": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", @@ -5120,6 +5194,19 @@ "text-hex": "1.0.x" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5306,6 +5393,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", @@ -5825,6 +5922,42 @@ "is-callable": "^1.1.3" } }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data-encoder": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==", + "dev": true, + "license": "MIT" + }, + "node_modules/formdata-node": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", + "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "node-domexception": "1.0.0", + "web-streams-polyfill": "4.0.0-beta.3" + }, + "engines": { + "node": ">= 12.20" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -6222,6 +6355,16 @@ "optional": true, "peer": true }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -7147,6 +7290,26 @@ "node": ">= 0.6" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -7302,6 +7465,33 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/openai": { + "version": "4.76.3", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.76.3.tgz", + "integrity": "sha512-BISkI90m8zT7BAMljK0j00TzOoLvmc7AulPxv6EARa++3+hhIK5G6z4xkITurEaA9bvDhQ09kSNKA3DL+rDMwA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7" + }, + "bin": { + "openai": "bin/cli" + }, + "peerDependencies": { + "zod": "^3.23.8" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -8546,6 +8736,16 @@ "node": ">= 0.8" } }, + "node_modules/web-streams-polyfill": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", + "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -10033,6 +10233,31 @@ "safe-stable-stringify": "^2.5.0" } }, + "@elastic/opentelemetry-instrumentation-openai": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@elastic/opentelemetry-instrumentation-openai/-/opentelemetry-instrumentation-openai-0.4.0.tgz", + "integrity": "sha512-o9lxtoozYqW4yP9WP8DL7HVb1buy5GAE/mCRN5AXDuVWPflENFOfBnbgyS3wI/9TXDk6oIBEtAw/cwJYsiPQaA==", + "requires": { + "@opentelemetry/api-logs": "^0.56.0", + "@opentelemetry/instrumentation": "^0.56.0", + "debug": "^4.3.6" + }, + "dependencies": { + "debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, "@fastify/ajv-compiler": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-4.0.1.tgz", @@ -12204,13 +12429,23 @@ } }, "@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "version": "18.19.68", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.68.tgz", + "integrity": "sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw==", "requires": { "undici-types": "~5.26.4" } }, + "@types/node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==", + "dev": true, + "requires": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, "@types/pg": { "version": "8.6.1", "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", @@ -12365,6 +12600,15 @@ } } }, + "agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dev": true, + "requires": { + "humanize-ms": "^1.2.1" + } + }, "ajv": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", @@ -12465,6 +12709,12 @@ "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, "atomic-sleep": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", @@ -12674,6 +12924,15 @@ "text-hex": "1.0.x" } }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -12809,6 +13068,12 @@ "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", "dev": true }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true + }, "denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", @@ -13225,6 +13490,33 @@ "is-callable": "^1.1.3" } }, + "form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "form-data-encoder": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==", + "dev": true + }, + "formdata-node": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", + "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", + "dev": true, + "requires": { + "node-domexception": "1.0.0", + "web-streams-polyfill": "4.0.0-beta.3" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -13507,6 +13799,15 @@ } } }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "requires": { + "ms": "^2.0.0" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -14174,6 +14475,12 @@ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true + }, "node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -14287,6 +14594,21 @@ "is-wsl": "^2.2.0" } }, + "openai": { + "version": "4.76.3", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.76.3.tgz", + "integrity": "sha512-BISkI90m8zT7BAMljK0j00TzOoLvmc7AulPxv6EARa++3+hhIK5G6z4xkITurEaA9bvDhQ09kSNKA3DL+rDMwA==", + "dev": true, + "requires": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7" + } + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -15215,6 +15537,12 @@ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true }, + "web-streams-polyfill": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", + "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", + "dev": true + }, "webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", diff --git a/packages/opentelemetry-node/package.json b/packages/opentelemetry-node/package.json index 3268f557..e0c5d3dc 100644 --- a/packages/opentelemetry-node/package.json +++ b/packages/opentelemetry-node/package.json @@ -67,6 +67,8 @@ "./package.json": "./package.json" }, "dependencies": { + "@elastic/opentelemetry-instrumentation-openai": "^0.4.0", + "@opentelemetry/api": "^1.3.0", "@opentelemetry/core": "1.27.0", "@opentelemetry/exporter-logs-otlp-grpc": "^0.56.0", "@opentelemetry/exporter-logs-otlp-http": "^0.56.0", @@ -127,7 +129,6 @@ "@grpc/grpc-js": "^1.11.1", "@grpc/proto-loader": "^0.7.13", "@hapi/hapi": "^21.3.10", - "@opentelemetry/api": "^1.3.0", "@types/tape": "^5.6.4", "bunyan": "^1.8.15", "dotenv": "^16.4.5", @@ -136,6 +137,7 @@ "ioredis": "^5.4.1", "module-details-from-path": "^1.0.3", "mongodb": "^6.9.0", + "openai": "^4.76.3", "pg": "^8.13.0", "pino": "^9.4.0", "redis": "^4.7.0", diff --git a/packages/opentelemetry-node/test/OTEL_NODE_ENABLE_DISABLE_INSTRUMENTATIONS.test.js b/packages/opentelemetry-node/test/OTEL_NODE_ENABLE_DISABLE_INSTRUMENTATIONS.test.js index ce302215..e04fb908 100644 --- a/packages/opentelemetry-node/test/OTEL_NODE_ENABLE_DISABLE_INSTRUMENTATIONS.test.js +++ b/packages/opentelemetry-node/test/OTEL_NODE_ENABLE_DISABLE_INSTRUMENTATIONS.test.js @@ -23,7 +23,7 @@ const {runTestFixtures} = require('./testutils'); /** @type {import('./testutils').TestFixture[]} */ const testFixtures = [ { - name: 'basic scenario without values in OTEL_(EN|DIS)ABLE_INSTRUMENTATIONS', + name: 'basic scenario without values in OTEL_(EN|DIS)ABLED_INSTRUMENTATIONS', args: ['./fixtures/use-env.js'], cwd: __dirname, env: { @@ -100,7 +100,7 @@ const testFixtures = [ OTEL_LOG_LEVEL: 'debug', OTEL_NODE_DISABLED_INSTRUMENTATIONS: 'fastify, express , bogus', }, - verbose: true, + // verbose: true, checkResult: (t, err, stdout, stderr) => { t.error(err); const lines = stdout.split('\n'); diff --git a/packages/opentelemetry-node/test/docker-compose.yaml b/packages/opentelemetry-node/test/docker-compose.yaml index 4db5b7df..43462657 100644 --- a/packages/opentelemetry-node/test/docker-compose.yaml +++ b/packages/opentelemetry-node/test/docker-compose.yaml @@ -8,7 +8,7 @@ # npm run test-services:start [services...] # npm run test-services:stop [services...] -name: test-services +name: edot-nodejs-test-services services: redis: @@ -31,6 +31,18 @@ services: timeout: 10s retries: 30 + ollama: + # A light fork of Ollama to float some in-progress contributions related + # to more closely matching OpenAI behavior. + image: ghcr.io/elastic/ollama/ollama:testing + ports: + - "11434:11434" + healthcheck: + test: ["CMD", "ollama", "ls"] + interval: 1s + timeout: 10s + retries: 30 + postgres: # https://github.com/docker-library/docs/blob/master/postgres/README.md#how-to-extend-this-image image: postgres:16 diff --git a/packages/opentelemetry-node/test/fixtures/use-elastic-openai.js b/packages/opentelemetry-node/test/fixtures/use-elastic-openai.js new file mode 100644 index 00000000..9009faae --- /dev/null +++ b/packages/opentelemetry-node/test/fixtures/use-elastic-openai.js @@ -0,0 +1,36 @@ +/* + * 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 --env-file ./test-services.env -r @elastic/opentelemetry-node fixtures/use-elastic-openai.js + +const {OpenAI} = require('openai'); + +async function main() { + const client = new OpenAI(); + const embedding = await client.embeddings.create({ + model: process.env.TEST_GENAI_MODEL, + input: 'Blah blah blah', + encoding_format: 'float', + }); + console.log('Embeddings:'); + console.dir(embedding, {depth: 50}); +} + +main(); diff --git a/packages/opentelemetry-node/test/instr-elastic-openai.test.js b/packages/opentelemetry-node/test/instr-elastic-openai.test.js new file mode 100644 index 00000000..38a3d5b5 --- /dev/null +++ b/packages/opentelemetry-node/test/instr-elastic-openai.test.js @@ -0,0 +1,130 @@ +/* + * 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. + */ + +const http = require('http'); +const test = require('tape'); +const semver = require('semver'); +const {runTestFixtures, assertDeepMatch} = require('./testutils'); + +let skip = process.env.TEST_GENAI_MODEL === undefined; +if (skip) { + console.log( + '# SKIP elastic openai tests: TEST_GENAI_MODEL is not set (load env from test/test-services.env)' + ); +} else { + skip = !semver.satisfies(process.version, '>=18'); + if (skip) { + console.log('# SKIP elastic openai requires node >=18'); + } +} + +/** @type {import('./testutils').TestFixture[]} */ +const testFixtures = [ + { + name: 'use-elastic-openai.js (CommonJS)', + args: ['./fixtures/use-elastic-openai.js'], + cwd: __dirname, + env: { + NODE_OPTIONS: '--require=@elastic/opentelemetry-node', + }, + // verbose: true, + checkTelemetry: (t, col) => { + // Expected a trace like this: + // span 7e8ca8 "embeddings all-minilm:22m" (26.4ms, SPAN_KIND_CLIENT, GenAI openai) + // +9ms `- span 39fc32 "POST" (16.7ms, SPAN_KIND_CLIENT, POST http://127.0.0.1:11434/v1/embeddings -> 200) + const spans = col.sortedSpans; + assertDeepMatch( + t, + spans, + [ + { + name: `embeddings ${process.env.TEST_GENAI_MODEL}`, + kind: 'SPAN_KIND_CLIENT', + attributes: { + 'gen_ai.operation.name': 'embeddings', + 'gen_ai.request.model': + process.env.TEST_GENAI_MODEL, + 'gen_ai.system': 'openai', + }, + events: [], + scope: { + name: '@elastic/opentelemetry-instrumentation-openai', + }, + }, + { + name: 'POST', + parentSpanId: spans[0].spanId, + attributes: { + 'http.target': '/v1/embeddings', + }, + scope: { + name: '@opentelemetry/instrumentation-http', + }, + }, + ], + 'spans' + ); + }, + }, + + // TODO: ESM test, requires `createAddHookMessageChannel` IITM work +]; + +// Basically do this: +// curl -i http://localhost:11434/api/pull -d '{"model": "$TEST_GENAI_MODEL"}' +async function testModelIsPulled() { + return new Promise((resolve, reject) => { + const u = new URL(process.env.OPENAI_BASE_URL); + const req = http.request( + { + hostname: u.hostname, + port: u.port, + path: '/api/pull', + method: 'POST', + }, + (res) => { + // This is lazy error handling. We should watch for the response + // data ending with `{"status":"success"}`. + res.resume(); + res.on('end', () => { + if (res.statusCode !== 200) { + reject( + new Error( + `unexpected status code from Ollama: ${res.statusCode}` + ) + ); + } else { + resolve(); + } + }); + } + ); + req.on('error', reject); + req.write(JSON.stringify({model: process.env.TEST_GENAI_MODEL})); + req.end(); + }); +} + +test('elastic openai instrumentation', {skip}, async (suite) => { + suite.comment(`pulling test GenAI model (${process.env.TEST_GENAI_MODEL})`); + await testModelIsPulled(); + + runTestFixtures(suite, testFixtures); + suite.end(); +}); diff --git a/packages/opentelemetry-node/test/instr-mongodb.test.js b/packages/opentelemetry-node/test/instr-mongodb.test.js index 0b0940a0..17d4e138 100644 --- a/packages/opentelemetry-node/test/instr-mongodb.test.js +++ b/packages/opentelemetry-node/test/instr-mongodb.test.js @@ -25,7 +25,7 @@ const {filterOutDnsNetSpans, runTestFixtures} = require('./testutils'); let skip = process.env.MONGODB_HOST === undefined; if (skip) { console.log( - '# SKIP mongodb tests: MONGODB_HOST is not set (try with `MONGODB_HOST=localhost:27017`)' + '# SKIP mongodb tests: MONGODB_HOST is not set (try with `MONGODB_HOST=localhost`)' ); } diff --git a/packages/opentelemetry-node/test/test-services.env b/packages/opentelemetry-node/test/test-services.env index 5cba7050..9665b82a 100644 --- a/packages/opentelemetry-node/test/test-services.env +++ b/packages/opentelemetry-node/test/test-services.env @@ -1,4 +1,9 @@ REDIS_HOST=localhost PGHOST=localhost MONGODB_HOST=localhost -MSSQL_HOST=localhost \ No newline at end of file +MSSQL_HOST=localhost + +OPENAI_BASE_URL=http://127.0.0.1:11434/v1 +OPENAI_API_KEY=notused +# A small a model as possible for lightweight test runs. +TEST_GENAI_MODEL=all-minilm:22m diff --git a/packages/opentelemetry-node/test/testutils.js b/packages/opentelemetry-node/test/testutils.js index 575eaf2e..57b82e8e 100644 --- a/packages/opentelemetry-node/test/testutils.js +++ b/packages/opentelemetry-node/test/testutils.js @@ -34,6 +34,51 @@ const { normalizeMetrics, } = require('@elastic/mockotlpserver'); +// isIdentifier based on https://github.com/sindresorhus/identifier-regex +const isIdentifier = /^[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}]*$/u; + +/** + * Assert the given object matches given expectations. + * + * The fields in `expected` are compared against the equivalent field in `actual`: + * - if `expected` is a RegExp, comparison is via Tape's `t.match()` + * - if `actual` and `expected` are both arrays, a deep comparison is done, + * - if `actual` and `expected` are both objects, a deep comparison is done, + * - if `expected` is a function, it is passed the actual value and the + * return value is asserted with `t.ok()` + * - otherwise comparison is via `t.equal()` + * + * assertDeepMatch(t, {foo: 'bar'}, {foo: /^b/}); + * assertDeepMatch(t, process.versions, {node: /^18/, napi: '9'}); + */ +function assertDeepMatch(t, actual, expected, msgPrefix = 'obj') { + if (expected instanceof RegExp) { + t.match(actual, expected, msgPrefix); + } else if (typeof expected === 'function') { + t.ok(expected(actual), msgPrefix); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + t.equal(actual.length, expected.length, msgPrefix + '.length'); + for (let i = 0; i < Math.min(actual.length, expected.length); i++) { + assertDeepMatch(t, actual[i], expected[i], msgPrefix + `[${i}]`); + } + } else if ( + actual != null && + typeof actual === 'object' && + expected != null && + typeof expected === 'object' + ) { + for (let k in expected) { + const a = actual[k]; + const e = expected[k]; + const kPrefix = + msgPrefix + (isIdentifier.test(k) ? `.${k}` : `['${k}']`); + assertDeepMatch(t, a, e, kPrefix); + } + } else { + t.equal(actual, expected, msgPrefix); + } +} + /** * Filter out instr-dns and instr-net spans for testing. * Eventually it would be preferable to have each test run with instr-dns @@ -639,6 +684,7 @@ function runTestFixtures(suite, testFixtures) { } module.exports = { + assertDeepMatch, filterOutDnsNetSpans, dottedLookup, findObjInArray, diff --git a/packages/opentelemetry-node/types/instrumentations.d.ts b/packages/opentelemetry-node/types/instrumentations.d.ts index 2df1d694..2aa54c93 100644 --- a/packages/opentelemetry-node/types/instrumentations.d.ts +++ b/packages/opentelemetry-node/types/instrumentations.d.ts @@ -1,6 +1,7 @@ export type Instrumentation = import('@opentelemetry/instrumentation').Instrumentation; export type InstrumentationFactory = () => Instrumentation; export type InstrumentaionsMap = { + "@elastic/opentelemetry-instrumentation-openai": import('@elastic/opentelemetry-instrumentation-openai').OpenAIInstrumentationConfig | InstrumentationFactory; "@opentelemetry/instrumentation-aws-sdk": import('@opentelemetry/instrumentation-aws-sdk').AwsSdkInstrumentationConfig | InstrumentationFactory; "@opentelemetry/instrumentation-bunyan": import('@opentelemetry/instrumentation-bunyan').BunyanInstrumentationConfig | InstrumentationFactory; "@opentelemetry/instrumentation-connect": import('@opentelemetry/instrumentation').InstrumentationConfig | InstrumentationFactory; diff --git a/packages/opentelemetry-node/types/metrics/host.d.ts b/packages/opentelemetry-node/types/metrics/host.d.ts index a93f07d7..8ccb6eda 100644 --- a/packages/opentelemetry-node/types/metrics/host.d.ts +++ b/packages/opentelemetry-node/types/metrics/host.d.ts @@ -1,6 +1,6 @@ -/** @type {metrics.View[]} */ -export const HOST_METRICS_VIEWS: metrics.View[]; +/** @type {metricsSdk.View[]} */ +export const HOST_METRICS_VIEWS: metricsSdk.View[]; export function enableHostMetrics(): void; -import { metrics } from "@opentelemetry/sdk-node"; -declare const View: typeof metrics.View; +import { metrics as metricsSdk } from "@opentelemetry/sdk-node"; +declare const View: typeof metricsSdk.View; export {}; diff --git a/scripts/gen-notice.sh b/scripts/gen-notice.sh index 5b1d3095..cb173bc8 100755 --- a/scripts/gen-notice.sh +++ b/scripts/gen-notice.sh @@ -84,6 +84,9 @@ npm ls --omit=dev --all --parseable \ "pg-types": "license.pg-types.txt", "undici-types": "license.undici.txt", "tr46": "license.MIT.txt", + // Temporary manual license path for v0.4.0 of @elastic/opentelemetry-instrumentation-openai + // TODO: remove this when the next version is published and updated in EDOT Node.js. + "@elastic/opentelemetry-instrumentation-openai": "../packages/instrumentation-openai/LICENSE", } const allowNoLicFile = [ "binary-search" // CC is a public domain dedication, no need for license text.