@loglayer/transport-new-relic
Version:
New Relic transport for the LogLayer logging library.
1 lines • 6.15 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","names":["HttpTransport"],"sources":["../src/NewRelicTransport.ts"],"sourcesContent":["import type { HttpTransportConfig } from \"@loglayer/transport-http\";\nimport { HttpTransport } from \"@loglayer/transport-http\";\n\n// Constants defining New Relic's API limits\nconst MAX_ATTRIBUTES = 255;\nconst MAX_ATTRIBUTE_NAME_LENGTH = 255;\nconst MAX_ATTRIBUTE_VALUE_LENGTH = 4094;\n\n/**\n * Error thrown when log entry validation fails.\n * This includes attribute count, attribute name length, and other New Relic API validations.\n */\nexport class ValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ValidationError\";\n }\n}\n\n/**\n * Configuration options for the New Relic transport.\n * Extends HttpTransportConfig with New Relic-specific options.\n */\nexport interface NewRelicTransportConfig extends Omit<HttpTransportConfig, \"url\" | \"headers\" | \"payloadTemplate\"> {\n /**\n * The New Relic API key\n */\n apiKey: string;\n /**\n * The New Relic Log API endpoint\n * @default \"https://log-api.newrelic.com/log/v1\"\n */\n endpoint?: string;\n /**\n * Custom payload template function (optional, defaults to New Relic format).\n * Receives log level, message, and optional data (metadata).\n */\n payloadTemplate?: (params: { logLevel: string; message: string; data?: Record<string, any> }) => string;\n}\n\n/**\n * Validates attributes against New Relic's constraints.\n * - Checks number of attributes (max 255)\n * - Validates attribute name length (max 255 characters)\n * - Truncates attribute values longer than 4094 characters\n *\n * @param attributes - The attributes to validate\n * @returns The validated (and potentially modified) attributes\n * @throws {ValidationError} If validation fails\n */\nfunction validateAttributes(attributes: Record<string, any>): Record<string, any> {\n const validated: Record<string, any> = {};\n\n // Check number of attributes\n const attributeCount = Object.keys(attributes).length;\n if (attributeCount > MAX_ATTRIBUTES) {\n throw new ValidationError(\n `Log entry exceeds maximum number of attributes (${MAX_ATTRIBUTES}). Found: ${attributeCount}`,\n );\n }\n\n // Check attribute names and values\n for (const [key, value] of Object.entries(attributes)) {\n // Check attribute name length\n if (key.length > MAX_ATTRIBUTE_NAME_LENGTH) {\n throw new ValidationError(\n `Attribute name exceeds maximum length (${MAX_ATTRIBUTE_NAME_LENGTH}). Found: ${key.length}`,\n );\n }\n\n // Truncate string values that are too long\n if (typeof value === \"string\" && value.length > MAX_ATTRIBUTE_VALUE_LENGTH) {\n validated[key] = value.slice(0, MAX_ATTRIBUTE_VALUE_LENGTH);\n } else {\n validated[key] = value;\n }\n }\n\n return validated;\n}\n\n/**\n * Default payload template that formats log data for New Relic's Log API.\n * Each entry includes timestamp, level, the log message, and optional attributes.\n */\nfunction defaultNewRelicPayload(params: { logLevel: string; message: string; data?: Record<string, any> }): string {\n const logEntry: Record<string, any> = {\n timestamp: Date.now(),\n level: params.logLevel,\n log: params.message,\n };\n\n if (params.data) {\n logEntry.attributes = validateAttributes(params.data);\n }\n\n return JSON.stringify(logEntry);\n}\n\n/**\n * NewRelicTransport is responsible for sending logs to New Relic's Log API.\n * It extends HttpTransport with New Relic-specific configuration, validation,\n * and formatting.\n *\n * Features:\n * - Validates attribute count (max 255)\n * - Validates attribute name length (max 255 characters)\n * - Truncates attribute values longer than 4094 characters\n * - Gzip compression by default (via HttpTransport)\n * - Retry logic with exponential backoff (via HttpTransport)\n * - Rate limiting support (via HttpTransport)\n * - Batch sending support (via HttpTransport)\n * - Error and debug callbacks\n */\nexport class NewRelicTransport extends HttpTransport {\n /**\n * Creates a new instance of NewRelicTransport.\n *\n * @param config - Configuration options for the transport\n */\n constructor(config: NewRelicTransportConfig) {\n const { apiKey, endpoint, payloadTemplate, ...httpConfig } = config;\n\n super({\n ...httpConfig,\n url: endpoint ?? \"https://log-api.newrelic.com/log/v1\",\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Api-Key\": apiKey,\n },\n payloadTemplate: payloadTemplate ?? defaultNewRelicPayload,\n // Defaults (only apply if not provided)\n compression: httpConfig.compression ?? true,\n maxRetries: httpConfig.maxRetries ?? 3,\n retryDelay: httpConfig.retryDelay ?? 1000,\n respectRateLimit: httpConfig.respectRateLimit ?? true,\n maxLogSize: httpConfig.maxLogSize ?? 1_048_576,\n maxPayloadSize: httpConfig.maxPayloadSize ?? 1_048_576,\n } as HttpTransportConfig);\n }\n}\n"],"mappings":";;;;AAIA,MAAM,iBAAiB;AACvB,MAAM,4BAA4B;AAClC,MAAM,6BAA6B;;;;;AAMnC,IAAa,kBAAb,cAAqC,MAAM;CACzC,YAAY,SAAiB;AAC3B,QAAM,QAAQ;AACd,OAAK,OAAO;;;;;;;;;;;;;AAmChB,SAAS,mBAAmB,YAAsD;CAChF,MAAM,YAAiC,EAAE;CAGzC,MAAM,iBAAiB,OAAO,KAAK,WAAW,CAAC;AAC/C,KAAI,iBAAiB,eACnB,OAAM,IAAI,gBACR,mDAAmD,eAAe,YAAY,iBAC/E;AAIH,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,WAAW,EAAE;AAErD,MAAI,IAAI,SAAS,0BACf,OAAM,IAAI,gBACR,0CAA0C,0BAA0B,YAAY,IAAI,SACrF;AAIH,MAAI,OAAO,UAAU,YAAY,MAAM,SAAS,2BAC9C,WAAU,OAAO,MAAM,MAAM,GAAG,2BAA2B;MAE3D,WAAU,OAAO;;AAIrB,QAAO;;;;;;AAOT,SAAS,uBAAuB,QAAmF;CACjH,MAAM,WAAgC;EACpC,WAAW,KAAK,KAAK;EACrB,OAAO,OAAO;EACd,KAAK,OAAO;EACb;AAED,KAAI,OAAO,KACT,UAAS,aAAa,mBAAmB,OAAO,KAAK;AAGvD,QAAO,KAAK,UAAU,SAAS;;;;;;;;;;;;;;;;;AAkBjC,IAAa,oBAAb,cAAuCA,uCAAc;;;;;;CAMnD,YAAY,QAAiC;EAC3C,MAAM,EAAE,QAAQ,UAAU,iBAAiB,GAAG,eAAe;AAE7D,QAAM;GACJ,GAAG;GACH,KAAK,YAAY;GACjB,QAAQ;GACR,SAAS;IACP,gBAAgB;IAChB,WAAW;IACZ;GACD,iBAAiB,mBAAmB;GAEpC,aAAa,WAAW,eAAe;GACvC,YAAY,WAAW,cAAc;GACrC,YAAY,WAAW,cAAc;GACrC,kBAAkB,WAAW,oBAAoB;GACjD,YAAY,WAAW,cAAc;GACrC,gBAAgB,WAAW,kBAAkB;GAC9C,CAAwB"}