diff --git a/.changeset/shiny-mails-exercise.md b/.changeset/shiny-mails-exercise.md new file mode 100644 index 00000000..3a5cdf5c --- /dev/null +++ b/.changeset/shiny-mails-exercise.md @@ -0,0 +1,5 @@ +--- +'@hyperdx/node-opentelemetry': patch +--- + +feat: support gRPC protocol diff --git a/.changeset/stupid-pugs-type.md b/.changeset/stupid-pugs-type.md new file mode 100644 index 00000000..27f9347f --- /dev/null +++ b/.changeset/stupid-pugs-type.md @@ -0,0 +1,5 @@ +--- +'@hyperdx/node-opentelemetry': patch +--- + +fix: pino trace linking issue diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..b11ebfe9 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,14 @@ +node_modules +dist +.nx +.git +.github +*.md +.vscode +.idea +*.log +coverage +.eslintcache +smoke-tests/collector/data.json +smoke-tests/collector/data-results +smoke-tests/report.* diff --git a/.github/workflows/smoke.yaml b/.github/workflows/smoke.yaml index 3f00dd6e..767df49c 100644 --- a/.github/workflows/smoke.yaml +++ b/.github/workflows/smoke.yaml @@ -15,8 +15,10 @@ jobs: - name: Setup BATS uses: mig4/setup-bats@v1 with: - bats-version: 1.10.0 + bats-version: 1.12.0 - name: Check out repository uses: actions/checkout@v4 + - name: Build smoke test images + run: make build-smoke-images - name: Run smoke tests run: make smoke-sdk diff --git a/Makefile b/Makefile index 1b4b2995..f4eb2903 100644 --- a/Makefile +++ b/Makefile @@ -6,51 +6,46 @@ clean-smoke-tests: #: cleans up TS build, smoke test output, and example app detritus squeaky-clean: clean clean-smoke-tests - rm -rf ./examples/dist - rm -rf ./examples/node_modules - rm -rf ./examples/hello-node/dist - rm -rf ./examples/hello-node/node_modules - rm -rf ./examples/hello-node-express/dist - rm -rf ./examples/hello-node-express/node_modules - rm -rf ./examples/hello-node-express-ts/dist - rm -rf ./examples/hello-node-express-ts/node_modules + rm -rf ./smoke-tests/hello-node-express-ts/dist + rm -rf ./smoke-tests/hello-node-express-ts/node_modules smoke-tests/collector/data.json: @echo "" @echo "+++ Zhuzhing smoke test's Collector data.json" @touch $@ && chmod o+w $@ -smoke-sdk-grpc: smoke-tests/collector/data.json +#: build Docker images for smoke tests (with caching) +build-smoke-images: @echo "" - @echo "+++ Running gRPC smoke tests." + @echo "+++ Building smoke test Docker images (cached)" @echo "" - cd smoke-tests && bats ./smoke-sdk-grpc.bats --report-formatter junit --output ./ + cd smoke-tests && docker compose build -smoke-sdk-grpc-ts: smoke-tests/collector/data.json +smoke-sdk-grpc-ts: build-smoke-images smoke-tests/collector/data.json @echo "" @echo "+++ Running gRPC smoke tests for TypeScript." @echo "" - cd smoke-tests && bats ./smoke-sdk-grpc-ts.bats --report-formatter junit --output ./ + cd smoke-tests && bats ./smoke-sdk-grpc-ts.bats --report-formatter junit --output ./ --verbose-run -smoke-sdk-http: smoke-tests/collector/data.json +smoke-sdk-http-ts: build-smoke-images smoke-tests/collector/data.json @echo "" - @echo "+++ Running HTTP smoke tests." + @echo "+++ Running HTTP smoke tests for TypeScript." @echo "" - cd smoke-tests && bats ./smoke-sdk-http.bats --report-formatter junit --output ./ + cd smoke-tests && bats ./smoke-sdk-http-ts.bats --report-formatter junit --output ./ --verbose-run -smoke-sdk-http-ts: smoke-tests/collector/data.json +smoke-sdk-http-ts-programmaticImports: build-smoke-images smoke-tests/collector/data.json @echo "" - @echo "+++ Running HTTP smoke tests for TypeScript." + @echo "+++ Running HTTP programmatic imports smoke tests for TypeScript." @echo "" - cd smoke-tests && bats ./smoke-sdk-http-ts.bats --report-formatter junit --output ./ + cd smoke-tests && bats ./smoke-sdk-http-ts-programmaticImports.bats --report-formatter junit --output ./ --verbose-run -smoke-sdk: smoke-sdk-http smoke-sdk-http-ts +smoke-sdk: smoke-sdk-http-ts smoke-sdk-grpc-ts smoke: docker_compose_present @echo "" @echo "+++ Smoking all the tests." @echo "" - cd smoke-tests && bats . --report-formatter junit --output ./ + cd smoke-tests && bats . --report-formatter junit --output ./ --verbose-run unsmoke: docker_compose_present @echo "" @@ -61,7 +56,7 @@ unsmoke: docker_compose_present #: use this for local smoke testing resmoke: unsmoke smoke -.PHONY: clean-smoke-tests example smoke unsmoke resmoke smoke-sdk-grpc smoke-sdk-http smoke-sdk +.PHONY: clean-smoke-tests build-smoke-images example smoke unsmoke resmoke smoke-sdk-grpc-ts smoke-sdk-http-ts smoke-sdk-http-ts-programmaticImports smoke-sdk .PHONY: docker_compose_present docker_compose_present: diff --git a/examples/hello-node-express-ts/instrumentation.ts b/examples/hello-node-express-ts/instrumentation.ts deleted file mode 100644 index ca90c31d..00000000 --- a/examples/hello-node-express-ts/instrumentation.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { initSDK } from '@hyperdx/node-opentelemetry'; - -initSDK({ - // advancedNetworkCapture: true, - // betaMode: true, - // consoleCapture: true, -}); diff --git a/examples/hello-node-express/Dockerfile b/examples/hello-node-express/Dockerfile deleted file mode 100644 index 86996557..00000000 --- a/examples/hello-node-express/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM node:18 - -# Create app directory -WORKDIR /usr/src/app - -# copy everything from root directory (must use smoke-tests/docker-compose) -COPY . ./ - -# Bundle app source -COPY . . - -# example app listens on port 3000 -EXPOSE 3000 - -# symlink hyperdx sdk dependency -RUN cd ./examples/hello-node-express/ && npm run setup - -# run example express app -CMD [ "node", "./examples/hello-node-express/index.js" ] diff --git a/examples/hello-node-express/README.md b/examples/hello-node-express/README.md deleted file mode 100644 index d0de9863..00000000 --- a/examples/hello-node-express/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# Hello World Express Example - -## Overview - -This example illustrates a simple hello world using a local dependency and express. - -## Usage - -### Install and setup - -```bash -npm run setup -``` - -### Running the main application - -```bash -HYPERDX_API_KEY={apikey} OTEL_SERVICE_NAME="hello-node-express" npm start -``` - -Alternatively, to export telemetry using `gRPC` instead of `http/protobuf`: - -```bash -HYPERDX_API_KEY={apikey} OTEL_SERVICE_NAME="hello-node-express" OTEL_EXPORTER_OTLP_PROTOCOL=grpc npm start -``` - -You can now curl the app: - -```bash -curl localhost:3000 -Hello, World! -``` diff --git a/examples/hello-node-express/index.js b/examples/hello-node-express/index.js deleted file mode 100644 index 0b0f3ea0..00000000 --- a/examples/hello-node-express/index.js +++ /dev/null @@ -1,52 +0,0 @@ -const { initSDK } = require('@hyperdx/node-opentelemetry'); -const { context, metrics, propagation, trace } = require('@opentelemetry/api'); - -initSDK({ - // advancedNetworkCapture: true, - // betaMode: true, - // consoleCapture: true, -}); - -const express = require('express'); -const app = express(); -const hostname = '0.0.0.0'; -const port = 3000; - -app.get('/', (req, res) => { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/plain'); - const sayHello = () => 'Hello world!'; - const tracer = trace.getTracer('hello-world-tracer'); - const meter = metrics.getMeter('hello-world-meter'); - const counter = meter.createCounter('sheep'); - counter.add(1); - // new context based on current, with key/values added to baggage - const ctx = propagation.setBaggage( - context.active(), - propagation.createBaggage({ - for_the_children: { value: 'another important value' }, - }), - ); - // within the new context, do some "work" - context.with(ctx, () => { - tracer.startActiveSpan('sleep', (span) => { - console.log('saying hello to the world'); - span.setAttribute('message', 'hello-world'); - span.setAttribute('delay_ms', 100); - sleepy().then(() => console.log('sleeping a bit!')); - span.end(); - }); - }); - sayHello(); - res.end('Hello, World!\n'); -}); - -async function sleepy() { - await setTimeout(() => { - console.log('awake now!'); - }, 100); -} - -app.listen(port, hostname, () => { - console.log(`Now listening on: http://${hostname}:${port}/`); -}); diff --git a/examples/hello-node-express/package.json b/examples/hello-node-express/package.json deleted file mode 100644 index f6bb5bad..00000000 --- a/examples/hello-node-express/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "hello-node-express", - "version": "0.0.1", - "description": "HyperDX OpenTelemetry Distro for JavaScript", - "author": "HyperDX (https://www.hyperdx.io/)", - "license": "Apache-2.0", - "scripts": { - "setup": "yarn install && cd ../.. && yarn install && yarn ci:build --exclude='@hyperdx/deno' && cd ./packages/node-opentelemetry && yarn link && cd ../../examples/hello-node-express && yarn link @hyperdx/node-opentelemetry", - "start": "node ./index.js" - }, - "dependencies": { - "@opentelemetry/api": "^1.7.0", - "express": "^4.19.2" - } -} diff --git a/examples/hello-node-express/yarn.lock b/examples/hello-node-express/yarn.lock deleted file mode 100644 index 722682ef..00000000 --- a/examples/hello-node-express/yarn.lock +++ /dev/null @@ -1,468 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@opentelemetry/api@^1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.7.0.tgz#b139c81999c23e3c8d3c0a7234480e945920fc40" - integrity sha512-AdY5wvN0P2vXBi3b29hxZgSFvdhdxPB9+f0B6s//P9Q8nibRWeA3cHm8UmLpio9ABigkVHJ5NMPk+Mz8VCCyrw== - -accepts@~1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== - -body-parser@1.20.2: - version "1.20.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" - integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== - dependencies: - bytes "3.1.2" - content-type "~1.0.5" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.11.0" - raw-body "2.5.2" - type-is "~1.6.18" - unpipe "1.0.0" - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -call-bind@^1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - set-function-length "^1.2.1" - -content-disposition@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== - dependencies: - safe-buffer "5.2.1" - -content-type@~1.0.4, content-type@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" - integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== - -cookie@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" - integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== - -debug@2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -define-data-property@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - gopd "^1.0.1" - -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -destroy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== - -es-define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== - dependencies: - get-intrinsic "^1.2.4" - -es-errors@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== - -express@^4.19.2: - version "4.19.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" - integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== - dependencies: - accepts "~1.3.8" - array-flatten "1.1.1" - body-parser "1.20.2" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.6.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "2.0.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.2.0" - fresh "0.5.2" - http-errors "2.0.0" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "2.4.1" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.11.0" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" - setprototypeof "1.2.0" - statuses "2.0.1" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "2.4.1" - parseurl "~1.3.3" - statuses "2.0.1" - unpipe "~1.0.0" - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -get-intrinsic@^1.1.3, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== - dependencies: - es-errors "^1.3.0" - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -has-property-descriptors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== - dependencies: - es-define-property "^1.0.0" - -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - -has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -hasown@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.1.tgz#26f48f039de2c0f8d3356c223fb8d50253519faa" - integrity sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA== - dependencies: - function-bind "^1.1.2" - -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -inherits@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@~2.1.24, mime-types@~2.1.34: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -object-inspect@^1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== - -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== - -proxy-addr@~2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" - -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - -range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" - integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - -safe-buffer@5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== - dependencies: - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "2.0.0" - mime "1.6.0" - ms "2.1.3" - on-finished "2.4.1" - range-parser "~1.2.1" - statuses "2.0.1" - -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.18.0" - -set-function-length@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.1.tgz#47cc5945f2c771e2cf261c6737cf9684a2a5e425" - integrity sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g== - dependencies: - define-data-property "^1.1.2" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.3" - gopd "^1.0.1" - has-property-descriptors "^1.0.1" - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -side-channel@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.5.tgz#9a84546599b48909fb6af1211708d23b1946221b" - integrity sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - object-inspect "^1.13.1" - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== diff --git a/examples/hello-node/.dockerignore b/examples/hello-node/.dockerignore deleted file mode 100644 index 93f13619..00000000 --- a/examples/hello-node/.dockerignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -npm-debug.log diff --git a/examples/hello-node/Dockerfile b/examples/hello-node/Dockerfile deleted file mode 100644 index a82c3045..00000000 --- a/examples/hello-node/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM node:18 - -# Create app directory -WORKDIR /usr/src/app -# copy everything from root directory (using docker-compose) -COPY . ./ - -# If you are building your code for production -# RUN npm ci --only=production - -# Bundle app source -COPY . . - -EXPOSE 3000 - -# symlink hyperdx sdk dependency -RUN cd ./examples/hello-node/ && npm run setup - -# run example script from root package.json -CMD [ "npm", "run", "example-node" ] diff --git a/examples/hello-node/index.js b/examples/hello-node/index.js deleted file mode 100644 index 47713d22..00000000 --- a/examples/hello-node/index.js +++ /dev/null @@ -1,32 +0,0 @@ -const { initSDK } = require('@hyperdx/node-opentelemetry'); -const { trace } = require('@opentelemetry/api'); - -// uses HYPERDX_API_KEY and OTEL_SERVICE_NAME environment variables -// enable debug output with env var DEBUG=true -initSDK({ - // advancedNetworkCapture: true, - // betaMode: true, - // consoleCapture: true, -}); - -const http = require('node:http'); -const hostname = '0.0.0.0'; -const port = 3000; - -const server = http.createServer((req, res) => { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/plain'); - const sayHello = () => 'Hello world!'; - const tracer = trace.getTracer('hello-world-tracer'); - tracer.startActiveSpan('main', (span) => { - console.log('saying hello to the world'); - span.setAttribute('message', 'hello-world'); - span.end(); - }); - sayHello(); - res.end('Hello, World!\n'); -}); - -server.listen(port, hostname, () => { - console.log(`Server running at http://${hostname}:${port}/`); -}); diff --git a/examples/hello-node/package.json b/examples/hello-node/package.json deleted file mode 100644 index 3766fede..00000000 --- a/examples/hello-node/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "hello-node", - "version": "0.0.1", - "description": "HyperDX OpenTelemetry Distro for JavaScript", - "author": "HyperDX (https://www.hyperdx.io/)", - "license": "Apache-2.0", - "scripts": { - "setup": "yarn install && cd ../.. && yarn install && yarn ci:build --exclude='@hyperdx/deno' && npx nx build @hyperdx/node-opentelemetry && cd ./packages/node-opentelemetry && yarn link && cd ../../examples/hello-node && yarn link @hyperdx/node-opentelemetry", - "start": "node ./index.js" - }, - "dependencies": { - "@opentelemetry/api": "^1.7.0", - "@opentelemetry/instrumentation-http": "~0.46.0" - } -} diff --git a/examples/hello-node/readme.md b/examples/hello-node/readme.md deleted file mode 100644 index 0269af85..00000000 --- a/examples/hello-node/readme.md +++ /dev/null @@ -1,25 +0,0 @@ -# Hello World example - -## Overview - -This example illustrates a simple hello world using a local dependency. The eslint is currently disabled because this directory is ignored - please enable it for future development. - -## Usage - -### Install and setup - -```bash -npm run setup -``` - -### Running the main application - -```bash -HYPERDX_API_KEY={apikey} OTEL_SERVICE_NAME="hello-node" npm start -``` - -Alternatively, to export telemetry using `gRPC` instead of `http/protobuf`: - -```bash -HYPERDX_API_KEY={apikey} OTEL_SERVICE_NAME="hello-node" OTEL_EXPORTER_OTLP_PROTOCOL=grpc npm start -``` diff --git a/examples/hello-node/yarn.lock b/examples/hello-node/yarn.lock deleted file mode 100644 index 62104272..00000000 --- a/examples/hello-node/yarn.lock +++ /dev/null @@ -1,159 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@opentelemetry/api@^1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.7.0.tgz#b139c81999c23e3c8d3c0a7234480e945920fc40" - integrity sha512-AdY5wvN0P2vXBi3b29hxZgSFvdhdxPB9+f0B6s//P9Q8nibRWeA3cHm8UmLpio9ABigkVHJ5NMPk+Mz8VCCyrw== - -"@opentelemetry/core@1.19.0": - version "1.19.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.19.0.tgz#6563bb65465bf232d8435553b9a122d9351c0fbb" - integrity sha512-w42AukJh3TP8R0IZZOVJVM/kMWu8g+lm4LzT70WtuKqhwq7KVhcDzZZuZinWZa6TtQCl7Smt2wolEYzpHabOgw== - dependencies: - "@opentelemetry/semantic-conventions" "1.19.0" - -"@opentelemetry/instrumentation-http@~0.46.0": - version "0.46.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-http/-/instrumentation-http-0.46.0.tgz#c567d3ed69935153eaa018b989bfc167249bdf4f" - integrity sha512-t5cxgqfV9AcxVP00/OL1ggkOSZM57VXDpvlWaOidYyyfLKcUJ9e2fGbNwoVsGFboRDeH0iFo7gLA3EEvX13wCA== - dependencies: - "@opentelemetry/core" "1.19.0" - "@opentelemetry/instrumentation" "0.46.0" - "@opentelemetry/semantic-conventions" "1.19.0" - semver "^7.5.2" - -"@opentelemetry/instrumentation@0.46.0": - version "0.46.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.46.0.tgz#a8a252306f82e2eace489312798592a14eb9830e" - integrity sha512-a9TijXZZbk0vI5TGLZl+0kxyFfrXHhX6Svtz7Pp2/VBlCSKrazuULEyoJQrOknJyFWNMEmbbJgOciHCCpQcisw== - dependencies: - "@types/shimmer" "^1.0.2" - import-in-the-middle "1.7.1" - require-in-the-middle "^7.1.1" - semver "^7.5.2" - shimmer "^1.2.1" - -"@opentelemetry/semantic-conventions@1.19.0": - version "1.19.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.19.0.tgz#0c17f80b45de1c8778dfdf17acb1e9d4c4aa4ba8" - integrity sha512-14jRpC8f5c0gPSwoZ7SbEJni1PqI+AhAE8m1bMz6v+RPM4OlP1PT2UHBJj5Qh/ALLPjhVU/aZUK3YyjTUqqQVg== - -"@types/shimmer@^1.0.2": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.0.5.tgz#491d8984d4510e550bfeb02d518791d7f59d2b88" - integrity sha512-9Hp0ObzwwO57DpLFF0InUjUm/II8GmKAvzbefxQTihCb7KI6yc9yzf0nLc4mVdby5N4DRCgQM2wCup9KTieeww== - -acorn-import-assertions@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" - integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== - -acorn@^8.8.2: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== - -cjs-module-lexer@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" - integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== - -debug@^4.1.1: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -hasown@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.1.tgz#26f48f039de2c0f8d3356c223fb8d50253519faa" - integrity sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA== - dependencies: - function-bind "^1.1.2" - -import-in-the-middle@1.7.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.7.1.tgz#3e111ff79c639d0bde459bd7ba29dd9fdf357364" - integrity sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg== - dependencies: - acorn "^8.8.2" - acorn-import-assertions "^1.9.0" - cjs-module-lexer "^1.2.2" - module-details-from-path "^1.0.3" - -is-core-module@^2.13.0: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== - dependencies: - hasown "^2.0.0" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -module-details-from-path@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" - integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -require-in-the-middle@^7.1.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz#b539de8f00955444dc8aed95e17c69b0a4f10fcf" - integrity sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw== - dependencies: - debug "^4.1.1" - module-details-from-path "^1.0.3" - resolve "^1.22.1" - -resolve@^1.22.1: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -semver@^7.5.2: - version "7.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" - integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== - dependencies: - lru-cache "^6.0.0" - -shimmer@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" - integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== diff --git a/packages/node-opentelemetry/package.json b/packages/node-opentelemetry/package.json index f62947bb..e7214829 100644 --- a/packages/node-opentelemetry/package.json +++ b/packages/node-opentelemetry/package.json @@ -38,8 +38,11 @@ "@opentelemetry/api-logs": "^0.57.2", "@opentelemetry/auto-instrumentations-node": "^0.56.1", "@opentelemetry/core": "^1.30.1", + "@opentelemetry/exporter-logs-otlp-grpc": "^0.57.2", "@opentelemetry/exporter-logs-otlp-http": "^0.57.2", + "@opentelemetry/exporter-metrics-otlp-grpc": "^0.57.2", "@opentelemetry/exporter-metrics-otlp-proto": "^0.57.2", + "@opentelemetry/exporter-trace-otlp-grpc": "^0.57.2", "@opentelemetry/exporter-trace-otlp-proto": "^0.57.2", "@opentelemetry/instrumentation": "^0.57.2", "@opentelemetry/instrumentation-http": "^0.57.2", diff --git a/packages/node-opentelemetry/src/constants.ts b/packages/node-opentelemetry/src/constants.ts index 585ae14b..d4ed8de3 100644 --- a/packages/node-opentelemetry/src/constants.ts +++ b/packages/node-opentelemetry/src/constants.ts @@ -20,7 +20,9 @@ export const DEFAULT_OTEL_TRACES_EXPORTER = otelEnv.OTEL_TRACES_EXPORTER; export const DEFAULT_OTEL_TRACES_EXPORTER_URL = otelEnv.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ?? (otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT - ? `${otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/traces` + ? otelEnv.OTEL_EXPORTER_OTLP_PROTOCOL === 'grpc' + ? otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT + : `${otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/traces` : 'https://in-otel.hyperdx.io/v1/traces'); export const DEFAULT_OTEL_TRACES_SAMPLER = otelEnv.OTEL_TRACES_SAMPLER ?? 'parentbased_always_on'; @@ -34,13 +36,17 @@ export const DEFAULT_OTEL_LOGS_EXPORTER = otelEnv.OTEL_LOGS_EXPORTER; export const DEFAULT_OTEL_LOGS_EXPORTER_URL = otelEnv.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT ?? (otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT - ? `${otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/logs` + ? otelEnv.OTEL_EXPORTER_OTLP_PROTOCOL === 'grpc' + ? otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT + : `${otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/logs` : 'https://in-otel.hyperdx.io/v1/logs'); export const DEFAULT_OTEL_METRICS_EXPORTER = env.OTEL_METRICS_EXPORTER; // not exist yet export const DEFAULT_OTEL_METRICS_EXPORTER_URL = otelEnv.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT ?? (otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT - ? `${otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/metrics` + ? otelEnv.OTEL_EXPORTER_OTLP_PROTOCOL === 'grpc' + ? otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT + : `${otelEnv.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/metrics` : 'https://in-otel.hyperdx.io/v1/metrics'); export const DEFAULT_OTEL_METRIC_EXPORT_INTERVAL = env.OTEL_METRIC_EXPORT_INTERVAL diff --git a/packages/node-opentelemetry/src/metrics.ts b/packages/node-opentelemetry/src/metrics.ts index b9432f85..4bc6e5fa 100644 --- a/packages/node-opentelemetry/src/metrics.ts +++ b/packages/node-opentelemetry/src/metrics.ts @@ -1,4 +1,5 @@ -import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-proto'; +import { OTLPMetricExporter as OTLPMetricExporterGRPC } from '@opentelemetry/exporter-metrics-otlp-grpc'; +import { OTLPMetricExporter as OTLPMetricExporterHTTP } from '@opentelemetry/exporter-metrics-otlp-proto'; import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'; import { @@ -7,11 +8,18 @@ import { DEFAULT_OTEL_METRICS_EXPORTER_URL, } from './constants'; +const env = process.env; + export const getHyperDXMetricReader = () => new PeriodicExportingMetricReader({ - exporter: new OTLPMetricExporter({ - url: DEFAULT_OTEL_METRICS_EXPORTER_URL, - }), + exporter: + env.OTEL_EXPORTER_OTLP_PROTOCOL === 'grpc' + ? new OTLPMetricExporterGRPC({ + url: DEFAULT_OTEL_METRICS_EXPORTER_URL, + }) + : new OTLPMetricExporterHTTP({ + url: DEFAULT_OTEL_METRICS_EXPORTER_URL, + }), exportIntervalMillis: DEFAULT_OTEL_METRIC_EXPORT_INTERVAL, exportTimeoutMillis: DEFAULT_OTEL_METRIC_EXPORT_TIMEOUT, }); diff --git a/packages/node-opentelemetry/src/otel-logger/index.ts b/packages/node-opentelemetry/src/otel-logger/index.ts index 1c82d141..d3702c37 100644 --- a/packages/node-opentelemetry/src/otel-logger/index.ts +++ b/packages/node-opentelemetry/src/otel-logger/index.ts @@ -1,7 +1,13 @@ -import { Attributes, diag } from '@opentelemetry/api'; -import { Logger as OtelLogger, logs } from '@opentelemetry/api-logs'; +import { + Attributes, + context as apiContext, + diag, + trace, +} from '@opentelemetry/api'; +import { Logger as OtelLogger, LogRecord, logs } from '@opentelemetry/api-logs'; import { getEnvWithoutDefaults } from '@opentelemetry/core'; -import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'; +import { OTLPLogExporter as OTLPLogExporterGRPC } from '@opentelemetry/exporter-logs-otlp-grpc'; +import { OTLPLogExporter as OTLPLogExporterHTTP } from '@opentelemetry/exporter-logs-otlp-http'; import { detectResourcesSync, envDetectorSync, @@ -29,6 +35,47 @@ import { const LOG_PREFIX = `โš ๏ธ [LOGGER]`; +/** + * Load context from attributes and set it to logRecord.context + * + * @param {LogRecord} logRecord + * @returns {LogRecord} + */ +function loadContext(logRecord: LogRecord): LogRecord { + let context = apiContext.active(); + let attributes = logRecord.attributes; + + if (typeof attributes !== 'undefined') { + const { trace_id, span_id, trace_flags, ...otherAttributes } = + logRecord.attributes as Attributes & { + trace_id?: string; + span_id?: string; + trace_flags?: number; + }; + + if ( + typeof trace_id !== 'undefined' && + typeof span_id !== 'undefined' && + typeof trace_flags !== 'undefined' + ) { + context = trace.setSpanContext(context, { + traceId: trace_id, + spanId: span_id, + traceFlags: trace_flags, + isRemote: true, + }); + } + + attributes = otherAttributes; + } + + return { + ...logRecord, + attributes, + context, + }; +} + export type LoggerOptions = { baseUrl?: string; bufferSize?: number; @@ -86,10 +133,16 @@ export class Logger { diag.warn(`${LOG_PREFIX} Sending logs to ${this._url}`); - const exporter = new OTLPLogExporter({ - url: this._url, - ...(headers && { headers }), - }); + const exporter = + process.env.OTEL_EXPORTER_OTLP_PROTOCOL === 'grpc' + ? new OTLPLogExporterGRPC({ + url: this._url, + ...(headers && { headers }), + }) + : new OTLPLogExporterHTTP({ + url: this._url, + ...(headers && { headers }), + }); this.processor = this.isDisabled() ? new NoopLogRecordProcessor() : new BatchLogRecordProcessor(exporter, { @@ -156,14 +209,16 @@ export class Logger { } postMessage(level: string, body: string, attributes: Attributes = {}): void { - this.logger.emit({ - // TODO: should map to otel severity number - severityNumber: 0, - // TODO: set up the mapping between different downstream log levels - severityText: level, - body, - attributes, - timestamp: this.parseTimestamp(attributes), - }); + this.logger.emit( + loadContext({ + // TODO: should map to otel severity number + severityNumber: 0, + // TODO: set up the mapping between different downstream log levels + severityText: level, + body, + attributes, + timestamp: this.parseTimestamp(attributes), + }), + ); } } diff --git a/packages/node-opentelemetry/src/otel.ts b/packages/node-opentelemetry/src/otel.ts index 5c3b0970..6b29c23c 100644 --- a/packages/node-opentelemetry/src/otel.ts +++ b/packages/node-opentelemetry/src/otel.ts @@ -5,7 +5,8 @@ import { getNodeAutoInstrumentations, InstrumentationConfigMap, } from '@opentelemetry/auto-instrumentations-node'; -import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto'; +import { OTLPTraceExporter as OTLPTraceExporterGRPC } from '@opentelemetry/exporter-trace-otlp-grpc'; +import { OTLPTraceExporter as OTLPTraceExporterHTTP } from '@opentelemetry/exporter-trace-otlp-proto'; import { InstrumentationBase, InstrumentationModuleDefinition, @@ -343,10 +344,16 @@ export const initSDK = (config: SDKConfig) => { ? [] : [ new HyperDXSpanProcessor({ - exporter: new OTLPTraceExporter({ - timeoutMillis: DEFAULT_OTEL_EXPORTER_OTLP_TRACES_TIMEOUT, - url: DEFAULT_OTEL_TRACES_EXPORTER_URL, - }), + exporter: + env.OTEL_EXPORTER_OTLP_PROTOCOL === 'grpc' + ? new OTLPTraceExporterGRPC({ + timeoutMillis: DEFAULT_OTEL_EXPORTER_OTLP_TRACES_TIMEOUT, + url: DEFAULT_OTEL_TRACES_EXPORTER_URL, + }) + : new OTLPTraceExporterHTTP({ + timeoutMillis: DEFAULT_OTEL_EXPORTER_OTLP_TRACES_TIMEOUT, + url: DEFAULT_OTEL_TRACES_EXPORTER_URL, + }), enableHDXGlobalContext: defaultBetaMode, contextManager, }), diff --git a/smoke-tests/collector/otel-collector-config.yaml b/smoke-tests/collector/otel-collector-config.yaml index 7d99fd32..16d9fed8 100644 --- a/smoke-tests/collector/otel-collector-config.yaml +++ b/smoke-tests/collector/otel-collector-config.yaml @@ -2,7 +2,9 @@ receivers: otlp: protocols: grpc: + endpoint: 0.0.0.0:4317 http: + endpoint: 0.0.0.0:4318 processors: batch: @@ -10,21 +12,20 @@ processors: exporters: file: path: /var/lib/data.json - logging: - loglevel: debug + debug: + verbosity: detailed service: pipelines: traces: receivers: [otlp] processors: [batch] - exporters: [file, logging] + exporters: [file, debug] metrics: receivers: [otlp] processors: [batch] - exporters: [file, logging] + exporters: [file, debug] logs: receivers: [otlp] processors: [batch] - # exporters: [file, logging] - exporters: [logging] + exporters: [file, debug] diff --git a/smoke-tests/docker-compose.yml b/smoke-tests/docker-compose.yml index 35e366ab..dec5a587 100644 --- a/smoke-tests/docker-compose.yml +++ b/smoke-tests/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3.0' - x-env-base: &env_base OTEL_EXPORTER_OTLP_ENDPOINT: http://collector:4318 HYPERDX_API_KEY: bogus_key @@ -10,53 +8,22 @@ x-env-base: &env_base OTEL_SERVICE_NAME: 'hello-node-express' DEBUG: 'true' -x-app-base: &app_base - build: - context: ../ - dockerfile: ./examples/hello-node-express/Dockerfile - image: hyperdx/hello-node-express - depends_on: - - collector - x-app-base-ts: &app_base_ts build: context: ../ - dockerfile: ./examples/hello-node-express-ts/Dockerfile + dockerfile: ./smoke-tests/hello-node-express-ts/Dockerfile image: hyperdx/hello-node-express-ts depends_on: - collector services: collector: - image: otel/opentelemetry-collector:0.52.0 + image: otel/opentelemetry-collector:0.137.0 command: ['--config=/etc/otel-collector-config.yaml'] volumes: - './collector/otel-collector-config.yaml:/etc/otel-collector-config.yaml' - './collector:/var/lib' - app-hellonode: - <<: *app_base - environment: - <<: *env_base - ports: - - '127.0.0.1:3000:3000' - - app-hellonode-ts: - <<: *app_base_ts - environment: - <<: *env_base - ports: - - '127.0.0.1:3000:3000' - - app-sdk-http: - <<: *app_base - environment: - <<: *env_base - OTEL_EXPORTER_OTLP_ENDPOINT: http://collector:4318 - OTEL_EXPORTER_OTLP_PROTOCOL: http/protobuf - ports: - - '127.0.0.1:3000:3000' - app-sdk-http-ts: <<: *app_base_ts environment: @@ -66,8 +33,8 @@ services: ports: - '127.0.0.1:3000:3000' - app-sdk-grpc: - <<: *app_base + app-sdk-grpc-ts: + <<: *app_base_ts environment: <<: *env_base OTEL_EXPORTER_OTLP_ENDPOINT: http://collector:4317 @@ -75,11 +42,13 @@ services: ports: - '127.0.0.1:3000:3000' - app-sdk-grpc-ts: + app-sdk-http-ts-programmaticImports: <<: *app_base_ts + command: ['node', './smoke-tests/hello-node-express-ts/dist/index.js'] environment: <<: *env_base - OTEL_EXPORTER_OTLP_ENDPOINT: http://collector:4317 - OTEL_EXPORTER_OTLP_PROTOCOL: grpc + OTEL_EXPORTER_OTLP_ENDPOINT: http://collector:4318 + OTEL_EXPORTER_OTLP_PROTOCOL: http/protobuf + HYPERDX_SDK_PROGRAMMATIC_IMPORTS: 'true' ports: - '127.0.0.1:3000:3000' diff --git a/smoke-tests/hello-node-express-ts/.eslintrc.json b/smoke-tests/hello-node-express-ts/.eslintrc.json new file mode 100644 index 00000000..9f70ddb2 --- /dev/null +++ b/smoke-tests/hello-node-express-ts/.eslintrc.json @@ -0,0 +1,25 @@ +{ + "env": { + "browser": false, + "es6": true, + "node": true + }, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "tsconfig.json", + "sourceType": "module", + "ecmaVersion": 2020 + }, + "plugins": ["@typescript-eslint", "prettier"], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:prettier/recommended" + ], + "rules": { + "@typescript-eslint/ban-ts-comment": "warn", + "@typescript-eslint/explicit-function-return-type": "warn", + "@typescript-eslint/no-this-alias": "warn", + "prettier/prettier": "error" + } +} diff --git a/examples/hello-node-express-ts/Dockerfile b/smoke-tests/hello-node-express-ts/Dockerfile similarity index 54% rename from examples/hello-node-express-ts/Dockerfile rename to smoke-tests/hello-node-express-ts/Dockerfile index b99edf35..eeec00c5 100644 --- a/examples/hello-node-express-ts/Dockerfile +++ b/smoke-tests/hello-node-express-ts/Dockerfile @@ -12,8 +12,10 @@ COPY . . # example app listens on port 3000 EXPOSE 3000 +ENV PUPPETEER_SKIP_DOWNLOAD=true + # symlink hyperdx sdk dependency -RUN cd ./examples/hello-node-express-ts/ && npm run setup && npm run build +RUN cd ./smoke-tests/hello-node-express-ts/ && npm run setup && npm run build # run example express app -CMD [ "node", "-r", "./examples/hello-node-express-ts/dist/instrumentation.js", "./examples/hello-node-express-ts/dist/index.js" ] +CMD [ "node", "-r", "@hyperdx/node-opentelemetry/build/src/tracing", "./smoke-tests/hello-node-express-ts/dist/index.js" ] diff --git a/examples/hello-node-express-ts/README.md b/smoke-tests/hello-node-express-ts/README.md similarity index 100% rename from examples/hello-node-express-ts/README.md rename to smoke-tests/hello-node-express-ts/README.md diff --git a/examples/hello-node-express-ts/index.ts b/smoke-tests/hello-node-express-ts/index.ts similarity index 61% rename from examples/hello-node-express-ts/index.ts rename to smoke-tests/hello-node-express-ts/index.ts index 93b42deb..5cc559d0 100644 --- a/examples/hello-node-express-ts/index.ts +++ b/smoke-tests/hello-node-express-ts/index.ts @@ -1,3 +1,10 @@ +import * as HyperDX from '@hyperdx/node-opentelemetry'; + +// Initialize HyperDX SDK BEFORE importing other libraries for programmatic imports +if (process.env.HYPERDX_SDK_PROGRAMMATIC_IMPORTS === 'true') { + HyperDX.init({}); +} + import { context, Context, @@ -11,6 +18,23 @@ import { ValueType, } from '@opentelemetry/api'; import express, { Express, NextFunction, Request, Response } from 'express'; +import pino from 'pino'; + +const pinoLogger = pino({ + mixin: HyperDX.getPinoMixinFunction, + transport: { + targets: [ + HyperDX.getPinoTransport('info', { + // Send logs info and above + detectResources: true, + }), + { + target: 'pino-pretty', + level: 'debug', + }, + ], + }, +}); const app: Express = express(); const hostname = '0.0.0.0'; @@ -67,6 +91,37 @@ app.get('/', async (_req: Request, res: Response, next: NextFunction) => { } }); +app.get('/logs', (_req: Request, res: Response) => { + // Log with different levels + pinoLogger.trace('This is a trace log - lowest level'); + pinoLogger.debug({ debugInfo: 'some debug data' }, 'This is a debug log'); + pinoLogger.info({ userId: 123, action: 'test' }, 'This is an info log'); + pinoLogger.warn( + { warning: 'something might be wrong' }, + 'This is a warning log', + ); + pinoLogger.error({ error: 'something went wrong' }, 'This is an error log'); + pinoLogger.fatal({ critical: 'system failure' }, 'This is a fatal log'); + + // Log with nested objects + pinoLogger.info( + { + request: { + method: 'GET', + path: '/logs', + headers: { 'user-agent': 'test' }, + }, + performance: { + duration: 123, + memory: process.memoryUsage(), + }, + }, + 'Complex log with nested data', + ); + + res.status(200).json({ message: 'Logs generated successfully' }); +}); + function sleepy(): Promise { return new Promise((resolve) => { setTimeout(() => { diff --git a/examples/hello-node-express-ts/package.json b/smoke-tests/hello-node-express-ts/package.json similarity index 66% rename from examples/hello-node-express-ts/package.json rename to smoke-tests/hello-node-express-ts/package.json index aab62b04..173fd211 100644 --- a/examples/hello-node-express-ts/package.json +++ b/smoke-tests/hello-node-express-ts/package.json @@ -7,14 +7,16 @@ "main": "dist/index.js", "scripts": { "build": "tsc --build", - "setup": "yarn install && cd ../.. && yarn install && yarn ci:build --exclude='@hyperdx/deno' && cd ./packages/node-opentelemetry && yarn link && cd ../../examples/hello-node-express-ts && yarn link @hyperdx/node-opentelemetry", + "setup": "yarn install && cd ../.. && yarn install && npx nx build @hyperdx/node-opentelemetry --skip-nx-cache && cd ./packages/node-opentelemetry && yarn link && cd ../../smoke-tests/hello-node-express-ts && yarn link @hyperdx/node-opentelemetry", "start": "ts-node -r ./instrumentation.ts index.ts", "start-js": "node -r ./dist/instrumentation.js ./dist/index.js" }, "dependencies": { "@opentelemetry/api": "^1.7.0", "@opentelemetry/resources": "^1.17.1", - "express": "^4.19.2" + "express": "^4.19.2", + "pino": "^10.0.0", + "pino-pretty": "^13.0.0" }, "devDependencies": { "@types/express": "^4.17.21", diff --git a/examples/hello-node-express-ts/tsconfig.json b/smoke-tests/hello-node-express-ts/tsconfig.json similarity index 100% rename from examples/hello-node-express-ts/tsconfig.json rename to smoke-tests/hello-node-express-ts/tsconfig.json diff --git a/examples/hello-node-express-ts/yarn.lock b/smoke-tests/hello-node-express-ts/yarn.lock similarity index 86% rename from examples/hello-node-express-ts/yarn.lock rename to smoke-tests/hello-node-express-ts/yarn.lock index 672378a9..c75fee38 100644 --- a/examples/hello-node-express-ts/yarn.lock +++ b/smoke-tests/hello-node-express-ts/yarn.lock @@ -184,6 +184,11 @@ array-flatten@1.1.1: resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== +atomic-sleep@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== + body-parser@1.20.2: version "1.20.2" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" @@ -500,6 +505,11 @@ object-inspect@^1.13.1: resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz" integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== +on-exit-leak-free@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" + integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== + on-finished@2.4.1: version "2.4.1" resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz" @@ -517,6 +527,40 @@ path-to-regexp@0.1.7: resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== +pino-abstract-transport@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz#de241578406ac7b8a33ce0d77ae6e8a0b3b68a60" + integrity sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw== + dependencies: + split2 "^4.0.0" + +pino-std-serializers@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz#7c625038b13718dbbd84ab446bd673dc52259e3b" + integrity sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA== + +pino@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/pino/-/pino-10.0.0.tgz#3d1a8abc7a700142edebf02a7b291834da199fbe" + integrity sha512-eI9pKwWEix40kfvSzqEP6ldqOoBIN7dwD/o91TY5z8vQI12sAffpR/pOqAD1IVVwIVHDpHjkq0joBPdJD0rafA== + dependencies: + atomic-sleep "^1.0.0" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^2.0.0" + pino-std-serializers "^7.0.0" + process-warning "^5.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.2.0" + safe-stable-stringify "^2.3.1" + slow-redact "^0.3.0" + sonic-boom "^4.0.1" + thread-stream "^3.0.0" + +process-warning@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-5.0.0.tgz#566e0bf79d1dff30a72d8bbbe9e8ecefe8d378d7" + integrity sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA== + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" @@ -532,6 +576,11 @@ qs@6.11.0: dependencies: side-channel "^1.0.4" +quick-format-unescaped@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" + integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== + range-parser@~1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" @@ -547,11 +596,21 @@ raw-body@2.5.2: iconv-lite "0.4.24" unpipe "1.0.0" +real-require@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" + integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== + safe-buffer@5.2.1: version "5.2.1" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-stable-stringify@^2.3.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" + integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== + "safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" @@ -613,11 +672,35 @@ side-channel@^1.0.4: get-intrinsic "^1.2.4" object-inspect "^1.13.1" +slow-redact@^0.3.0: + version "0.3.2" + resolved "https://registry.yarnpkg.com/slow-redact/-/slow-redact-0.3.2.tgz#d06e25195aa5c492d32631c53d9ae86043b8b0e2" + integrity sha512-MseHyi2+E/hBRqdOi5COy6wZ7j7DxXRz9NkseavNYSvvWC06D8a5cidVZX3tcG5eCW3NIyVU4zT63hw0Q486jw== + +sonic-boom@^4.0.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.2.0.tgz#e59a525f831210fa4ef1896428338641ac1c124d" + integrity sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww== + dependencies: + atomic-sleep "^1.0.0" + +split2@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + statuses@2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== +thread-stream@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-3.1.0.tgz#4b2ef252a7c215064507d4ef70c05a5e2d34c4f1" + integrity sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A== + dependencies: + real-require "^0.2.0" + toidentifier@1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" diff --git a/smoke-tests/smoke-sdk-grpc-ts.bats b/smoke-tests/smoke-sdk-grpc-ts.bats index c1206c2e..d1f6ae73 100644 --- a/smoke-tests/smoke-sdk-grpc-ts.bats +++ b/smoke-tests/smoke-sdk-grpc-ts.bats @@ -6,35 +6,45 @@ CONTAINER_NAME="app-sdk-grpc-ts" TRACER_NAME="hello-world-tracer" METER_NAME="hello-world-meter" NODE_METER_NAME="node-monitor-meter" +LOG_SCOPE_NAME="node-logger" setup_file() { - echo "# ๐Ÿšง" >&3 - docker compose up --build --detach collector ${CONTAINER_NAME} + echo "# ๐Ÿšง Starting smoke-sdk-grpc-ts tests" >&3 + echo "# ๐Ÿ“ฆ Starting containers: collector ${CONTAINER_NAME}" >&3 + docker compose up --detach collector ${CONTAINER_NAME} >&3 2>&3 wait_for_ready_app ${CONTAINER_NAME} + echo "# ๐ŸŒ Sending test request to http://localhost:3000" >&3 curl --silent "http://localhost:3000" + echo "# ๐ŸŒ Sending test request to http://localhost:3000/logs" >&3 + curl --silent "http://localhost:3000/logs" wait_for_traces - # wait_for_metrics + wait_for_metrics 15 } teardown_file() { + echo "# ๐Ÿงน Cleaning up smoke-sdk-grpc-ts tests" >&3 + echo "# ๐Ÿ’พ Saving collector data to data-${CONTAINER_NAME}.json" >&3 cp collector/data.json collector/data-results/data-${CONTAINER_NAME}.json - docker compose stop ${CONTAINER_NAME} - docker compose restart collector + echo "# ๐Ÿ›‘ Stopping ${CONTAINER_NAME} container" >&3 + docker compose stop ${CONTAINER_NAME} >&3 2>&3 + echo "# ๐Ÿ”„ Restarting collector" >&3 + docker compose restart collector >&3 2>&3 wait_for_flush } # TESTS -@test "Auto instrumentation produces 3 Express middleware spans" { - result=$(span_names_for "@opentelemetry/instrumentation-express") - assert_equal "$result" '"middleware - query" -"middleware - expressInit" -"request handler - /"' +@test "Auto instrumentation produces Express middleware spans" { + echo "# โœ… Testing: Auto instrumentation produces Express middleware spans" >&3 + result=$(span_names_for "@opentelemetry/instrumentation-express" | grep -c "middleware") + [ "$result" -ge 4 ] } -@test "Auto instrumentation produces an http request span" { +@test "Auto instrumentation produces http request spans" { + echo "# โœ… Testing: Auto instrumentation produces http request spans" >&3 result=$(span_names_for "@opentelemetry/instrumentation-http") - assert_equal "$result" '"GET /"' + echo "$result" | grep -q "GET /" + echo "$result" | grep -q "GET /logs" } # @test "Manual instrumentation produces span with name of span" { @@ -52,11 +62,41 @@ teardown_file() { # assert_equal "$result" '"another important value"' # } -# @test "Manual instrumentation produces metrics for counter" { -# result=$(metric_names_for ${METER_NAME}) -# assert_equal "$result" '"sheep"' -# } -# @test "Manual instrumentation produces metrics for observable gauge" { -# result=$(metric_names_for ${NODE_METER_NAME}) -# assert_equal "$result" '"process.runtime.nodejs.memory.heap.total"' -# } +@test "Manual instrumentation produces metrics for counter" { + result=$(metric_names_for ${METER_NAME}) + assert_equal "$result" '"sheep"' +} +@test "Manual instrumentation produces metrics for observable gauge" { + result=$(metric_names_for ${NODE_METER_NAME}) + assert_equal "$result" '"process.runtime.nodejs.memory.heap.total"' +} + +@test "Pino logger produces logs with different severity levels" { + echo "# โœ… Testing: Pino logger produces logs with different severity levels" >&3 + result=$(log_severities_for ${LOG_SCOPE_NAME} | grep -E '"(info|warn|error|fatal)"' | wc -l | xargs) + [ "$result" -ge 4 ] +} + +@test "Pino logger produces info level log" { + echo "# โœ… Testing: Pino logger produces info level log" >&3 + result=$(log_bodies_for ${LOG_SCOPE_NAME} | grep "This is an info log") + assert_equal "$result" '"This is an info log"' +} + +@test "Pino logger produces error level log" { + echo "# โœ… Testing: Pino logger produces error level log" >&3 + result=$(log_bodies_for ${LOG_SCOPE_NAME} | grep "This is an error log") + assert_equal "$result" '"This is an error log"' +} + +@test "Logs and traces share the same trace ID" { + echo "# โœ… Testing: Logs and traces share the same trace ID" >&3 + log_trace_id=$(log_trace_ids_for ${LOG_SCOPE_NAME} | head -1) + span_trace_id=$(span_trace_ids_for "@opentelemetry/instrumentation-http" | grep -v "^$" | head -1) + echo "# Log trace ID: $log_trace_id" >&3 + echo "# Span trace ID: $span_trace_id" >&3 + [ -n "$log_trace_id" ] + [ -n "$span_trace_id" ] + # Check if log trace ID appears in any span trace IDs + span_trace_ids_for "@opentelemetry/instrumentation-http" | grep -q "$log_trace_id" +} diff --git a/smoke-tests/smoke-sdk-grpc.bats b/smoke-tests/smoke-sdk-grpc.bats deleted file mode 100644 index 7c055a87..00000000 --- a/smoke-tests/smoke-sdk-grpc.bats +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env bats - -load test_helpers/utilities - -CONTAINER_NAME="app-sdk-grpc" -TRACER_NAME="hello-world-tracer" -METER_NAME="hello-world-meter" - -setup_file() { - echo "# ๐Ÿšง" >&3 - docker compose up --build --detach collector ${CONTAINER_NAME} - wait_for_ready_app ${CONTAINER_NAME} - curl --silent "http://localhost:3000" - wait_for_traces - # wait_for_metrics 5 -} - -teardown_file() { - cp collector/data.json collector/data-results/data-${CONTAINER_NAME}.json - docker compose stop ${CONTAINER_NAME} - docker compose restart collector - wait_for_flush -} - -# TESTS - -@test "Auto instrumentation produces 3 Express middleware spans" { - result=$(span_names_for "@opentelemetry/instrumentation-express") - assert_equal "$result" '"middleware - query" -"middleware - expressInit" -"request handler - /"' -} - -@test "Auto instrumentation produces an http request span" { - result=$(span_names_for "@opentelemetry/instrumentation-http") - assert_equal "$result" '"GET /"' -} - -# @test "Manual instrumentation produces span with name of span" { -# result=$(span_names_for ${TRACER_NAME}) -# assert_equal "$result" '"sleep"' -# } - -# @test "Manual instrumentation adds custom attribute" { -# result=$(span_attributes_for ${TRACER_NAME} | jq "select(.key == \"delay_ms\").value.intValue") -# assert_equal "$result" '"100"' -# } - -# @test "BaggageSpanProcessor: key-values added to baggage appear on child spans" { -# result=$(span_attributes_for ${TRACER_NAME} | jq "select(.key == \"for_the_children\").value.stringValue") -# assert_equal "$result" '"another important value"' -# } - -# @test "Manual instrumentation produces metrics" { -# result=$(metric_names_for ${METER_NAME}) -# assert_equal "$result" '"sheep"' -# } diff --git a/smoke-tests/smoke-sdk-http-ts-programmaticImports.bats b/smoke-tests/smoke-sdk-http-ts-programmaticImports.bats new file mode 100644 index 00000000..b64f2ec2 --- /dev/null +++ b/smoke-tests/smoke-sdk-http-ts-programmaticImports.bats @@ -0,0 +1,97 @@ +#!/usr/bin/env bats + +load test_helpers/utilities + +CONTAINER_NAME="app-sdk-http-ts-programmaticImports" +TRACER_NAME="hello-world-tracer" +METER_NAME="hello-world-meter" +NODE_METER_NAME="node-monitor-meter" +LOG_SCOPE_NAME="node-logger" + +setup_file() { + echo "# ๐Ÿšง Starting smoke-sdk-http-ts-programmaticImports tests" >&3 + echo "# ๐Ÿ“ฆ Starting containers: collector ${CONTAINER_NAME}" >&3 + docker compose up --detach collector ${CONTAINER_NAME} >&3 2>&3 + wait_for_ready_app ${CONTAINER_NAME} + echo "# ๐ŸŒ Sending test request to http://localhost:3000" >&3 + curl --silent "http://localhost:3000" + echo "# ๐ŸŒ Sending test request to http://localhost:3000/logs" >&3 + curl --silent "http://localhost:3000/logs" + wait_for_traces + wait_for_metrics 15 +} + +teardown_file() { + echo "# ๐Ÿงน Cleaning up smoke-sdk-http-ts-programmaticImports tests" >&3 + echo "# ๐Ÿ’พ Saving collector data to data-${CONTAINER_NAME}.json" >&3 + cp collector/data.json collector/data-results/data-${CONTAINER_NAME}.json + echo "# ๐Ÿ›‘ Stopping ${CONTAINER_NAME} container" >&3 + docker compose stop ${CONTAINER_NAME} >&3 2>&3 + echo "# ๐Ÿ”„ Restarting collector" >&3 + docker compose restart collector >&3 2>&3 + wait_for_flush +} + +# TESTS + +@test "HTTP instrumentation produces an http request span (without route)" { + echo "# โœ… Testing: HTTP instrumentation produces an http request span (without route)" >&3 + result=$(span_names_for "@opentelemetry/instrumentation-http") + assert_equal "$result" '"GET"' +} + +@test "Manual instrumentation produces span with name of span" { + echo "# โœ… Testing: Manual instrumentation produces span with name of span" >&3 + result=$(span_names_for ${TRACER_NAME}) + assert_equal "$result" '"sleep"' +} + +@test "Manual instrumentation adds custom attribute" { + echo "# โœ… Testing: Manual instrumentation adds custom attribute" >&3 + result=$(span_attributes_for ${TRACER_NAME} | jq "select(.key == \"delay_ms\").value.intValue") + assert_equal "$result" '"100"' +} + +# @test "BaggageSpanProcessor: key-values added to baggage appear on child spans" { +# result=$(span_attributes_for ${TRACER_NAME} | jq "select(.key == \"for_the_children\").value.stringValue") +# assert_equal "$result" '"another important value"' +# } + +@test "Manual instrumentation produces metrics for counter" { + result=$(metric_names_for ${METER_NAME}) + assert_equal "$result" '"sheep"' +} +@test "Manual instrumentation produces metrics for observable gauge" { + result=$(metric_names_for ${NODE_METER_NAME}) + assert_equal "$result" '"process.runtime.nodejs.memory.heap.total"' +} + +@test "Pino logger produces logs with different severity levels" { + echo "# โœ… Testing: Pino logger produces logs with different severity levels" >&3 + result=$(log_severities_for ${LOG_SCOPE_NAME} | grep -E '"(info|warn|error|fatal)"' | wc -l | xargs) + [ "$result" -ge 4 ] +} + +@test "Pino logger produces info level log" { + echo "# โœ… Testing: Pino logger produces info level log" >&3 + result=$(log_bodies_for ${LOG_SCOPE_NAME} | grep "This is an info log") + assert_equal "$result" '"This is an info log"' +} + +@test "Pino logger produces error level log" { + echo "# โœ… Testing: Pino logger produces error level log" >&3 + result=$(log_bodies_for ${LOG_SCOPE_NAME} | grep "This is an error log") + assert_equal "$result" '"This is an error log"' +} + +@test "Logs and traces share the same trace ID" { + echo "# โœ… Testing: Logs and traces share the same trace ID" >&3 + log_trace_id=$(log_trace_ids_for ${LOG_SCOPE_NAME} | head -1) + span_trace_id=$(span_trace_ids_for "@opentelemetry/instrumentation-http" | grep -v "^$" | head -1) + echo "# Log trace ID: $log_trace_id" >&3 + echo "# Span trace ID: $span_trace_id" >&3 + [ -n "$log_trace_id" ] + [ -n "$span_trace_id" ] + # Check if log trace ID appears in any span trace IDs + span_trace_ids_for "@opentelemetry/instrumentation-http" | grep -q "$log_trace_id" +} diff --git a/smoke-tests/smoke-sdk-http-ts.bats b/smoke-tests/smoke-sdk-http-ts.bats index ada88b3a..6c02eb63 100644 --- a/smoke-tests/smoke-sdk-http-ts.bats +++ b/smoke-tests/smoke-sdk-http-ts.bats @@ -6,43 +6,55 @@ CONTAINER_NAME="app-sdk-http-ts" TRACER_NAME="hello-world-tracer" METER_NAME="hello-world-meter" NODE_METER_NAME="node-monitor-meter" +LOG_SCOPE_NAME="node-logger" setup_file() { - echo "# ๐Ÿšง" >&3 - docker compose up --build --detach collector ${CONTAINER_NAME} + echo "# ๐Ÿšง Starting smoke-sdk-http-ts tests" >&3 + echo "# ๐Ÿ“ฆ Starting containers: collector ${CONTAINER_NAME}" >&3 + docker compose up --detach collector ${CONTAINER_NAME} >&3 2>&3 wait_for_ready_app ${CONTAINER_NAME} + echo "# ๐ŸŒ Sending test request to http://localhost:3000" >&3 curl --silent "http://localhost:3000" + echo "# ๐ŸŒ Sending test request to http://localhost:3000/logs" >&3 + curl --silent "http://localhost:3000/logs" wait_for_traces - # wait_for_metrics 15 + wait_for_metrics 15 } teardown_file() { + echo "# ๐Ÿงน Cleaning up smoke-sdk-http-ts tests" >&3 + echo "# ๐Ÿ’พ Saving collector data to data-${CONTAINER_NAME}.json" >&3 cp collector/data.json collector/data-results/data-${CONTAINER_NAME}.json - docker compose stop ${CONTAINER_NAME} - docker compose restart collector + echo "# ๐Ÿ›‘ Stopping ${CONTAINER_NAME} container" >&3 + docker compose stop ${CONTAINER_NAME} >&3 2>&3 + echo "# ๐Ÿ”„ Restarting collector" >&3 + docker compose restart collector >&3 2>&3 wait_for_flush } # TESTS -@test "Auto instrumentation produces 3 Express middleware spans" { - result=$(span_names_for "@opentelemetry/instrumentation-express") - assert_equal "$result" '"middleware - query" -"middleware - expressInit" -"request handler - /"' +@test "Auto instrumentation produces Express middleware spans" { + echo "# โœ… Testing: Auto instrumentation produces Express middleware spans" >&3 + result=$(span_names_for "@opentelemetry/instrumentation-express" | grep -c "middleware") + [ "$result" -ge 4 ] } -@test "Auto instrumentation produces an http request span" { +@test "Auto instrumentation produces http request spans" { + echo "# โœ… Testing: Auto instrumentation produces http request spans" >&3 result=$(span_names_for "@opentelemetry/instrumentation-http") - assert_equal "$result" '"GET /"' + echo "$result" | grep -q "GET /" + echo "$result" | grep -q "GET /logs" } @test "Manual instrumentation produces span with name of span" { + echo "# โœ… Testing: Manual instrumentation produces span with name of span" >&3 result=$(span_names_for ${TRACER_NAME}) assert_equal "$result" '"sleep"' } @test "Manual instrumentation adds custom attribute" { + echo "# โœ… Testing: Manual instrumentation adds custom attribute" >&3 result=$(span_attributes_for ${TRACER_NAME} | jq "select(.key == \"delay_ms\").value.intValue") assert_equal "$result" '"100"' } @@ -52,11 +64,41 @@ teardown_file() { # assert_equal "$result" '"another important value"' # } -# @test "Manual instrumentation produces metrics for counter" { -# result=$(metric_names_for ${METER_NAME}) -# assert_equal "$result" '"sheep"' -# } -# @test "Manual instrumentation produces metrics for observable gauge" { -# result=$(metric_names_for ${NODE_METER_NAME}) -# assert_equal "$result" '"process.runtime.nodejs.memory.heap.total"' -# } +@test "Manual instrumentation produces metrics for counter" { + result=$(metric_names_for ${METER_NAME}) + assert_equal "$result" '"sheep"' +} +@test "Manual instrumentation produces metrics for observable gauge" { + result=$(metric_names_for ${NODE_METER_NAME}) + assert_equal "$result" '"process.runtime.nodejs.memory.heap.total"' +} + +@test "Pino logger produces logs with different severity levels" { + echo "# โœ… Testing: Pino logger produces logs with different severity levels" >&3 + result=$(log_severities_for ${LOG_SCOPE_NAME} | grep -E '"(info|warn|error|fatal)"' | wc -l | xargs) + [ "$result" -ge 4 ] +} + +@test "Pino logger produces info level log" { + echo "# โœ… Testing: Pino logger produces info level log" >&3 + result=$(log_bodies_for ${LOG_SCOPE_NAME} | grep "This is an info log") + assert_equal "$result" '"This is an info log"' +} + +@test "Pino logger produces error level log" { + echo "# โœ… Testing: Pino logger produces error level log" >&3 + result=$(log_bodies_for ${LOG_SCOPE_NAME} | grep "This is an error log") + assert_equal "$result" '"This is an error log"' +} + +@test "Logs and traces share the same trace ID" { + echo "# โœ… Testing: Logs and traces share the same trace ID" >&3 + log_trace_id=$(log_trace_ids_for ${LOG_SCOPE_NAME} | head -1) + span_trace_id=$(span_trace_ids_for "@opentelemetry/instrumentation-http" | grep -v "^$" | head -1) + echo "# Log trace ID: $log_trace_id" >&3 + echo "# Span trace ID: $span_trace_id" >&3 + [ -n "$log_trace_id" ] + [ -n "$span_trace_id" ] + # Check if log trace ID appears in any span trace IDs + span_trace_ids_for "@opentelemetry/instrumentation-http" | grep -q "$log_trace_id" +} diff --git a/smoke-tests/smoke-sdk-http.bats b/smoke-tests/smoke-sdk-http.bats deleted file mode 100644 index 6a67fca0..00000000 --- a/smoke-tests/smoke-sdk-http.bats +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env bats - -load test_helpers/utilities - -CONTAINER_NAME="app-sdk-http" -TRACER_NAME="hello-world-tracer" -METER_NAME="hello-world-meter" - -setup_file() { - echo "# ๐Ÿšง" >&3 - docker compose up --build --detach collector ${CONTAINER_NAME} - wait_for_ready_app ${CONTAINER_NAME} - curl --silent "http://localhost:3000" - wait_for_traces - # wait_for_metrics 15 -} - -teardown_file() { - cp collector/data.json collector/data-results/data-${CONTAINER_NAME}.json - docker compose stop ${CONTAINER_NAME} - docker compose restart collector - wait_for_flush -} - -# TESTS - -@test "Auto instrumentation produces 3 Express middleware spans" { - result=$(span_names_for "@opentelemetry/instrumentation-express") - assert_equal "$result" '"middleware - query" -"middleware - expressInit" -"request handler - /"' -} - -@test "Auto instrumentation produces an http request span" { - result=$(span_names_for "@opentelemetry/instrumentation-http") - assert_equal "$result" '"GET /"' -} - -@test "Manual instrumentation produces span with name of span" { - result=$(span_names_for ${TRACER_NAME}) - assert_equal "$result" '"sleep"' -} - -@test "Manual instrumentation adds custom attribute" { - result=$(span_attributes_for ${TRACER_NAME} | jq "select(.key == \"delay_ms\").value.intValue") - assert_equal "$result" '"100"' -} - -# @test "BaggageSpanProcessor: key-values added to baggage appear on child spans" { -# result=$(span_attributes_for ${TRACER_NAME} | jq "select(.key == \"for_the_children\").value.stringValue") -# assert_equal "$result" '"another important value"' -# } - -# @test "Manual instrumentation produces metrics" { -# result=$(metric_names_for ${METER_NAME}) -# assert_equal "$result" '"sheep"' -# } diff --git a/smoke-tests/test_helpers/utilities.bash b/smoke-tests/test_helpers/utilities.bash index 19cf39af..f9475d85 100644 --- a/smoke-tests/test_helpers/utilities.bash +++ b/smoke-tests/test_helpers/utilities.bash @@ -16,21 +16,31 @@ metrics_received() { jq ".resourceMetrics[]?" ./collector/data.json } +logs_received() { + jq ".resourceLogs[]?" ./collector/data.json +} + +logs_from_scope_named() { + logs_received | jq ".scopeLogs[] | select(.scope.name == \"$1\").logRecords[]" +} + # test span name span_names_for() { + echo "# ๐Ÿ” Getting span names for library: $1" >&3 spans_from_library_named $1 | jq '.name' } # test span attributes span_attributes_for() { # $1 - library name - + echo "# ๐Ÿ” Getting span attributes for library: $1" >&3 spans_from_library_named $1 | \ jq ".attributes[]" } # test metric name metric_names_for() { + echo "# ๐Ÿ” Getting metric names for library: $1" >&3 metrics_from_library_named $1 | jq '.name' } @@ -49,6 +59,30 @@ wait_for_metrics() { [ $NEXT_WAIT_TIME -lt $MAX_RETRIES ] } +# test log body messages +log_bodies_for() { + echo "# ๐Ÿ” Getting log bodies for scope: $1" >&3 + logs_from_scope_named $1 | jq '.body.stringValue' +} + +# test log severity +log_severities_for() { + echo "# ๐Ÿ” Getting log severities for scope: $1" >&3 + logs_from_scope_named $1 | jq '.severityText' +} + +# test log trace IDs +log_trace_ids_for() { + echo "# ๐Ÿ” Getting log trace IDs for scope: $1" >&3 + logs_from_scope_named $1 | jq -r 'select(.traceId != null and .traceId != "") | .traceId' +} + +# get span trace IDs +span_trace_ids_for() { + echo "# ๐Ÿ” Getting span trace IDs for library: $1" >&3 + spans_from_library_named $1 | jq -r '.traceId' +} + # Arguments # $1 - retry limit (default 5); Nth retry sleeps for N seconds wait_for_data() { @@ -98,14 +132,18 @@ wait_for_flush() { wait_for_ready_app() { CONTAINER=${1:?container name is a required parameter} MAX_RETRIES=10 - echo -n "# ๐Ÿฟ Setting up ${CONTAINER}" >&3 + echo "# ๐Ÿฟ Setting up ${CONTAINER}" >&3 NEXT_WAIT_TIME=0 - until [ $NEXT_WAIT_TIME -eq $MAX_RETRIES ] || [[ $(docker compose logs ${CONTAINER} | grep "Now listening on:") ]] + until [ $NEXT_WAIT_TIME -eq $MAX_RETRIES ] || [[ $(docker compose logs ${CONTAINER} 2>&1) =~ "Now listening on:" ]] do - echo -n " ... $(( NEXT_WAIT_TIME++ ))s" >&3 - sleep $NEXT_WAIT_TIME + echo "# ... waiting $(( NEXT_WAIT_TIME ))s" >&3 + if [ $NEXT_WAIT_TIME -gt 0 ]; then + echo "# Container logs:" >&3 + docker compose logs ${CONTAINER} 2>&1 | tail -10 >&3 + fi + sleep $(( NEXT_WAIT_TIME++ )) done - echo "" >&3 + echo "# โœ“ ${CONTAINER} is ready" >&3 [ $NEXT_WAIT_TIME -lt $MAX_RETRIES ] }