From fe0b45e4036436337fcdd061a4c90881fd790747 Mon Sep 17 00:00:00 2001 From: William Chong Date: Tue, 28 May 2024 16:42:23 +0400 Subject: [PATCH] Add code samples for user certificates and opentelemetry (#380) --- packages/test/package.json | 3 +- packages/test/src/samples/opentelemetry.ts | 104 ++++++++++++++ .../test/src/samples/user-certificates.ts | 47 +++++++ yarn.lock | 130 ++++++++++++++++++ 4 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 packages/test/src/samples/opentelemetry.ts create mode 100644 packages/test/src/samples/user-certificates.ts diff --git a/packages/test/package.json b/packages/test/package.json index 4a0e2a0..d1033bb 100644 --- a/packages/test/package.json +++ b/packages/test/package.json @@ -35,6 +35,7 @@ }, "devDependencies": { "@opentelemetry/api": "^1.8.0", + "@opentelemetry/exporter-trace-otlp-grpc": "^0.51.1", "@opentelemetry/sdk-trace-node": "^1.23.0", "@opentelemetry/semantic-conventions": "^1.23.0", "@types/jest": "^29.5.12", @@ -44,4 +45,4 @@ "npm-run-all": "^4.1.5", "shx": "^0.3.4" } -} +} \ No newline at end of file diff --git a/packages/test/src/samples/opentelemetry.ts b/packages/test/src/samples/opentelemetry.ts new file mode 100644 index 0000000..d604759 --- /dev/null +++ b/packages/test/src/samples/opentelemetry.ts @@ -0,0 +1,104 @@ +// region import-required-packages +import { + InMemorySpanExporter, + NodeTracerProvider, + ConsoleSpanExporter, + SimpleSpanProcessor, +} from "@opentelemetry/sdk-trace-node"; +import { registerInstrumentations } from "@opentelemetry/instrumentation"; +import { EventStoreDBInstrumentation } from "@eventstore/opentelemetry"; +import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc"; +import {} from "@opentelemetry/sdk-trace-node"; +// endregion import-required-packages +import { createTestNode } from "@test-utils"; +import { EventStoreDBClient } from "@eventstore/db-client"; + +import * as esdb from "@eventstore/db-client"; + +// region register-instrumentation +const provider = new NodeTracerProvider(); + +const instrumentation = new EventStoreDBInstrumentation(); + +registerInstrumentations({ + instrumentations: [instrumentation], + tracerProvider: provider, +}); +// endregion register-instrumentation + +instrumentation.disable(); + +describe("[sample] opentelemetry", () => { + const node = createTestNode(); + let client!: EventStoreDBClient; + + // region setup-exporter + const memoryExporter = new InMemorySpanExporter(); + const otlpExporter = new OTLPTraceExporter({ url: "http://localhost:4317" }); // change this to your OTLP receiver address + const consoleExporter = new ConsoleSpanExporter(); + + provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); + provider.addSpanProcessor(new SimpleSpanProcessor(consoleExporter)); + provider.addSpanProcessor(new SimpleSpanProcessor(otlpExporter)); + // endregion setup-exporter + + // @ts-expect-error the moduleExports property is private. This is needed to make the test work with auto-mocking + instrumentation._modules[0].moduleExports = esdb; + + beforeAll(async () => { + await node.up(); + client = new EventStoreDBClient( + { endpoint: node.uri }, + { rootCertificate: node.certs.root }, + { username: "admin", password: "changeit" } + ); + }); + + beforeAll(async () => { + await node.up(); + instrumentation.enable(); + }); + + afterAll(async () => { + instrumentation.disable(); + await node.down(); + }); + + afterEach(() => { + memoryExporter.reset(); + }); + + test("tracing", async () => { + // region setup-client-for-tracing + const { EventStoreDBClient, jsonEvent } = await import( + "@eventstore/db-client" + ); + + const client = new EventStoreDBClient( + { endpoint: node.uri }, + { rootCertificate: node.certs.root }, + { username: "admin", password: "changeit" } + ); + // endregion setup-client-for-tracing + + const response = await client.appendToStream( + "some-stream", + jsonEvent({ + type: "OrderPlaced", + data: { + orderId: "1337", + orderValue: 123.45, + }, + }), + { + expectedRevision: "any", + } + ); + + expect(response).toBeDefined(); + + const memorySpans = memoryExporter.getFinishedSpans(); + + expect(memorySpans.length).toBe(1); + }); +}); diff --git a/packages/test/src/samples/user-certificates.ts b/packages/test/src/samples/user-certificates.ts new file mode 100644 index 0000000..9bfa725 --- /dev/null +++ b/packages/test/src/samples/user-certificates.ts @@ -0,0 +1,47 @@ +import { EventStoreDBClient } from "@eventstore/db-client"; +import { createTestNode, jsonTestEvents } from "@test-utils"; +import { v4 as uuid } from "uuid"; + +const STREAM_NAME = uuid(); + +describe("[sample] user certificates", () => { + const node = createTestNode(); + + beforeAll(async () => { + await node.up(); + }); + + afterAll(async () => { + await node.down(); + }); + + test("connection string", async () => { + const connectionStringTemplate = `esdb://admin:changeit@{endpoint}?tls=true&userCertFile={pathToCaFile}&userKeyFile={pathToKeyFile}`; + + try { + // region client-with-user-certificates + const connectionString = `esdb://admin:changeit@{endpoint}?tls=true&userCertFile={pathToCaFile}&userKeyFile={pathToKeyFile}`; + const client = EventStoreDBClient.connectionString(connectionString); + // endregion client-with-user-certificates + + expect(connectionString).toBe(connectionStringTemplate); + } catch (error) { + // do nothing. + } + + const endpoints = node.endpoints + .map((endpoint) => `${endpoint.address}:${endpoint.port}`) + .join(","); + let connectionStringTest = connectionStringTemplate + .replace("{endpoint}", endpoints) + .replace("{pathToCaFile}", node.certPath.admin.certPath) + .replace("{pathToKeyFile}", node.certPath.admin.certKeyPath); + + connectionStringTest = `${connectionStringTest}&tlsCaFile=${node.certPath.root}`; + + const client = EventStoreDBClient.connectionString(connectionStringTest); + + const result = await client.appendToStream(STREAM_NAME, jsonTestEvents(2)); + expect(result).toBeDefined(); + }); +}); diff --git a/yarn.lock b/yarn.lock index 628104c..62be90f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -361,6 +361,14 @@ resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== +"@grpc/grpc-js@^1.7.1": + version "1.10.8" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.10.8.tgz#99787785cd8335be861afd1cd485ae9f058e4484" + integrity sha512-vYVqYzHicDqyKB+NQhAc54I1QWCBLCrYG6unqOIcBTHx+7x8C9lcoLj3KVJXs2VB4lUbpWY+Kk9NipcbXYWmvg== + dependencies: + "@grpc/proto-loader" "^0.7.13" + "@js-sdsl/ordered-map" "^4.4.2" + "@grpc/grpc-js@^1.9.12": version "1.10.6" resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.10.6.tgz#1e3eb1af911dc888fbef7452f56a7573b8284d54" @@ -379,6 +387,16 @@ protobufjs "^7.2.4" yargs "^17.7.2" +"@grpc/proto-loader@^0.7.13": + version "0.7.13" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.13.tgz#f6a44b2b7c9f7b609f5748c6eac2d420e37670cf" + integrity sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw== + dependencies: + lodash.camelcase "^4.3.0" + long "^5.0.0" + protobufjs "^7.2.5" + yargs "^17.7.2" + "@humanwhocodes/config-array@^0.5.0": version "0.5.0" resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz" @@ -1189,6 +1207,13 @@ dependencies: "@opentelemetry/api" "^1.0.0" +"@opentelemetry/api-logs@0.51.1": + version "0.51.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.51.1.tgz#ded1874c04516c2b8cb24828eef3d6c3d1f75343" + integrity sha512-E3skn949Pk1z2XtXu/lxf6QAZpawuTM/IUEXcAzpiUkTd73Hmvw26FiN3cJuTmkpM5hZzHwkomVdtrh/n/zzwA== + dependencies: + "@opentelemetry/api" "^1.0.0" + "@opentelemetry/api@^1.0.0", "@opentelemetry/api@^1.8.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.8.0.tgz#5aa7abb48f23f693068ed2999ae627d2f7d902ec" @@ -1206,6 +1231,25 @@ dependencies: "@opentelemetry/semantic-conventions" "1.23.0" +"@opentelemetry/core@1.24.1": + version "1.24.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.24.1.tgz#35ab9d2ac9ca938e0ffbdfa40c49c169ac8ba80d" + integrity sha512-wMSGfsdmibI88K9wB498zXY04yThPexo8jvwNNlm542HZB7XrrMRBbAyKJqG8qDRJwIBdBrPMi4V9ZPW/sqrcg== + dependencies: + "@opentelemetry/semantic-conventions" "1.24.1" + +"@opentelemetry/exporter-trace-otlp-grpc@^0.51.1": + version "0.51.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.51.1.tgz#f38ef867ec11d25880fa81d6b5cbd1edec7d75db" + integrity sha512-P9+Hkszih95ITvldGZ+kXvj9HpD1QfS+PwooyHK72GYA+Bgm+yUSAsDkUkDms8+s9HW6poxURv3LcjaMuBBpVQ== + dependencies: + "@grpc/grpc-js" "^1.7.1" + "@opentelemetry/core" "1.24.1" + "@opentelemetry/otlp-grpc-exporter-base" "0.51.1" + "@opentelemetry/otlp-transformer" "0.51.1" + "@opentelemetry/resources" "1.24.1" + "@opentelemetry/sdk-trace-base" "1.24.1" + "@opentelemetry/instrumentation@^0.50.0": version "0.50.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.50.0.tgz#c558cfc64b84c11d304f31ccdf0de312ec60a2c9" @@ -1218,6 +1262,35 @@ semver "^7.5.2" shimmer "^1.2.1" +"@opentelemetry/otlp-exporter-base@0.51.1": + version "0.51.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.51.1.tgz#e3b1e877f88adfd6a5d48acc8b72a1cf70167371" + integrity sha512-UYlnOYyDdzo1Gw559EHCzru0RwhvuXCwoH8jGo9J4gO1TE58GjnEmIjomMsKBCym3qWNJfIQXw+9SZCV0DdQNg== + dependencies: + "@opentelemetry/core" "1.24.1" + +"@opentelemetry/otlp-grpc-exporter-base@0.51.1": + version "0.51.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.51.1.tgz#79a5ffd7c1d8cc0c5dd1af0e57e61b63c7ccc02e" + integrity sha512-ZAS+4pq8o7dsugGTwV9s6JMKSxi+guIHdn0acOv0bqj26e9pWDFx5Ky+bI0aY46uR9Y0JyXqY+KAEYM/SO3DFA== + dependencies: + "@grpc/grpc-js" "^1.7.1" + "@opentelemetry/core" "1.24.1" + "@opentelemetry/otlp-exporter-base" "0.51.1" + protobufjs "^7.2.3" + +"@opentelemetry/otlp-transformer@0.51.1": + version "0.51.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-transformer/-/otlp-transformer-0.51.1.tgz#d2344075de50ff64a11fc047db6bcb301a11dcf8" + integrity sha512-OppYOXwV9LQqqtYUCywqoOqX/JT9LQ5/FMuPZ//eTkvuHdUC4ZMwz2c6uSoT2R90GWvvGnF1iEqTGyTT3xAt2Q== + dependencies: + "@opentelemetry/api-logs" "0.51.1" + "@opentelemetry/core" "1.24.1" + "@opentelemetry/resources" "1.24.1" + "@opentelemetry/sdk-logs" "0.51.1" + "@opentelemetry/sdk-metrics" "1.24.1" + "@opentelemetry/sdk-trace-base" "1.24.1" + "@opentelemetry/propagator-b3@1.23.0": version "1.23.0" resolved "https://registry.yarnpkg.com/@opentelemetry/propagator-b3/-/propagator-b3-1.23.0.tgz#436c1e33b68e6b0964853d0dc3e4f5f0b785c47e" @@ -1240,6 +1313,31 @@ "@opentelemetry/core" "1.23.0" "@opentelemetry/semantic-conventions" "1.23.0" +"@opentelemetry/resources@1.24.1": + version "1.24.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.24.1.tgz#5e2cb84814824f3b1e1017e6caeeee8402e0ad6e" + integrity sha512-cyv0MwAaPF7O86x5hk3NNgenMObeejZFLJJDVuSeSMIsknlsj3oOZzRv3qSzlwYomXsICfBeFFlxwHQte5mGXQ== + dependencies: + "@opentelemetry/core" "1.24.1" + "@opentelemetry/semantic-conventions" "1.24.1" + +"@opentelemetry/sdk-logs@0.51.1": + version "0.51.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-logs/-/sdk-logs-0.51.1.tgz#8e4544e1034413ed2bd5e0741734d062c5e81c94" + integrity sha512-ULQQtl82b673PpZc5/0EtH4V+BrwVOgKJZEB7tYZnGTG3I98tQVk89S9/JSixomDr++F4ih+LSJTCqIKBz+MQQ== + dependencies: + "@opentelemetry/core" "1.24.1" + "@opentelemetry/resources" "1.24.1" + +"@opentelemetry/sdk-metrics@1.24.1": + version "1.24.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-metrics/-/sdk-metrics-1.24.1.tgz#82ee3069b2ca9bb7c1e91272ff81536dc2e9bc8d" + integrity sha512-FrAqCbbGao9iKI+Mgh+OsC9+U2YMoXnlDHe06yH7dvavCKzE3S892dGtX54+WhSFVxHR/TMRVJiK/CV93GR0TQ== + dependencies: + "@opentelemetry/core" "1.24.1" + "@opentelemetry/resources" "1.24.1" + lodash.merge "^4.6.2" + "@opentelemetry/sdk-trace-base@1.23.0": version "1.23.0" resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.23.0.tgz#ff0a0f8ec47205e0b14b3b765ea2a34de1ad01dd" @@ -1249,6 +1347,15 @@ "@opentelemetry/resources" "1.23.0" "@opentelemetry/semantic-conventions" "1.23.0" +"@opentelemetry/sdk-trace-base@1.24.1": + version "1.24.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.24.1.tgz#dc2ab89126e75e442913fb5af98803fde67b2536" + integrity sha512-zz+N423IcySgjihl2NfjBf0qw1RWe11XIAWVrTNOSSI6dtSPJiVom2zipFB2AEEtJWpv0Iz6DY6+TjnyTV5pWg== + dependencies: + "@opentelemetry/core" "1.24.1" + "@opentelemetry/resources" "1.24.1" + "@opentelemetry/semantic-conventions" "1.24.1" + "@opentelemetry/sdk-trace-node@^1.23.0": version "1.23.0" resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.23.0.tgz#7787f32722e8c77774bfb8a31b88be03e2df0b0d" @@ -1266,6 +1373,11 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.23.0.tgz#627f2721b960fe586b7f72a07912cb7699f06eef" integrity sha512-MiqFvfOzfR31t8cc74CTP1OZfz7MbqpAnLCra8NqQoaHJX6ncIRTdYOQYBDQ2uFISDq0WY8Y9dDTWvsgzzBYRg== +"@opentelemetry/semantic-conventions@1.24.1": + version "1.24.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.1.tgz#d4bcebda1cb5146d47a2a53daaa7922f8e084dfb" + integrity sha512-VkliWlS4/+GHLLW7J/rVBA00uXus1SWvwFvcUDxDwmFxYfg/2VI6ekwdXS28cjI8Qz2ky2BzG8OUHo+WeYIWqw== + "@opentelemetry/semantic-conventions@^1.23.0": version "1.24.0" resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.0.tgz#f074db930a7feb4d64103a9a576c5fbad046fcac" @@ -6327,6 +6439,24 @@ proto-list@~1.2.1: resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== +protobufjs@^7.2.3, protobufjs@^7.2.5: + version "7.3.0" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.3.0.tgz#a32ec0422c039798c41a0700306a6e305b9cb32c" + integrity sha512-YWD03n3shzV9ImZRX3ccbjqLxj7NokGN0V/ESiBV5xWqrommYHYiihuIyavq03pWSGqlyvYUFmfoMKd+1rPA/g== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/node" ">=13.7.0" + long "^5.0.0" + protobufjs@^7.2.4: version "7.2.6" resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.2.6.tgz#4a0ccd79eb292717aacf07530a07e0ed20278215"