From a4017d38c5572b94d8cec60e268313cd4754a1ba Mon Sep 17 00:00:00 2001 From: Harel Moshe Date: Wed, 4 Dec 2024 12:47:42 +0200 Subject: [PATCH] feat: more robust winston support (#552) --- package-lock.json | 107 +++++++++++++++--- package.json | 1 + src/utils.ts | 1 - .../instrumentations/winston/app/package.json | 9 +- .../winston/app/winston_app.js | 16 +-- .../winston/deps/package.json | 5 + test/instrumentations/winston/winston.test.ts | 35 +++--- 7 files changed, 125 insertions(+), 49 deletions(-) create mode 100644 test/instrumentations/winston/deps/package.json diff --git a/package-lock.json b/package-lock.json index ba39232b..cafc0a25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2592,6 +2592,14 @@ "shimmer": "^1.2.1" } }, + "@types/ioredis4": { + "version": "npm:@types/ioredis@4.28.10", + "resolved": "https://registry.npmjs.org/@types/ioredis/-/ioredis-4.28.10.tgz", + "integrity": "sha512-69LyhUgrXdgcNDv7ogs1qXZomnfOEnSmrmMFqKgt1XMJxmoOSG/u3wYy13yACIfKuMJ8IhKgHafDO3sx19zVQQ==", + "requires": { + "@types/node": "*" + } + }, "import-in-the-middle": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz", @@ -3103,6 +3111,25 @@ "@opentelemetry/core": "^1.1.0" } }, + "@opentelemetry/winston-transport": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/winston-transport/-/winston-transport-0.8.0.tgz", + "integrity": "sha512-NIUToAei4nSoZdwwSw2oK75gmdIc5iwSPOWS5S9n1vTjK+v+leja0h+55vQDnJC0QeZtkckmpoCxgBG3wJLJ8w==", + "requires": { + "@opentelemetry/api-logs": "^0.55.0", + "winston-transport": "4.*" + }, + "dependencies": { + "@opentelemetry/api-logs": { + "version": "0.55.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.55.0.tgz", + "integrity": "sha512-3cpa+qI45VHYcA5c0bHM6VHo9gicv3p5mlLHNG3rLyjQU8b7e0st1rWtrUn3JbZ3DwwCfhKop4eQ9UuYlC6Pkg==", + "requires": { + "@opentelemetry/api": "^1.3.0" + } + } + } + }, "@pnpm/config.env-replace": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", @@ -5373,14 +5400,6 @@ "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", "dev": true }, - "@types/ioredis4": { - "version": "npm:@types/ioredis@4.28.10", - "resolved": "https://registry.npmjs.org/@types/ioredis/-/ioredis-4.28.10.tgz", - "integrity": "sha512-69LyhUgrXdgcNDv7ogs1qXZomnfOEnSmrmMFqKgt1XMJxmoOSG/u3wYy13yACIfKuMJ8IhKgHafDO3sx19zVQQ==", - "requires": { - "@types/node": "*" - } - }, "@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", @@ -5586,6 +5605,11 @@ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true }, + "@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" + }, "@types/yargs": { "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", @@ -8351,6 +8375,11 @@ "bser": "2.1.1" } }, + "fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -8994,8 +9023,7 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { "version": "1.3.8", @@ -10933,6 +10961,26 @@ "log-prefix": "0.1.1" } }, + "logform": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", + "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", + "requires": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "dependencies": { + "@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==" + } + } + }, "long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", @@ -16228,6 +16276,11 @@ "is-regex": "^1.1.4" } }, + "safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==" + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -16764,7 +16817,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" }, @@ -16772,8 +16824,7 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, @@ -17118,6 +17169,11 @@ "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true }, + "triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==" + }, "ts-node": { "version": "9.1.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", @@ -17450,8 +17506,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "utils-merge": { "version": "1.0.1", @@ -17676,6 +17731,28 @@ "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", "dev": true }, + "winston-transport": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", + "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", + "requires": { + "logform": "^2.7.0", + "readable-stream": "^3.6.2", + "triple-beam": "^1.3.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", diff --git a/package.json b/package.json index 0a221954..151b8420 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "@opentelemetry/sdk-trace-base": "1.9.1", "@opentelemetry/sdk-trace-node": "1.9.1", "@opentelemetry/semantic-conventions": "1.17.1", + "@opentelemetry/winston-transport": "^0.8.0", "@prisma/instrumentation": "^4.14.0", "deasync": "^0.1.30", "opentelemetry-instrumentation-express": "0.39.1", diff --git a/src/utils.ts b/src/utils.ts index 7adf7a0c..f29d8e0c 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -4,7 +4,6 @@ import * as https from 'https'; import { logger } from './logging'; import { sortify } from './tools/jsonSortify'; -import path from 'path'; export const DEFAULT_ATTRIBUTE_VALUE_LENGTH_LIMIT = 2048; export const DEFAULT_CONNECTION_TIMEOUT = 5000; diff --git a/test/instrumentations/winston/app/package.json b/test/instrumentations/winston/app/package.json index 72c2e02b..c2a8f5f0 100644 --- a/test/instrumentations/winston/app/package.json +++ b/test/instrumentations/winston/app/package.json @@ -3,13 +3,8 @@ "version": "1.0.0", "description": "", "scripts": { - "start": "node -r @lumigo/opentelemetry winston_app.js" + "start": "node -r @lumigo/opentelemetry/sync winston_app.js" }, "author": "", - "license": "ISC", - "dependencies": { - "@lumigo/opentelemetry": "file:../../../../distro.tgz", - "@opentelemetry/winston-transport": "^0.2.0", - "winston": "^3.14.0" - } + "license": "ISC" } diff --git a/test/instrumentations/winston/app/winston_app.js b/test/instrumentations/winston/app/winston_app.js index 4dad838f..52b0fc8d 100644 --- a/test/instrumentations/winston/app/winston_app.js +++ b/test/instrumentations/winston/app/winston_app.js @@ -1,8 +1,10 @@ const http = require('http'); const url = require('url'); -const { init } = require("@lumigo/opentelemetry") +const winston = require('winston'); -require('log-timestamp'); +const winstonLogger = winston.createLogger({ + transports: [new winston.transports.Console()], +}) const host = 'localhost'; let httpServer; @@ -16,15 +18,7 @@ function respond(res, status, body) { } const requestListener = async function (req, res) { - await init; - - const winston = require('winston'); - const winstonLogger = winston.createLogger({ - transports: [new winston.transports.Console()], - }) - - console.error(`Received request: ${req.method} ${req.url}`); - + console.log(`Received request: ${req.method} ${req.url}`); const requestUrl = url.parse(req.url, true); switch (requestUrl.pathname) { diff --git a/test/instrumentations/winston/deps/package.json b/test/instrumentations/winston/deps/package.json new file mode 100644 index 00000000..19b0daee --- /dev/null +++ b/test/instrumentations/winston/deps/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@lumigo/opentelemetry": "file:./distro.tgz" + } +} \ No newline at end of file diff --git a/test/instrumentations/winston/winston.test.ts b/test/instrumentations/winston/winston.test.ts index af6c0aac..539c0066 100644 --- a/test/instrumentations/winston/winston.test.ts +++ b/test/instrumentations/winston/winston.test.ts @@ -1,28 +1,37 @@ -import fs from 'fs'; -import { join } from 'path'; +import path from 'path'; import { itTest } from '../../integration/setup'; import { TestApp } from '../../utils/test-apps'; -import { installPackage, reinstallPackages, uninstallPackage } from '../../utils/test-setup'; +import { installPackage, reinstallPackages } from '../../utils/test-setup'; import { versionsToTest } from '../../utils/versions'; import { FakeEdge } from '../../utils/fake-edge'; +import tmp from 'tmp'; +import fs from 'fs-extra'; const INSTRUMENTATION_NAME = 'winston'; -const LOGS_DIR = join(__dirname, 'logs'); -const TEST_APP_DIR = join(__dirname, 'app'); +const LOGS_DIR = path.join(__dirname, 'logs'); describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( `Instrumentation tests for the ${INSTRUMENTATION_NAME} package`, function (versionToTest) { let testApp: TestApp; const fakeEdge = new FakeEdge(); + let targetAppDir: string; beforeAll(async () => { await fakeEdge.start(); + await fs.mkdir(LOGS_DIR, { recursive: true }); + }); - reinstallPackages({ appDir: TEST_APP_DIR }); - fs.mkdirSync(LOGS_DIR, { recursive: true }); + beforeEach(async () => { + // copy the entire test project-root to a temp folder, to isolate dependencies + const sourceFolder = path.join(__dirname); + const targetTestProjectDir = tmp.dirSync({ keep: process.env.KEEP_TEMP_TEST_FOLDERS == "true" }).name; + targetAppDir = path.join(targetTestProjectDir, "app"); + await fs.copy(sourceFolder, targetTestProjectDir), + await fs.copy("distro.tgz", path.join(targetTestProjectDir, "deps", "distro.tgz")); + reinstallPackages({ appDir: path.join(targetTestProjectDir, "deps") }); installPackage({ - appDir: TEST_APP_DIR, + appDir: targetAppDir, packageName: INSTRUMENTATION_NAME, packageVersion: versionToTest, }); @@ -38,11 +47,6 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( afterAll(async () => { await fakeEdge.stop(); - uninstallPackage({ - appDir: TEST_APP_DIR, - packageName: INSTRUMENTATION_NAME, - packageVersion: versionToTest, - }); }); itTest( @@ -53,7 +57,7 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( timeout: 30_000, }, async function () { - testApp = new TestApp(TEST_APP_DIR, INSTRUMENTATION_NAME, { + testApp = new TestApp(targetAppDir, INSTRUMENTATION_NAME, { logDumpPath: `${LOGS_DIR}/${INSTRUMENTATION_NAME}.${INSTRUMENTATION_NAME}-logs@${versionToTest}.json`, env: { LUMIGO_ENABLE_LOGS: 'true', @@ -61,13 +65,14 @@ describe.each(versionsToTest(INSTRUMENTATION_NAME, INSTRUMENTATION_NAME))( LUMIGO_LOGS_ENDPOINT: fakeEdge.logsUrl, LUMIGO_ENDPOINT: fakeEdge.tracesUrl, LUMIGO_TRACER_TOKEN: 't_123456789', + NODE_PATH: path.join(targetAppDir, '..', "deps", "node_modules"), }, }); await writeLogLine('Hello Winston!'); await writeLogLine({ a: 1, sekret: 'this is secret!' }); - await expect(fakeEdge.waitFor(({ logs }) => logs.length === 2, 'waiting for logs to be processed')).toBeTruthy(); + await expect(fakeEdge.waitFor(({ logs }) => logs.length === 2, 'waiting for logs to be processed')).resolves.toBeTruthy(); await expect(fakeEdge.waitFor(({ resources }) => resources.length >= 1, 'waiting for resources to be processed')).resolves.toBeTruthy(); expect(fakeEdge.resources[0].attributes).toIncludeAllMembers([