From 0a1459417b9b509ec8f946c7f876a2612e284946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luismi=20Ram=C3=ADrez?= Date: Wed, 18 Jan 2023 12:22:09 +0100 Subject: [PATCH] Add instrumentationsLoaded as a helper Instead of calling `instrumentationsLoaded()` from a client property, add it as an isolated helper function so users' apps keep working if they haven't initialized the AppSignal client. --- ...ntelemetry-sdk-initialization-to-client.md | 4 ++-- package-lock.json | 4 ++-- src/__tests__/helpers.test.ts | 24 ++++++++++++++++++- src/client.ts | 3 ++- src/helpers.ts | 13 ++++++++++ 5 files changed, 42 insertions(+), 6 deletions(-) diff --git a/.changesets/add-opentelemetry-sdk-initialization-to-client.md b/.changesets/add-opentelemetry-sdk-initialization-to-client.md index 0e67de3c..be8ea954 100644 --- a/.changesets/add-opentelemetry-sdk-initialization-to-client.md +++ b/.changesets/add-opentelemetry-sdk-initialization-to-client.md @@ -3,7 +3,7 @@ bump: "patch" type: "add" --- -Add OpenTelemetry SDK initialization to client +Add OpenTelemetry SDK initialization helper function The OpenTelemetry instrumentations are loaded async, this is OK when users rely on automatic instrumentations, but for custom instrumentations -it might cause spans not to be reported. There's a new property in the client that contains the instrumentations registration that can be awaited for resolution before running any custom instrumentations. +it might cause spans not to be reported. There's a new helper function that contains the instrumentations registration that can be awaited for resolution before running any custom instrumentations. diff --git a/package-lock.json b/package-lock.json index 482d4108..ff56941c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@appsignal/nodejs", - "version": "3.0.2", + "version": "3.0.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@appsignal/nodejs", - "version": "3.0.2", + "version": "3.0.3", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/src/__tests__/helpers.test.ts b/src/__tests__/helpers.test.ts index 85c0ee63..f855d135 100644 --- a/src/__tests__/helpers.test.ts +++ b/src/__tests__/helpers.test.ts @@ -19,7 +19,8 @@ import { setNamespace, setRootName, setError, - sendError + sendError, + instrumentationsLoaded } from "../helpers" function throwError() { @@ -286,4 +287,25 @@ describe("Helpers", () => { expect(debugMock).not.toHaveBeenCalled() }) }) + + describe("instrumentationsLoaded", () => { + it("returns a promise from the globally stored client if found", () => { + const debugMock = jest.spyOn(Client.integrationLogger, "debug") + + expect(instrumentationsLoaded()).toBeInstanceOf(Promise) + expect(debugMock).toHaveBeenCalledTimes(0) + }) + + it("returns an empty promise and logs if the globally stored client is not found", () => { + // Remove the stored client + global.__APPSIGNAL__ = null as any + + const debugMock = jest.spyOn(Client.integrationLogger, "debug") + + expect(instrumentationsLoaded()).toBeInstanceOf(Promise) + expect(debugMock).toHaveBeenCalledWith( + "Client is not initialized, cannot get OpenTelemetry instrumentations loaded" + ) + }) + }) }) diff --git a/src/client.ts b/src/client.ts index 264b39bc..b9f09406 100644 --- a/src/client.ts +++ b/src/client.ts @@ -93,7 +93,7 @@ export class Client { config: Configuration readonly integrationLogger: IntegrationLogger extension: Extension - instrumentationsLoaded?: Promise + instrumentationsLoaded: Promise #metrics: Metrics #sdk?: NodeSDK @@ -141,6 +141,7 @@ export class Client { this.config = new Configuration(options) this.extension = new Extension() this.integrationLogger = this.setUpIntegrationLogger() + this.instrumentationsLoaded = Promise.resolve() this.storeInGlobal() if (this.isActive) { diff --git a/src/helpers.ts b/src/helpers.ts index 2a497b6c..7d4b0cd0 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -128,3 +128,16 @@ export function sendError(error: Error, fn: () => void = () => {}) { ) } } + +export function instrumentationsLoaded(): Promise { + const globallyStoredClient = Client.client + + if (globallyStoredClient) { + return globallyStoredClient.instrumentationsLoaded + } else { + Client.integrationLogger.debug( + "Client is not initialized, cannot get OpenTelemetry instrumentations loaded" + ) + return Promise.resolve() + } +}