diff --git a/.npmrc b/.npmrc new file mode 100644 index 000000000..f56badc3f --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +@mrge-group:registry=https://npm.pkg.github.com +//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN} diff --git a/src/handler.cjs b/src/handler.cjs index 641aea93d..34722b62e 100644 --- a/src/handler.cjs +++ b/src/handler.cjs @@ -7,15 +7,17 @@ const { } = require("./index.js"); const { logDebug, logError } = require("./utils/index.js"); const { loadSync } = require("./runtime/index.js"); -const { initTracer } = require("./runtime/module_importer"); +const { loadTracer } = require("./runtime/module_importer.js"); +const { initTracer } = require("./trace/index.js") if (process.env.DD_TRACE_DISABLED_PLUGINS === undefined) { process.env.DD_TRACE_DISABLED_PLUGINS = "fs"; logDebug("disabled the dd-trace plugin 'fs'"); } +const tracer = loadTracer(); if (getEnvValue("DD_TRACE_ENABLED", "true").toLowerCase() === "true") { - initTracer(); + initTracer(tracer); } const taskRootEnv = getEnvValue(lambdaTaskRootEnvVar, ""); @@ -32,4 +34,4 @@ if (extractorEnv) { } } -exports.handler = datadog(loadSync(taskRootEnv, handlerEnv), { traceExtractor }); +exports.handler = datadog(loadSync(taskRootEnv, handlerEnv), tracer, { traceExtractor }); diff --git a/src/handler.mjs b/src/handler.mjs index 2db66c2d1..1ce084d20 100644 --- a/src/handler.mjs +++ b/src/handler.mjs @@ -1,15 +1,17 @@ import { datadog, datadogHandlerEnvVar, lambdaTaskRootEnvVar, traceExtractorEnvVar, getEnvValue } from "./index.js"; import { logDebug, logError } from "./utils/index.js"; import { load } from "./runtime/index.js"; -import { initTracer } from "./runtime/module_importer.js"; +import { loadTracer } from "./runtime/module_importer.js"; +import { initTracer } from "./trace/index.js"; if (process.env.DD_TRACE_DISABLED_PLUGINS === undefined) { process.env.DD_TRACE_DISABLED_PLUGINS = "fs"; logDebug("disabled the dd-trace plugin 'fs'"); } +const tracer = loadTracer(); if (getEnvValue("DD_TRACE_ENABLED", "true").toLowerCase() === "true") { - initTracer(); + initTracer(tracer); } const taskRootEnv = getEnvValue(lambdaTaskRootEnvVar, ""); @@ -26,4 +28,4 @@ if (extractorEnv) { } } -export const handler = datadog(await load(taskRootEnv, handlerEnv), { traceExtractor }); +export const handler = datadog(await load(taskRootEnv, handlerEnv), tracer, { traceExtractor }); diff --git a/src/index.ts b/src/index.ts index bcca75221..6363b2518 100644 --- a/src/index.ts +++ b/src/index.ts @@ -21,9 +21,11 @@ import { } from "./utils"; import { getEnhancedMetricTags } from "./metrics/enhanced-metrics"; import { DatadogTraceHeaders } from "./trace/context/extractor"; +import {Tracer} from "dd-trace"; // Backwards-compatible export, TODO deprecate in next major export { DatadogTraceHeaders as TraceHeaders } from "./trace/context/extractor"; +export { initTracer } from "./trace"; export const apiKeyEnvVar = "DD_API_KEY"; export const apiKeyKMSEnvVar = "DD_KMS_API_KEY"; export const captureLambdaPayloadEnvVar = "DD_CAPTURE_LAMBDA_PAYLOAD"; @@ -98,6 +100,7 @@ const initTime = Date.now(); /** * Wraps your AWS lambda handler functions to add tracing/metrics support * @param handler A lambda handler function. + * @param tracer The tracer to be used. * @param config Configuration options for datadog. * @returns A wrapped handler function. * @@ -109,12 +112,13 @@ const initTime = Date.now(); */ export function datadog( handler: Handler | any, + tracer: Tracer, config?: Partial, ): Handler | any { const finalConfig = getConfig(config); const metricsListener = new MetricsListener(new KMSService(), finalConfig); - const traceListener = new TraceListener(finalConfig); + const traceListener = new TraceListener(tracer, finalConfig); // Only wrap the handler once unless forced const _ddWrappedKey = "_ddWrapped"; diff --git a/src/runtime/module_importer.js b/src/runtime/module_importer.js index 0ee71f471..2187f30eb 100644 --- a/src/runtime/module_importer.js +++ b/src/runtime/module_importer.js @@ -7,21 +7,17 @@ exports.import = function (path) { return import(path); } -exports.initTracer = function () { - // Looks for the function local version of dd-trace first, before using - // the version provided by the layer - const path = require.resolve("dd-trace", { paths: ["/var/task/node_modules", ...module.paths] }); - // tslint:disable-next-line:no-var-requires - const tracer = require(path).init({ - tags: { - "_dd.origin": "lambda", - }, - }); - logDebug("automatically initialized dd-trace"); - - // Configure the tracer to ignore HTTP calls made from the Lambda Library to the Extension - tracer.use("http", { - blocklist: /:8124\/lambda/, - }); - return tracer; +exports.loadTracer = function () { + try { + // Looks for the function local version of dd-trace first, before using + // the version provided by the layer + const path = require.resolve("dd-trace", { paths: ["/var/task/node_modules", ...module.paths] }); + // tslint:disable-next-line:no-var-requires + return require(path); + } catch (err) { + if (err instanceof Object || err instanceof Error) { + logDebug("Couldn't require dd-trace from main", err); + } + } + return undefined; } diff --git a/src/runtime/user-function.ts b/src/runtime/user-function.ts index 5071238fa..b1454e3d3 100644 --- a/src/runtime/user-function.ts +++ b/src/runtime/user-function.ts @@ -19,6 +19,8 @@ import { ImportModuleError, UserCodeSyntaxError, } from "./errors"; +import {logDebug} from "../utils"; +import {Tracer} from "dd-trace"; const module_importer = require("./module_importer"); const FUNCTION_EXPR = /^([^.]*)\.(.*)$/; diff --git a/src/trace/index.ts b/src/trace/index.ts index 74fbf13ce..cd2c1d9a8 100644 --- a/src/trace/index.ts +++ b/src/trace/index.ts @@ -1,2 +1,3 @@ export { TraceConfig, TraceListener, TraceExtractor } from "./listener"; export { DatadogTraceHeaders } from "./context/extractor"; +export { initTracer } from "./tracer-wrapper"; diff --git a/src/trace/listener.ts b/src/trace/listener.ts index 7456813a0..80ff93aa9 100644 --- a/src/trace/listener.ts +++ b/src/trace/listener.ts @@ -18,6 +18,7 @@ import { TraceContext, TraceContextService, TraceSource } from "./trace-context- import { StepFunctionContext, StepFunctionContextService } from "./step-function-service"; import { XrayService } from "./xray-service"; import { AUTHORIZING_REQUEST_ID_HEADER } from "./context/extractors/http"; +import {Tracer} from "dd-trace"; export type TraceExtractor = (event: any, context: Context) => Promise | TraceContext; export interface TraceConfig { @@ -80,8 +81,8 @@ export class TraceListener { return this.contextService.currentTraceHeaders; } - constructor(private config: TraceConfig) { - this.tracerWrapper = new TracerWrapper(); + constructor(private readonly tracer: Tracer, private config: TraceConfig) { + this.tracerWrapper = new TracerWrapper(tracer); this.contextService = new TraceContextService(this.tracerWrapper, this.config); this.inferrer = new SpanInferrer(this.tracerWrapper); } diff --git a/src/trace/tracer-wrapper.ts b/src/trace/tracer-wrapper.ts index 78cb6b49c..1d49ce766 100644 --- a/src/trace/tracer-wrapper.ts +++ b/src/trace/tracer-wrapper.ts @@ -1,6 +1,7 @@ import { logDebug } from "../utils"; import { SpanContextWrapper } from "./span-context-wrapper"; import { TraceSource } from "./trace-context-service"; +import {Tracer} from "dd-trace"; export interface SpanContext { toTraceId(): string; @@ -23,24 +24,28 @@ export interface TraceOptions { childOf?: SpanContext; } +export function initTracer(tracer: Tracer): Tracer { + tracer.init({ + tags: { + "_dd.origin": "lambda", + }, + }); + logDebug("automatically initialized dd-trace"); + + // Configure the tracer to ignore HTTP calls made from the Lambda Library to the Extension + tracer.use("http", { + blocklist: /:8124\/lambda/, + }); + return tracer; +} + // TraceWrapper is used to remove dd-trace as a hard dependency from the npm package. // This lets a customer bring their own version of the tracer. export class TracerWrapper { - private tracer: any; - - constructor() { - try { - // Try and use the same version of the tracing library the user has installed. - // This handles edge cases where two versions of dd-trace are installed, one in the layer - // and one in the user's code. - const path = require.resolve("dd-trace", { paths: ["/var/task/node_modules", ...module.paths] }); - this.tracer = require(path); - return; - } catch (err) { - if (err instanceof Object || err instanceof Error) { - logDebug("Couldn't require dd-trace from main", err); - } - } + private readonly tracer: any; + + constructor(tracer: Tracer) { + this.tracer = tracer; } public get isTracerAvailable(): boolean {