@agimon-ai/log-sink-mcp 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/node-Bu3xSfYZ.mjs +2 -0
- package/dist/node-Bu3xSfYZ.mjs.map +1 -0
- package/dist/node-fq51Liy5.cjs +2 -0
- package/dist/node-fq51Liy5.cjs.map +1 -0
- package/dist/telemetry/node.cjs +1 -1
- package/dist/telemetry/node.mjs +1 -1
- package/package.json +3 -3
- package/dist/node-BXUuvy4I.mjs +0 -2
- package/dist/node-BXUuvy4I.mjs.map +0 -1
- package/dist/node-DnZY4eWX.cjs +0 -2
- package/dist/node-DnZY4eWX.cjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(`./chunk-DjWAcSYV.cjs`),t=require(`./stdio-D-S2Mhwk.cjs`),n=require(`./node-
|
|
1
|
+
const e=require(`./chunk-DjWAcSYV.cjs`),t=require(`./stdio-D-S2Mhwk.cjs`),n=require(`./node-fq51Liy5.cjs`);let r=require(`@opentelemetry/api`),i=require(`@opentelemetry/api-logs`);exports.StdioTransportHandler=t.t,exports.createNodeTelemetry=n.t,exports.createServer=t.n,exports.getLogSinkOtelEndpoint=n.n,exports.log=i.logs,exports.resolveLogSinkOtelEndpoint=n.r,exports.resolveLogSinkPort=n.i,exports.trace=r.trace;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e,t}from"./stdio-DSDgdLCE.mjs";import{
|
|
1
|
+
import{n as e,t}from"./stdio-DSDgdLCE.mjs";import{a as n,i as r,n as i,o as a,r as o,t as s}from"./node-Bu3xSfYZ.mjs";export{t as StdioTransportHandler,s as createNodeTelemetry,e as createServer,i as getLogSinkOtelEndpoint,o as log,n as resolveLogSinkOtelEndpoint,a as resolveLogSinkPort,r as trace};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{existsSync as e}from"node:fs";import t from"node:path";import{DEFAULT_REGISTRY_PATH as n,PortRegistryService as r,normalizeRepositoryPath as i}from"@agimon-ai/foundation-port-registry";import{appendFile as a,mkdir as o,rename as s,stat as c}from"node:fs/promises";import{context as l,trace as u}from"@opentelemetry/api";import{SeverityNumber as d,logs as f}from"@opentelemetry/api-logs";import{OTLPLogExporter as p}from"@opentelemetry/exporter-logs-otlp-http";import{OTLPTraceExporter as m}from"@opentelemetry/exporter-trace-otlp-http";import{resourceFromAttributes as h}from"@opentelemetry/resources";import{BatchLogRecordProcessor as g,LoggerProvider as _}from"@opentelemetry/sdk-logs";import{BatchSpanProcessor as v,NodeTracerProvider as y}from"@opentelemetry/sdk-trace-node";const b=`log-sink-mcp-http`;async function x(e){let{env:t=process.env,workspaceRoot:a,healthCheck:o=!0}=e,s=t.PORT_REGISTRY_PATH??n,c=i(a),l=t.NODE_ENV||`development`,u=new r(s);try{let e=await u.getPort({repositoryPath:c,serviceName:b,serviceType:`tool`,environment:l});if(!e.success||!e.port)return;let t=e.record?.host??`127.0.0.1`,n=`http://${t}:${e.port}`;if(!o)return{port:e.port,host:t,endpoint:n};try{let r=await fetch(`${n}/health`);if(!r.ok)return;let i=await r.json();return i.status!==`healthy`||i.serviceName!==b&&i.service!==b?void 0:{port:e.port,host:t,endpoint:n}}catch{return}}catch{return}}async function S(e){return(await x(e))?.endpoint}const C=[`pnpm-workspace.yaml`,`nx.json`,`.git`],w=t.join(`logs`,`telemetry`);function T(n=process.cwd()){let r=t.resolve(n);for(;;){for(let n of C)if(e(t.join(r,n)))return r;let n=t.dirname(r);if(n===r)return process.cwd();r=n}}function E(n){return e(t.join(n,`packages/mcp/log-sink-mcp/package.json`))}async function D(e){return S(e)}function O(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return n.endsWith(`/v1/${t}/`)||n.endsWith(`/v1/${t}`)?e:new URL(`v1/${t}`,n).toString()}function k(e){return typeof e==`string`||typeof e==`number`||typeof e==`boolean`?e:e==null?``:JSON.stringify(e)}function A(e){if(!e)return;let t={};for(let[n,r]of Object.entries(e))r!=null&&(t[n]=k(r));return Object.keys(t).length>0?t:void 0}function j(){let e=u.getSpan(l.active());if(!e)return{};let t=e.spanContext();return{traceId:t.traceId,spanId:t.spanId}}function M(e,t,n={}){let r=u.getSpan(n.context??l.active())?.spanContext();return JSON.stringify({timestamp:new Date().toISOString(),level:e,message:t,traceId:r?.traceId,spanId:r?.spanId,attributes:n.attributes?A(n.attributes):void 0,exception:n.exception instanceof Error?{name:n.exception.name,message:n.exception.message,stack:n.exception.stack}:n.exception})}var N=class{pending=Promise.resolve();constructor(e){this.options=e}write(e,t,n){this.pending=this.pending.then(async()=>{let r=`${M(e,t,n)}\n`;await this.ensureDirectory(),await this.rotateIfNeeded(Buffer.byteLength(r)),await a(this.options.filePath,r,`utf8`)}).catch(e=>{console.error(`[log-sink-mcp telemetry] Failed to write log file ${this.options.filePath}:`,e)})}async flush(){await this.pending}async shutdown(){await this.flush()}async ensureDirectory(){await o(t.dirname(this.options.filePath),{recursive:!0})}async rotateIfNeeded(t){let n=0;try{n=(await c(this.options.filePath)).size}catch{n=0}if(!(n+t<=this.options.maxFileSizeBytes)){for(let t=this.options.maxFileCount-1;t>=1;--t){let n=`${this.options.filePath}.${t}`,r=`${this.options.filePath}.${t+1}`;e(n)&&await s(n,r).catch(()=>void 0)}e(this.options.filePath)&&await s(this.options.filePath,`${this.options.filePath}.1`).catch(()=>void 0)}}};function P(e,t){return{trace(t,n){e.emit({severityNumber:d.TRACE,severityText:`TRACE`,body:t,attributes:A(n?.attributes),context:n?.context??l.active(),exception:n?.exception})},debug(t,n){e.emit({severityNumber:d.DEBUG,severityText:`DEBUG`,body:t,attributes:A(n?.attributes),context:n?.context??l.active(),exception:n?.exception})},info(t,n){e.emit({severityNumber:d.INFO,severityText:`INFO`,body:t,attributes:A(n?.attributes),context:n?.context??l.active(),exception:n?.exception})},warn(t,n){e.emit({severityNumber:d.WARN,severityText:`WARN`,body:t,attributes:A(n?.attributes),context:n?.context??l.active(),exception:n?.exception})},error(t,n){e.emit({severityNumber:d.ERROR,severityText:`ERROR`,body:t,attributes:A(n?.attributes),context:n?.context??l.active(),exception:n?.exception})},fatal(t,n){e.emit({severityNumber:d.FATAL,severityText:`FATAL`,body:t,attributes:A(n?.attributes),context:n?.context??l.active(),exception:n?.exception})},getTraceContext:j,flush:t.flush,shutdown:t.shutdown}}function F(e){return{trace(t,n){e.write(`trace`,t,n)},debug(t,n){e.write(`debug`,t,n)},info(t,n){e.write(`info`,t,n)},warn(t,n){e.write(`warn`,t,n)},error(t,n){e.write(`error`,t,n)},fatal(t,n){e.write(`fatal`,t,n)},getTraceContext:j,flush:()=>e.flush(),shutdown:()=>e.shutdown()}}async function I(e){let n=e.env??process.env,r=e.workspaceRoot??T(process.cwd()),i=e.serviceName,a=e.serviceVersion??n.npm_package_version,o=e.enableTraces!==!1,s=e.enableLogs!==!1,c=e.maxFileSizeBytes??Number(n.LOG_SINK_FILE_MAX_BYTES??10485760),l=e.maxFileCount??Number(n.LOG_SINK_FILE_MAX_FILES??5),d=e.logDir??t.join(r,w),b=e.logFileName??`${i}.jsonl`,x=t.join(d,b),S=E(r)?await D({env:n,workspaceRoot:r}):void 0;if(S){let e={"service.name":i};a&&(e[`service.version`]=a);let t=h(e),n=o?new y({resource:t,spanProcessors:[new v(new m({url:O(S,`traces`)}))]}):void 0;n?.register();let r=s?new _({resource:t,processors:[new g(new p({url:O(S,`logs`)}))]}):void 0;r&&f.setGlobalLoggerProvider(r);let d=r?.getLogger(i,a);return{backend:`logsink`,enabled:!0,trace:u,log:f,logger:d?P(d,{flush:async()=>{await Promise.allSettled([n?.forceFlush(),r?.forceFlush()])},shutdown:async()=>{await Promise.allSettled([n?.shutdown(),r?.shutdown()])}}):F(new N({filePath:x,maxFileSizeBytes:c,maxFileCount:l})),endpoint:S,flush:async()=>{await Promise.allSettled([n?.forceFlush(),r?.forceFlush()])},shutdown:async()=>{await Promise.allSettled([n?.shutdown(),r?.shutdown()])}}}let C=new N({filePath:x,maxFileSizeBytes:c,maxFileCount:l});return{backend:`file`,enabled:!0,trace:u,log:f,logger:F(C),filePath:x,flush:()=>C.flush(),shutdown:()=>C.shutdown()}}export{S as a,u as i,D as n,x as o,f as r,I as t};
|
|
2
|
+
//# sourceMappingURL=node-Bu3xSfYZ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-Bu3xSfYZ.mjs","names":["sanitized: Attributes","options: FileSinkOptions","resourceAttributes: Attributes"],"sources":["../src/utils/resolveLogSinkPort.ts","../src/telemetry/node.ts"],"sourcesContent":["import {\n DEFAULT_REGISTRY_PATH,\n PortRegistryService,\n normalizeRepositoryPath,\n} from '@agimon-ai/foundation-port-registry';\n\nconst LOG_SINK_SERVICE_NAME = 'log-sink-mcp-http';\n\nexport interface LogSinkPortResult {\n port: number;\n host: string;\n endpoint: string;\n}\n\nexport interface ResolveLogSinkPortOptions {\n env?: NodeJS.ProcessEnv;\n workspaceRoot: string;\n healthCheck?: boolean;\n}\n\nexport async function resolveLogSinkPort(options: ResolveLogSinkPortOptions): Promise<LogSinkPortResult | undefined> {\n const { env = process.env, workspaceRoot, healthCheck = true } = options;\n const registryPath = env.PORT_REGISTRY_PATH ?? DEFAULT_REGISTRY_PATH;\n const repositoryPath = normalizeRepositoryPath(workspaceRoot);\n const environment = env.NODE_ENV || 'development';\n const portRegistry = new PortRegistryService(registryPath);\n\n try {\n const result = await portRegistry.getPort({\n repositoryPath,\n serviceName: LOG_SINK_SERVICE_NAME,\n serviceType: 'tool',\n environment,\n });\n\n if (!result.success || !result.port) {\n return undefined;\n }\n\n const host = result.record?.host ?? '127.0.0.1';\n const endpoint = `http://${host}:${result.port}`;\n\n if (!healthCheck) {\n return { port: result.port, host, endpoint };\n }\n\n try {\n const health = await fetch(`${endpoint}/health`);\n if (!health.ok) {\n return undefined;\n }\n\n const payload = (await health.json()) as { status?: string; serviceName?: string; service?: string };\n if (payload.status !== 'healthy') {\n return undefined;\n }\n\n if (payload.serviceName !== LOG_SINK_SERVICE_NAME && payload.service !== LOG_SINK_SERVICE_NAME) {\n return undefined;\n }\n\n return { port: result.port, host, endpoint };\n } catch {\n return undefined;\n }\n } catch {\n return undefined;\n }\n}\n\nexport async function resolveLogSinkOtelEndpoint(options: ResolveLogSinkPortOptions): Promise<string | undefined> {\n const result = await resolveLogSinkPort(options);\n return result?.endpoint;\n}\n","import { existsSync } from 'node:fs';\nimport { appendFile, mkdir, rename, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport { context, trace, type Attributes, type Context } from '@opentelemetry/api';\nimport { logs, SeverityNumber, type Logger as OtelLogger } from '@opentelemetry/api-logs';\nimport { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';\nimport { resourceFromAttributes } from '@opentelemetry/resources';\nimport { BatchLogRecordProcessor, LoggerProvider } from '@opentelemetry/sdk-logs';\nimport { BatchSpanProcessor, NodeTracerProvider } from '@opentelemetry/sdk-trace-node';\nimport { resolveLogSinkOtelEndpoint } from '../utils/resolveLogSinkPort.js';\n\nconst WORKSPACE_MARKERS = ['pnpm-workspace.yaml', 'nx.json', '.git'];\nconst DEFAULT_LOG_DIR = path.join('logs', 'telemetry');\nconst DEFAULT_MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024;\nconst DEFAULT_MAX_FILE_COUNT = 5;\n\nexport type TelemetryLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\nexport interface NodeTelemetryLogOptions {\n attributes?: Attributes;\n context?: Context;\n exception?: unknown;\n}\n\nexport interface NodeTelemetryLogger {\n trace(message: string, options?: NodeTelemetryLogOptions): void;\n debug(message: string, options?: NodeTelemetryLogOptions): void;\n info(message: string, options?: NodeTelemetryLogOptions): void;\n warn(message: string, options?: NodeTelemetryLogOptions): void;\n error(message: string, options?: NodeTelemetryLogOptions): void;\n fatal(message: string, options?: NodeTelemetryLogOptions): void;\n getTraceContext(): { traceId?: string; spanId?: string };\n flush(): Promise<void>;\n shutdown(): Promise<void>;\n}\n\nexport interface NodeTelemetryOptions {\n env?: NodeJS.ProcessEnv;\n serviceName: string;\n serviceVersion?: string;\n workspaceRoot?: string;\n enableTraces?: boolean;\n enableLogs?: boolean;\n logDir?: string;\n logFileName?: string;\n maxFileSizeBytes?: number;\n maxFileCount?: number;\n}\n\nexport interface NodeTelemetryHandle {\n backend: 'logsink' | 'file';\n enabled: boolean;\n trace: typeof trace;\n log: typeof logs;\n logger: NodeTelemetryLogger;\n endpoint?: string;\n filePath?: string;\n flush(): Promise<void>;\n shutdown(): Promise<void>;\n}\n\ninterface FileSinkOptions {\n filePath: string;\n maxFileSizeBytes: number;\n maxFileCount: number;\n}\n\nfunction resolveWorkspaceRoot(startPath = process.cwd()): string {\n let currentDir = path.resolve(startPath);\n\n while (true) {\n for (const marker of WORKSPACE_MARKERS) {\n if (existsSync(path.join(currentDir, marker))) {\n return currentDir;\n }\n }\n\n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) {\n return process.cwd();\n }\n\n currentDir = parentDir;\n }\n}\n\nfunction isLogSinkWorkspaceSupported(workspaceRoot: string): boolean {\n return existsSync(path.join(workspaceRoot, 'packages/mcp/log-sink-mcp/package.json'));\n}\n\nexport async function getLogSinkOtelEndpoint(options: {\n env?: NodeJS.ProcessEnv;\n workspaceRoot: string;\n healthCheck?: boolean;\n}): Promise<string | undefined> {\n return resolveLogSinkOtelEndpoint(options);\n}\n\nfunction withSignalPath(baseUrl: string, signal: 'traces' | 'logs'): string {\n const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;\n if (normalizedBaseUrl.endsWith(`/v1/${signal}/`) || normalizedBaseUrl.endsWith(`/v1/${signal}`)) {\n return baseUrl;\n }\n\n return new URL(`v1/${signal}`, normalizedBaseUrl).toString();\n}\n\nfunction toAttributeValue(value: unknown): string | number | boolean {\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return value;\n }\n\n if (value == null) {\n return '';\n }\n\n return JSON.stringify(value);\n}\n\nfunction sanitizeAttributes(attributes?: Attributes): Attributes | undefined {\n if (!attributes) {\n return undefined;\n }\n\n const sanitized: Attributes = {};\n for (const [key, value] of Object.entries(attributes)) {\n if (value === undefined || value === null) {\n continue;\n }\n\n sanitized[key] = toAttributeValue(value);\n }\n\n return Object.keys(sanitized).length > 0 ? sanitized : undefined;\n}\n\nfunction mapSeverity(level: TelemetryLevel): SeverityNumber {\n switch (level) {\n case 'trace':\n return SeverityNumber.TRACE;\n case 'debug':\n return SeverityNumber.DEBUG;\n case 'info':\n return SeverityNumber.INFO;\n case 'warn':\n return SeverityNumber.WARN;\n case 'error':\n return SeverityNumber.ERROR;\n case 'fatal':\n return SeverityNumber.FATAL;\n }\n}\n\nfunction getActiveSpanContext(): { traceId?: string; spanId?: string } {\n const activeSpan = trace.getSpan(context.active());\n if (!activeSpan) {\n return {};\n }\n\n const spanContext = activeSpan.spanContext();\n return {\n traceId: spanContext.traceId,\n spanId: spanContext.spanId,\n };\n}\n\nfunction serializeLogRecord(level: TelemetryLevel, message: string, options: NodeTelemetryLogOptions = {}): string {\n const activeSpan = trace.getSpan(options.context ?? context.active());\n const spanContext = activeSpan?.spanContext();\n\n return JSON.stringify({\n timestamp: new Date().toISOString(),\n level,\n message,\n traceId: spanContext?.traceId,\n spanId: spanContext?.spanId,\n attributes: options.attributes ? sanitizeAttributes(options.attributes) : undefined,\n exception:\n options.exception instanceof Error\n ? { name: options.exception.name, message: options.exception.message, stack: options.exception.stack }\n : options.exception,\n });\n}\n\nclass RotatingFileSink {\n private pending: Promise<void> = Promise.resolve();\n\n constructor(private readonly options: FileSinkOptions) {}\n\n write(level: TelemetryLevel, message: string, options?: NodeTelemetryLogOptions): void {\n this.pending = this.pending\n .then(async () => {\n const entry = `${serializeLogRecord(level, message, options)}\\n`;\n await this.ensureDirectory();\n await this.rotateIfNeeded(Buffer.byteLength(entry));\n await appendFile(this.options.filePath, entry, 'utf8');\n })\n .catch((error) => {\n console.error(`[log-sink-mcp telemetry] Failed to write log file ${this.options.filePath}:`, error);\n });\n }\n\n async flush(): Promise<void> {\n await this.pending;\n }\n\n async shutdown(): Promise<void> {\n await this.flush();\n }\n\n private async ensureDirectory(): Promise<void> {\n await mkdir(path.dirname(this.options.filePath), { recursive: true });\n }\n\n private async rotateIfNeeded(incomingBytes: number): Promise<void> {\n let currentSize = 0;\n try {\n currentSize = (await stat(this.options.filePath)).size;\n } catch {\n currentSize = 0;\n }\n\n if (currentSize + incomingBytes <= this.options.maxFileSizeBytes) {\n return;\n }\n\n for (let index = this.options.maxFileCount - 1; index >= 1; index -= 1) {\n const source = `${this.options.filePath}.${index}`;\n const target = `${this.options.filePath}.${index + 1}`;\n if (existsSync(source)) {\n await rename(source, target).catch(() => undefined);\n }\n }\n\n if (existsSync(this.options.filePath)) {\n await rename(this.options.filePath, `${this.options.filePath}.1`).catch(() => undefined);\n }\n }\n}\n\nfunction createOtelLogger(\n logger: OtelLogger,\n sink: { flush(): Promise<void>; shutdown(): Promise<void> },\n): NodeTelemetryLogger {\n return {\n trace(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.TRACE,\n severityText: 'TRACE',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n debug(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.DEBUG,\n severityText: 'DEBUG',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n info(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.INFO,\n severityText: 'INFO',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n warn(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.WARN,\n severityText: 'WARN',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n error(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.ERROR,\n severityText: 'ERROR',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n fatal(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.FATAL,\n severityText: 'FATAL',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n getTraceContext: getActiveSpanContext,\n flush: sink.flush,\n shutdown: sink.shutdown,\n };\n}\n\nfunction createFileLogger(sink: RotatingFileSink): NodeTelemetryLogger {\n return {\n trace(message, options) {\n sink.write('trace', message, options);\n },\n debug(message, options) {\n sink.write('debug', message, options);\n },\n info(message, options) {\n sink.write('info', message, options);\n },\n warn(message, options) {\n sink.write('warn', message, options);\n },\n error(message, options) {\n sink.write('error', message, options);\n },\n fatal(message, options) {\n sink.write('fatal', message, options);\n },\n getTraceContext: getActiveSpanContext,\n flush: () => sink.flush(),\n shutdown: () => sink.shutdown(),\n };\n}\n\nexport async function createNodeTelemetry(options: NodeTelemetryOptions): Promise<NodeTelemetryHandle> {\n const env = options.env ?? process.env;\n const workspaceRoot = options.workspaceRoot ?? resolveWorkspaceRoot(process.cwd());\n const serviceName = options.serviceName;\n const serviceVersion = options.serviceVersion ?? env.npm_package_version;\n const enableTraces = options.enableTraces !== false;\n const enableLogs = options.enableLogs !== false;\n const maxFileSizeBytes =\n options.maxFileSizeBytes ?? Number(env.LOG_SINK_FILE_MAX_BYTES ?? DEFAULT_MAX_FILE_SIZE_BYTES);\n const maxFileCount = options.maxFileCount ?? Number(env.LOG_SINK_FILE_MAX_FILES ?? DEFAULT_MAX_FILE_COUNT);\n const logDir = options.logDir ?? path.join(workspaceRoot, DEFAULT_LOG_DIR);\n const logFileName = options.logFileName ?? `${serviceName}.jsonl`;\n const filePath = path.join(logDir, logFileName);\n\n const sinkEndpoint = isLogSinkWorkspaceSupported(workspaceRoot)\n ? await getLogSinkOtelEndpoint({ env, workspaceRoot })\n : undefined;\n if (sinkEndpoint) {\n const resourceAttributes: Attributes = {\n 'service.name': serviceName,\n };\n if (serviceVersion) {\n resourceAttributes['service.version'] = serviceVersion;\n }\n\n const resource = resourceFromAttributes(resourceAttributes);\n const tracerProvider = enableTraces\n ? new NodeTracerProvider({\n resource,\n spanProcessors: [\n new BatchSpanProcessor(\n new OTLPTraceExporter({\n url: withSignalPath(sinkEndpoint, 'traces'),\n }),\n ),\n ],\n })\n : undefined;\n tracerProvider?.register();\n\n const loggerProvider = enableLogs\n ? new LoggerProvider({\n resource,\n processors: [\n new BatchLogRecordProcessor(\n new OTLPLogExporter({\n url: withSignalPath(sinkEndpoint, 'logs'),\n }),\n ),\n ],\n })\n : undefined;\n if (loggerProvider) {\n logs.setGlobalLoggerProvider(loggerProvider);\n }\n\n const sinkLogger = loggerProvider?.getLogger(serviceName, serviceVersion);\n const logger = sinkLogger\n ? createOtelLogger(sinkLogger, {\n flush: async () => {\n await Promise.allSettled([tracerProvider?.forceFlush(), loggerProvider?.forceFlush()]);\n },\n shutdown: async () => {\n await Promise.allSettled([tracerProvider?.shutdown(), loggerProvider?.shutdown()]);\n },\n })\n : createFileLogger(\n new RotatingFileSink({\n filePath,\n maxFileSizeBytes,\n maxFileCount,\n }),\n );\n\n return {\n backend: 'logsink',\n enabled: true,\n trace,\n log: logs,\n logger,\n endpoint: sinkEndpoint,\n flush: async () => {\n await Promise.allSettled([tracerProvider?.forceFlush(), loggerProvider?.forceFlush()]);\n },\n shutdown: async () => {\n await Promise.allSettled([tracerProvider?.shutdown(), loggerProvider?.shutdown()]);\n },\n };\n }\n\n const fileSink = new RotatingFileSink({\n filePath,\n maxFileSizeBytes,\n maxFileCount,\n });\n const logger = createFileLogger(fileSink);\n\n return {\n backend: 'file',\n enabled: true,\n trace,\n log: logs,\n logger,\n filePath,\n flush: () => fileSink.flush(),\n shutdown: () => fileSink.shutdown(),\n };\n}\n\nexport { trace, logs as log };\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`./chunk-DjWAcSYV.cjs`);let t=require(`node:fs`),n=require(`node:path`);n=e.t(n);let r=require(`@agimon-ai/foundation-port-registry`),i=require(`node:fs/promises`),a=require(`@opentelemetry/api`),o=require(`@opentelemetry/api-logs`),s=require(`@opentelemetry/exporter-logs-otlp-http`),c=require(`@opentelemetry/exporter-trace-otlp-http`),l=require(`@opentelemetry/resources`),u=require(`@opentelemetry/sdk-logs`),d=require(`@opentelemetry/sdk-trace-node`);const f=`log-sink-mcp-http`;async function p(e){let{env:t=process.env,workspaceRoot:n,healthCheck:i=!0}=e,a=t.PORT_REGISTRY_PATH??r.DEFAULT_REGISTRY_PATH,o=(0,r.normalizeRepositoryPath)(n),s=t.NODE_ENV||`development`,c=new r.PortRegistryService(a);try{let e=await c.getPort({repositoryPath:o,serviceName:f,serviceType:`tool`,environment:s});if(!e.success||!e.port)return;let t=e.record?.host??`127.0.0.1`,n=`http://${t}:${e.port}`;if(!i)return{port:e.port,host:t,endpoint:n};try{let r=await fetch(`${n}/health`);if(!r.ok)return;let i=await r.json();return i.status!==`healthy`||i.serviceName!==f&&i.service!==f?void 0:{port:e.port,host:t,endpoint:n}}catch{return}}catch{return}}async function m(e){return(await p(e))?.endpoint}const h=[`pnpm-workspace.yaml`,`nx.json`,`.git`],g=n.default.join(`logs`,`telemetry`),_=10*1024*1024,v=5;function y(e=process.cwd()){let r=n.default.resolve(e);for(;;){for(let e of h)if((0,t.existsSync)(n.default.join(r,e)))return r;let e=n.default.dirname(r);if(e===r)return process.cwd();r=e}}function b(e){return(0,t.existsSync)(n.default.join(e,`packages/mcp/log-sink-mcp/package.json`))}async function x(e){return m(e)}function S(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return n.endsWith(`/v1/${t}/`)||n.endsWith(`/v1/${t}`)?e:new URL(`v1/${t}`,n).toString()}function C(e){return typeof e==`string`||typeof e==`number`||typeof e==`boolean`?e:e==null?``:JSON.stringify(e)}function w(e){if(!e)return;let t={};for(let[n,r]of Object.entries(e))r!=null&&(t[n]=C(r));return Object.keys(t).length>0?t:void 0}function T(){let e=a.trace.getSpan(a.context.active());if(!e)return{};let t=e.spanContext();return{traceId:t.traceId,spanId:t.spanId}}function E(e,t,n={}){let r=a.trace.getSpan(n.context??a.context.active())?.spanContext();return JSON.stringify({timestamp:new Date().toISOString(),level:e,message:t,traceId:r?.traceId,spanId:r?.spanId,attributes:n.attributes?w(n.attributes):void 0,exception:n.exception instanceof Error?{name:n.exception.name,message:n.exception.message,stack:n.exception.stack}:n.exception})}var D=class{pending=Promise.resolve();constructor(e){this.options=e}write(e,t,n){this.pending=this.pending.then(async()=>{let r=`${E(e,t,n)}\n`;await this.ensureDirectory(),await this.rotateIfNeeded(Buffer.byteLength(r)),await(0,i.appendFile)(this.options.filePath,r,`utf8`)}).catch(e=>{console.error(`[log-sink-mcp telemetry] Failed to write log file ${this.options.filePath}:`,e)})}async flush(){await this.pending}async shutdown(){await this.flush()}async ensureDirectory(){await(0,i.mkdir)(n.default.dirname(this.options.filePath),{recursive:!0})}async rotateIfNeeded(e){let n=0;try{n=(await(0,i.stat)(this.options.filePath)).size}catch{n=0}if(!(n+e<=this.options.maxFileSizeBytes)){for(let e=this.options.maxFileCount-1;e>=1;--e){let n=`${this.options.filePath}.${e}`,r=`${this.options.filePath}.${e+1}`;(0,t.existsSync)(n)&&await(0,i.rename)(n,r).catch(()=>void 0)}(0,t.existsSync)(this.options.filePath)&&await(0,i.rename)(this.options.filePath,`${this.options.filePath}.1`).catch(()=>void 0)}}};function O(e,t){return{trace(t,n){e.emit({severityNumber:o.SeverityNumber.TRACE,severityText:`TRACE`,body:t,attributes:w(n?.attributes),context:n?.context??a.context.active(),exception:n?.exception})},debug(t,n){e.emit({severityNumber:o.SeverityNumber.DEBUG,severityText:`DEBUG`,body:t,attributes:w(n?.attributes),context:n?.context??a.context.active(),exception:n?.exception})},info(t,n){e.emit({severityNumber:o.SeverityNumber.INFO,severityText:`INFO`,body:t,attributes:w(n?.attributes),context:n?.context??a.context.active(),exception:n?.exception})},warn(t,n){e.emit({severityNumber:o.SeverityNumber.WARN,severityText:`WARN`,body:t,attributes:w(n?.attributes),context:n?.context??a.context.active(),exception:n?.exception})},error(t,n){e.emit({severityNumber:o.SeverityNumber.ERROR,severityText:`ERROR`,body:t,attributes:w(n?.attributes),context:n?.context??a.context.active(),exception:n?.exception})},fatal(t,n){e.emit({severityNumber:o.SeverityNumber.FATAL,severityText:`FATAL`,body:t,attributes:w(n?.attributes),context:n?.context??a.context.active(),exception:n?.exception})},getTraceContext:T,flush:t.flush,shutdown:t.shutdown}}function k(e){return{trace(t,n){e.write(`trace`,t,n)},debug(t,n){e.write(`debug`,t,n)},info(t,n){e.write(`info`,t,n)},warn(t,n){e.write(`warn`,t,n)},error(t,n){e.write(`error`,t,n)},fatal(t,n){e.write(`fatal`,t,n)},getTraceContext:T,flush:()=>e.flush(),shutdown:()=>e.shutdown()}}async function A(e){let t=e.env??process.env,r=e.workspaceRoot??y(process.cwd()),i=e.serviceName,f=e.serviceVersion??t.npm_package_version,p=e.enableTraces!==!1,m=e.enableLogs!==!1,h=e.maxFileSizeBytes??Number(t.LOG_SINK_FILE_MAX_BYTES??10485760),_=e.maxFileCount??Number(t.LOG_SINK_FILE_MAX_FILES??5),v=e.logDir??n.default.join(r,g),C=e.logFileName??`${i}.jsonl`,w=n.default.join(v,C),T=b(r)?await x({env:t,workspaceRoot:r}):void 0;if(T){let e={"service.name":i};f&&(e[`service.version`]=f);let t=(0,l.resourceFromAttributes)(e),n=p?new d.NodeTracerProvider({resource:t,spanProcessors:[new d.BatchSpanProcessor(new c.OTLPTraceExporter({url:S(T,`traces`)}))]}):void 0;n?.register();let r=m?new u.LoggerProvider({resource:t,processors:[new u.BatchLogRecordProcessor(new s.OTLPLogExporter({url:S(T,`logs`)}))]}):void 0;r&&o.logs.setGlobalLoggerProvider(r);let g=r?.getLogger(i,f);return{backend:`logsink`,enabled:!0,trace:a.trace,log:o.logs,logger:g?O(g,{flush:async()=>{await Promise.allSettled([n?.forceFlush(),r?.forceFlush()])},shutdown:async()=>{await Promise.allSettled([n?.shutdown(),r?.shutdown()])}}):k(new D({filePath:w,maxFileSizeBytes:h,maxFileCount:_})),endpoint:T,flush:async()=>{await Promise.allSettled([n?.forceFlush(),r?.forceFlush()])},shutdown:async()=>{await Promise.allSettled([n?.shutdown(),r?.shutdown()])}}}let E=new D({filePath:w,maxFileSizeBytes:h,maxFileCount:_});return{backend:`file`,enabled:!0,trace:a.trace,log:o.logs,logger:k(E),filePath:w,flush:()=>E.flush(),shutdown:()=>E.shutdown()}}Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return A}});
|
|
2
|
+
//# sourceMappingURL=node-fq51Liy5.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-fq51Liy5.cjs","names":["DEFAULT_REGISTRY_PATH","PortRegistryService","path","sanitized: Attributes","trace","context","options: FileSinkOptions","SeverityNumber","resourceAttributes: Attributes","NodeTracerProvider","BatchSpanProcessor","OTLPTraceExporter","LoggerProvider","BatchLogRecordProcessor","OTLPLogExporter","logs"],"sources":["../src/utils/resolveLogSinkPort.ts","../src/telemetry/node.ts"],"sourcesContent":["import {\n DEFAULT_REGISTRY_PATH,\n PortRegistryService,\n normalizeRepositoryPath,\n} from '@agimon-ai/foundation-port-registry';\n\nconst LOG_SINK_SERVICE_NAME = 'log-sink-mcp-http';\n\nexport interface LogSinkPortResult {\n port: number;\n host: string;\n endpoint: string;\n}\n\nexport interface ResolveLogSinkPortOptions {\n env?: NodeJS.ProcessEnv;\n workspaceRoot: string;\n healthCheck?: boolean;\n}\n\nexport async function resolveLogSinkPort(options: ResolveLogSinkPortOptions): Promise<LogSinkPortResult | undefined> {\n const { env = process.env, workspaceRoot, healthCheck = true } = options;\n const registryPath = env.PORT_REGISTRY_PATH ?? DEFAULT_REGISTRY_PATH;\n const repositoryPath = normalizeRepositoryPath(workspaceRoot);\n const environment = env.NODE_ENV || 'development';\n const portRegistry = new PortRegistryService(registryPath);\n\n try {\n const result = await portRegistry.getPort({\n repositoryPath,\n serviceName: LOG_SINK_SERVICE_NAME,\n serviceType: 'tool',\n environment,\n });\n\n if (!result.success || !result.port) {\n return undefined;\n }\n\n const host = result.record?.host ?? '127.0.0.1';\n const endpoint = `http://${host}:${result.port}`;\n\n if (!healthCheck) {\n return { port: result.port, host, endpoint };\n }\n\n try {\n const health = await fetch(`${endpoint}/health`);\n if (!health.ok) {\n return undefined;\n }\n\n const payload = (await health.json()) as { status?: string; serviceName?: string; service?: string };\n if (payload.status !== 'healthy') {\n return undefined;\n }\n\n if (payload.serviceName !== LOG_SINK_SERVICE_NAME && payload.service !== LOG_SINK_SERVICE_NAME) {\n return undefined;\n }\n\n return { port: result.port, host, endpoint };\n } catch {\n return undefined;\n }\n } catch {\n return undefined;\n }\n}\n\nexport async function resolveLogSinkOtelEndpoint(options: ResolveLogSinkPortOptions): Promise<string | undefined> {\n const result = await resolveLogSinkPort(options);\n return result?.endpoint;\n}\n","import { existsSync } from 'node:fs';\nimport { appendFile, mkdir, rename, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport { context, trace, type Attributes, type Context } from '@opentelemetry/api';\nimport { logs, SeverityNumber, type Logger as OtelLogger } from '@opentelemetry/api-logs';\nimport { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';\nimport { resourceFromAttributes } from '@opentelemetry/resources';\nimport { BatchLogRecordProcessor, LoggerProvider } from '@opentelemetry/sdk-logs';\nimport { BatchSpanProcessor, NodeTracerProvider } from '@opentelemetry/sdk-trace-node';\nimport { resolveLogSinkOtelEndpoint } from '../utils/resolveLogSinkPort.js';\n\nconst WORKSPACE_MARKERS = ['pnpm-workspace.yaml', 'nx.json', '.git'];\nconst DEFAULT_LOG_DIR = path.join('logs', 'telemetry');\nconst DEFAULT_MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024;\nconst DEFAULT_MAX_FILE_COUNT = 5;\n\nexport type TelemetryLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\nexport interface NodeTelemetryLogOptions {\n attributes?: Attributes;\n context?: Context;\n exception?: unknown;\n}\n\nexport interface NodeTelemetryLogger {\n trace(message: string, options?: NodeTelemetryLogOptions): void;\n debug(message: string, options?: NodeTelemetryLogOptions): void;\n info(message: string, options?: NodeTelemetryLogOptions): void;\n warn(message: string, options?: NodeTelemetryLogOptions): void;\n error(message: string, options?: NodeTelemetryLogOptions): void;\n fatal(message: string, options?: NodeTelemetryLogOptions): void;\n getTraceContext(): { traceId?: string; spanId?: string };\n flush(): Promise<void>;\n shutdown(): Promise<void>;\n}\n\nexport interface NodeTelemetryOptions {\n env?: NodeJS.ProcessEnv;\n serviceName: string;\n serviceVersion?: string;\n workspaceRoot?: string;\n enableTraces?: boolean;\n enableLogs?: boolean;\n logDir?: string;\n logFileName?: string;\n maxFileSizeBytes?: number;\n maxFileCount?: number;\n}\n\nexport interface NodeTelemetryHandle {\n backend: 'logsink' | 'file';\n enabled: boolean;\n trace: typeof trace;\n log: typeof logs;\n logger: NodeTelemetryLogger;\n endpoint?: string;\n filePath?: string;\n flush(): Promise<void>;\n shutdown(): Promise<void>;\n}\n\ninterface FileSinkOptions {\n filePath: string;\n maxFileSizeBytes: number;\n maxFileCount: number;\n}\n\nfunction resolveWorkspaceRoot(startPath = process.cwd()): string {\n let currentDir = path.resolve(startPath);\n\n while (true) {\n for (const marker of WORKSPACE_MARKERS) {\n if (existsSync(path.join(currentDir, marker))) {\n return currentDir;\n }\n }\n\n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) {\n return process.cwd();\n }\n\n currentDir = parentDir;\n }\n}\n\nfunction isLogSinkWorkspaceSupported(workspaceRoot: string): boolean {\n return existsSync(path.join(workspaceRoot, 'packages/mcp/log-sink-mcp/package.json'));\n}\n\nexport async function getLogSinkOtelEndpoint(options: {\n env?: NodeJS.ProcessEnv;\n workspaceRoot: string;\n healthCheck?: boolean;\n}): Promise<string | undefined> {\n return resolveLogSinkOtelEndpoint(options);\n}\n\nfunction withSignalPath(baseUrl: string, signal: 'traces' | 'logs'): string {\n const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;\n if (normalizedBaseUrl.endsWith(`/v1/${signal}/`) || normalizedBaseUrl.endsWith(`/v1/${signal}`)) {\n return baseUrl;\n }\n\n return new URL(`v1/${signal}`, normalizedBaseUrl).toString();\n}\n\nfunction toAttributeValue(value: unknown): string | number | boolean {\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return value;\n }\n\n if (value == null) {\n return '';\n }\n\n return JSON.stringify(value);\n}\n\nfunction sanitizeAttributes(attributes?: Attributes): Attributes | undefined {\n if (!attributes) {\n return undefined;\n }\n\n const sanitized: Attributes = {};\n for (const [key, value] of Object.entries(attributes)) {\n if (value === undefined || value === null) {\n continue;\n }\n\n sanitized[key] = toAttributeValue(value);\n }\n\n return Object.keys(sanitized).length > 0 ? sanitized : undefined;\n}\n\nfunction mapSeverity(level: TelemetryLevel): SeverityNumber {\n switch (level) {\n case 'trace':\n return SeverityNumber.TRACE;\n case 'debug':\n return SeverityNumber.DEBUG;\n case 'info':\n return SeverityNumber.INFO;\n case 'warn':\n return SeverityNumber.WARN;\n case 'error':\n return SeverityNumber.ERROR;\n case 'fatal':\n return SeverityNumber.FATAL;\n }\n}\n\nfunction getActiveSpanContext(): { traceId?: string; spanId?: string } {\n const activeSpan = trace.getSpan(context.active());\n if (!activeSpan) {\n return {};\n }\n\n const spanContext = activeSpan.spanContext();\n return {\n traceId: spanContext.traceId,\n spanId: spanContext.spanId,\n };\n}\n\nfunction serializeLogRecord(level: TelemetryLevel, message: string, options: NodeTelemetryLogOptions = {}): string {\n const activeSpan = trace.getSpan(options.context ?? context.active());\n const spanContext = activeSpan?.spanContext();\n\n return JSON.stringify({\n timestamp: new Date().toISOString(),\n level,\n message,\n traceId: spanContext?.traceId,\n spanId: spanContext?.spanId,\n attributes: options.attributes ? sanitizeAttributes(options.attributes) : undefined,\n exception:\n options.exception instanceof Error\n ? { name: options.exception.name, message: options.exception.message, stack: options.exception.stack }\n : options.exception,\n });\n}\n\nclass RotatingFileSink {\n private pending: Promise<void> = Promise.resolve();\n\n constructor(private readonly options: FileSinkOptions) {}\n\n write(level: TelemetryLevel, message: string, options?: NodeTelemetryLogOptions): void {\n this.pending = this.pending\n .then(async () => {\n const entry = `${serializeLogRecord(level, message, options)}\\n`;\n await this.ensureDirectory();\n await this.rotateIfNeeded(Buffer.byteLength(entry));\n await appendFile(this.options.filePath, entry, 'utf8');\n })\n .catch((error) => {\n console.error(`[log-sink-mcp telemetry] Failed to write log file ${this.options.filePath}:`, error);\n });\n }\n\n async flush(): Promise<void> {\n await this.pending;\n }\n\n async shutdown(): Promise<void> {\n await this.flush();\n }\n\n private async ensureDirectory(): Promise<void> {\n await mkdir(path.dirname(this.options.filePath), { recursive: true });\n }\n\n private async rotateIfNeeded(incomingBytes: number): Promise<void> {\n let currentSize = 0;\n try {\n currentSize = (await stat(this.options.filePath)).size;\n } catch {\n currentSize = 0;\n }\n\n if (currentSize + incomingBytes <= this.options.maxFileSizeBytes) {\n return;\n }\n\n for (let index = this.options.maxFileCount - 1; index >= 1; index -= 1) {\n const source = `${this.options.filePath}.${index}`;\n const target = `${this.options.filePath}.${index + 1}`;\n if (existsSync(source)) {\n await rename(source, target).catch(() => undefined);\n }\n }\n\n if (existsSync(this.options.filePath)) {\n await rename(this.options.filePath, `${this.options.filePath}.1`).catch(() => undefined);\n }\n }\n}\n\nfunction createOtelLogger(\n logger: OtelLogger,\n sink: { flush(): Promise<void>; shutdown(): Promise<void> },\n): NodeTelemetryLogger {\n return {\n trace(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.TRACE,\n severityText: 'TRACE',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n debug(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.DEBUG,\n severityText: 'DEBUG',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n info(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.INFO,\n severityText: 'INFO',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n warn(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.WARN,\n severityText: 'WARN',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n error(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.ERROR,\n severityText: 'ERROR',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n fatal(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.FATAL,\n severityText: 'FATAL',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n getTraceContext: getActiveSpanContext,\n flush: sink.flush,\n shutdown: sink.shutdown,\n };\n}\n\nfunction createFileLogger(sink: RotatingFileSink): NodeTelemetryLogger {\n return {\n trace(message, options) {\n sink.write('trace', message, options);\n },\n debug(message, options) {\n sink.write('debug', message, options);\n },\n info(message, options) {\n sink.write('info', message, options);\n },\n warn(message, options) {\n sink.write('warn', message, options);\n },\n error(message, options) {\n sink.write('error', message, options);\n },\n fatal(message, options) {\n sink.write('fatal', message, options);\n },\n getTraceContext: getActiveSpanContext,\n flush: () => sink.flush(),\n shutdown: () => sink.shutdown(),\n };\n}\n\nexport async function createNodeTelemetry(options: NodeTelemetryOptions): Promise<NodeTelemetryHandle> {\n const env = options.env ?? process.env;\n const workspaceRoot = options.workspaceRoot ?? resolveWorkspaceRoot(process.cwd());\n const serviceName = options.serviceName;\n const serviceVersion = options.serviceVersion ?? env.npm_package_version;\n const enableTraces = options.enableTraces !== false;\n const enableLogs = options.enableLogs !== false;\n const maxFileSizeBytes =\n options.maxFileSizeBytes ?? Number(env.LOG_SINK_FILE_MAX_BYTES ?? DEFAULT_MAX_FILE_SIZE_BYTES);\n const maxFileCount = options.maxFileCount ?? Number(env.LOG_SINK_FILE_MAX_FILES ?? DEFAULT_MAX_FILE_COUNT);\n const logDir = options.logDir ?? path.join(workspaceRoot, DEFAULT_LOG_DIR);\n const logFileName = options.logFileName ?? `${serviceName}.jsonl`;\n const filePath = path.join(logDir, logFileName);\n\n const sinkEndpoint = isLogSinkWorkspaceSupported(workspaceRoot)\n ? await getLogSinkOtelEndpoint({ env, workspaceRoot })\n : undefined;\n if (sinkEndpoint) {\n const resourceAttributes: Attributes = {\n 'service.name': serviceName,\n };\n if (serviceVersion) {\n resourceAttributes['service.version'] = serviceVersion;\n }\n\n const resource = resourceFromAttributes(resourceAttributes);\n const tracerProvider = enableTraces\n ? new NodeTracerProvider({\n resource,\n spanProcessors: [\n new BatchSpanProcessor(\n new OTLPTraceExporter({\n url: withSignalPath(sinkEndpoint, 'traces'),\n }),\n ),\n ],\n })\n : undefined;\n tracerProvider?.register();\n\n const loggerProvider = enableLogs\n ? new LoggerProvider({\n resource,\n processors: [\n new BatchLogRecordProcessor(\n new OTLPLogExporter({\n url: withSignalPath(sinkEndpoint, 'logs'),\n }),\n ),\n ],\n })\n : undefined;\n if (loggerProvider) {\n logs.setGlobalLoggerProvider(loggerProvider);\n }\n\n const sinkLogger = loggerProvider?.getLogger(serviceName, serviceVersion);\n const logger = sinkLogger\n ? createOtelLogger(sinkLogger, {\n flush: async () => {\n await Promise.allSettled([tracerProvider?.forceFlush(), loggerProvider?.forceFlush()]);\n },\n shutdown: async () => {\n await Promise.allSettled([tracerProvider?.shutdown(), loggerProvider?.shutdown()]);\n },\n })\n : createFileLogger(\n new RotatingFileSink({\n filePath,\n maxFileSizeBytes,\n maxFileCount,\n }),\n );\n\n return {\n backend: 'logsink',\n enabled: true,\n trace,\n log: logs,\n logger,\n endpoint: sinkEndpoint,\n flush: async () => {\n await Promise.allSettled([tracerProvider?.forceFlush(), loggerProvider?.forceFlush()]);\n },\n shutdown: async () => {\n await Promise.allSettled([tracerProvider?.shutdown(), loggerProvider?.shutdown()]);\n },\n };\n }\n\n const fileSink = new RotatingFileSink({\n filePath,\n maxFileSizeBytes,\n maxFileCount,\n });\n const logger = createFileLogger(fileSink);\n\n return {\n backend: 'file',\n enabled: true,\n trace,\n log: logs,\n logger,\n filePath,\n flush: () => fileSink.flush(),\n shutdown: () => fileSink.shutdown(),\n };\n}\n\nexport { trace, logs as log };\n"],"mappings":"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"}
|
package/dist/telemetry/node.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(`../chunk-DjWAcSYV.cjs`),t=require(`../node-
|
|
1
|
+
const e=require(`../chunk-DjWAcSYV.cjs`),t=require(`../node-fq51Liy5.cjs`);let n=require(`@opentelemetry/api`),r=require(`@opentelemetry/api-logs`);exports.createNodeTelemetry=t.t,exports.getLogSinkOtelEndpoint=t.n,exports.log=r.logs,exports.trace=n.trace;
|
package/dist/telemetry/node.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{i as e,n as t,r as n,t as r}from"../node-Bu3xSfYZ.mjs";export{r as createNodeTelemetry,t as getLogSinkOtelEndpoint,n as log,e as trace};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/log-sink-mcp",
|
|
3
3
|
"description": "Log sink MCP server with HTTP ingestion and AI analysis",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.1",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mcp",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"sqlite-vec": "^0.1.7",
|
|
42
42
|
"ulidx": "2.4.1",
|
|
43
43
|
"zod": "4.3.6",
|
|
44
|
-
"@agimon-ai/foundation-
|
|
45
|
-
"@agimon-ai/foundation-
|
|
44
|
+
"@agimon-ai/foundation-port-registry": "0.3.1",
|
|
45
|
+
"@agimon-ai/foundation-process-registry": "0.3.1"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/bun": "^1.3.6",
|
package/dist/node-BXUuvy4I.mjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{existsSync as e}from"node:fs";import t from"node:path";import{DEFAULT_REGISTRY_PATH as n,PortRegistryService as r,normalizeRepositoryPath as i}from"@agimon-ai/foundation-port-registry";import{appendFile as a,mkdir as o,rename as s,stat as c}from"node:fs/promises";import{context as l,trace as u}from"@opentelemetry/api";import{SeverityNumber as d,logs as f}from"@opentelemetry/api-logs";import{OTLPLogExporter as p}from"@opentelemetry/exporter-logs-otlp-http";import{OTLPTraceExporter as m}from"@opentelemetry/exporter-trace-otlp-http";import{resourceFromAttributes as h}from"@opentelemetry/resources";import{BatchLogRecordProcessor as g,LoggerProvider as _}from"@opentelemetry/sdk-logs";import{BatchSpanProcessor as v,NodeTracerProvider as y}from"@opentelemetry/sdk-trace-node";const b=`log-sink-mcp-http`;async function x(e){let{env:t=process.env,workspaceRoot:a,healthCheck:o=!0}=e,s=t.PORT_REGISTRY_PATH??n,c=i(a),l=t.NODE_ENV||`development`,u=new r(s);try{let e=await u.getPort({repositoryPath:c,serviceName:b,serviceType:`tool`,environment:l});if(!e.success||!e.port)return;let t=e.record?.host??`127.0.0.1`,n=`http://${t}:${e.port}`;if(!o)return{port:e.port,host:t,endpoint:n};try{let r=await fetch(`${n}/health`);if(!r.ok)return;let i=await r.json();return i.status!==`healthy`||i.serviceName!==b&&i.service!==b?void 0:{port:e.port,host:t,endpoint:n}}catch{return}}catch{return}}const S=[`pnpm-workspace.yaml`,`nx.json`,`.git`],C=t.join(`logs`,`telemetry`);function w(n=process.cwd()){let r=t.resolve(n);for(;;){for(let n of S)if(e(t.join(r,n)))return r;let n=t.dirname(r);if(n===r)return process.cwd();r=n}}function T(n){return e(t.join(n,`packages/mcp/log-sink-mcp/package.json`))}async function E(e,t){return(await x({env:e,workspaceRoot:t}))?.endpoint}function D(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return n.endsWith(`/v1/${t}/`)||n.endsWith(`/v1/${t}`)?e:new URL(`v1/${t}`,n).toString()}function O(e){return typeof e==`string`||typeof e==`number`||typeof e==`boolean`?e:e==null?``:JSON.stringify(e)}function k(e){if(!e)return;let t={};for(let[n,r]of Object.entries(e))r!=null&&(t[n]=O(r));return Object.keys(t).length>0?t:void 0}function A(){let e=u.getSpan(l.active());if(!e)return{};let t=e.spanContext();return{traceId:t.traceId,spanId:t.spanId}}function j(e,t,n={}){let r=u.getSpan(n.context??l.active())?.spanContext();return JSON.stringify({timestamp:new Date().toISOString(),level:e,message:t,traceId:r?.traceId,spanId:r?.spanId,attributes:n.attributes?k(n.attributes):void 0,exception:n.exception instanceof Error?{name:n.exception.name,message:n.exception.message,stack:n.exception.stack}:n.exception})}var M=class{pending=Promise.resolve();constructor(e){this.options=e}write(e,t,n){this.pending=this.pending.then(async()=>{let r=`${j(e,t,n)}\n`;await this.ensureDirectory(),await this.rotateIfNeeded(Buffer.byteLength(r)),await a(this.options.filePath,r,`utf8`)}).catch(e=>{console.error(`[log-sink-mcp telemetry] Failed to write log file ${this.options.filePath}:`,e)})}async flush(){await this.pending}async shutdown(){await this.flush()}async ensureDirectory(){await o(t.dirname(this.options.filePath),{recursive:!0})}async rotateIfNeeded(t){let n=0;try{n=(await c(this.options.filePath)).size}catch{n=0}if(!(n+t<=this.options.maxFileSizeBytes)){for(let t=this.options.maxFileCount-1;t>=1;--t){let n=`${this.options.filePath}.${t}`,r=`${this.options.filePath}.${t+1}`;e(n)&&await s(n,r).catch(()=>void 0)}e(this.options.filePath)&&await s(this.options.filePath,`${this.options.filePath}.1`).catch(()=>void 0)}}};function N(e,t){return{trace(t,n){e.emit({severityNumber:d.TRACE,severityText:`TRACE`,body:t,attributes:k(n?.attributes),context:n?.context??l.active(),exception:n?.exception})},debug(t,n){e.emit({severityNumber:d.DEBUG,severityText:`DEBUG`,body:t,attributes:k(n?.attributes),context:n?.context??l.active(),exception:n?.exception})},info(t,n){e.emit({severityNumber:d.INFO,severityText:`INFO`,body:t,attributes:k(n?.attributes),context:n?.context??l.active(),exception:n?.exception})},warn(t,n){e.emit({severityNumber:d.WARN,severityText:`WARN`,body:t,attributes:k(n?.attributes),context:n?.context??l.active(),exception:n?.exception})},error(t,n){e.emit({severityNumber:d.ERROR,severityText:`ERROR`,body:t,attributes:k(n?.attributes),context:n?.context??l.active(),exception:n?.exception})},fatal(t,n){e.emit({severityNumber:d.FATAL,severityText:`FATAL`,body:t,attributes:k(n?.attributes),context:n?.context??l.active(),exception:n?.exception})},getTraceContext:A,flush:t.flush,shutdown:t.shutdown}}function P(e){return{trace(t,n){e.write(`trace`,t,n)},debug(t,n){e.write(`debug`,t,n)},info(t,n){e.write(`info`,t,n)},warn(t,n){e.write(`warn`,t,n)},error(t,n){e.write(`error`,t,n)},fatal(t,n){e.write(`fatal`,t,n)},getTraceContext:A,flush:()=>e.flush(),shutdown:()=>e.shutdown()}}async function F(e){let n=e.env??process.env,r=e.workspaceRoot??w(process.cwd()),i=e.serviceName,a=e.serviceVersion??n.npm_package_version,o=e.enableTraces!==!1,s=e.enableLogs!==!1,c=e.maxFileSizeBytes??Number(n.LOG_SINK_FILE_MAX_BYTES??10485760),l=e.maxFileCount??Number(n.LOG_SINK_FILE_MAX_FILES??5),d=e.logDir??t.join(r,C),b=e.logFileName??`${i}.jsonl`,x=t.join(d,b),S=T(r)?await E(n,r):void 0;if(S){let e={"service.name":i};a&&(e[`service.version`]=a);let t=h(e),n=o?new y({resource:t,spanProcessors:[new v(new m({url:D(S,`traces`)}))]}):void 0;n?.register();let r=s?new _({resource:t,processors:[new g(new p({url:D(S,`logs`)}))]}):void 0;r&&f.setGlobalLoggerProvider(r);let d=r?.getLogger(i,a);return{backend:`logsink`,enabled:!0,trace:u,log:f,logger:d?N(d,{flush:async()=>{await Promise.allSettled([n?.forceFlush(),r?.forceFlush()])},shutdown:async()=>{await Promise.allSettled([n?.shutdown(),r?.shutdown()])}}):P(new M({filePath:x,maxFileSizeBytes:c,maxFileCount:l})),endpoint:S,flush:async()=>{await Promise.allSettled([n?.forceFlush(),r?.forceFlush()])},shutdown:async()=>{await Promise.allSettled([n?.shutdown(),r?.shutdown()])}}}let O=new M({filePath:x,maxFileSizeBytes:c,maxFileCount:l});return{backend:`file`,enabled:!0,trace:u,log:f,logger:P(O),filePath:x,flush:()=>O.flush(),shutdown:()=>O.shutdown()}}export{x as i,f as n,u as r,F as t};
|
|
2
|
-
//# sourceMappingURL=node-BXUuvy4I.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"node-BXUuvy4I.mjs","names":["sanitized: Attributes","options: FileSinkOptions","resourceAttributes: Attributes"],"sources":["../src/utils/resolveLogSinkPort.ts","../src/telemetry/node.ts"],"sourcesContent":["import {\n DEFAULT_REGISTRY_PATH,\n PortRegistryService,\n normalizeRepositoryPath,\n} from '@agimon-ai/foundation-port-registry';\n\nconst LOG_SINK_SERVICE_NAME = 'log-sink-mcp-http';\n\nexport interface LogSinkPortResult {\n port: number;\n host: string;\n endpoint: string;\n}\n\nexport interface ResolveLogSinkPortOptions {\n env?: NodeJS.ProcessEnv;\n workspaceRoot: string;\n healthCheck?: boolean;\n}\n\nexport async function resolveLogSinkPort(options: ResolveLogSinkPortOptions): Promise<LogSinkPortResult | undefined> {\n const { env = process.env, workspaceRoot, healthCheck = true } = options;\n const registryPath = env.PORT_REGISTRY_PATH ?? DEFAULT_REGISTRY_PATH;\n const repositoryPath = normalizeRepositoryPath(workspaceRoot);\n const environment = env.NODE_ENV || 'development';\n const portRegistry = new PortRegistryService(registryPath);\n\n try {\n const result = await portRegistry.getPort({\n repositoryPath,\n serviceName: LOG_SINK_SERVICE_NAME,\n serviceType: 'tool',\n environment,\n });\n\n if (!result.success || !result.port) {\n return undefined;\n }\n\n const host = result.record?.host ?? '127.0.0.1';\n const endpoint = `http://${host}:${result.port}`;\n\n if (!healthCheck) {\n return { port: result.port, host, endpoint };\n }\n\n try {\n const health = await fetch(`${endpoint}/health`);\n if (!health.ok) {\n return undefined;\n }\n\n const payload = (await health.json()) as { status?: string; serviceName?: string; service?: string };\n if (payload.status !== 'healthy') {\n return undefined;\n }\n\n if (payload.serviceName !== LOG_SINK_SERVICE_NAME && payload.service !== LOG_SINK_SERVICE_NAME) {\n return undefined;\n }\n\n return { port: result.port, host, endpoint };\n } catch {\n return undefined;\n }\n } catch {\n return undefined;\n }\n}\n","import { existsSync } from 'node:fs';\nimport { appendFile, mkdir, rename, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport { context, trace, type Attributes, type Context } from '@opentelemetry/api';\nimport { logs, SeverityNumber, type Logger as OtelLogger } from '@opentelemetry/api-logs';\nimport { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';\nimport { resourceFromAttributes } from '@opentelemetry/resources';\nimport { BatchLogRecordProcessor, LoggerProvider } from '@opentelemetry/sdk-logs';\nimport { BatchSpanProcessor, NodeTracerProvider } from '@opentelemetry/sdk-trace-node';\nimport { resolveLogSinkPort } from '../utils/resolveLogSinkPort.js';\n\nconst WORKSPACE_MARKERS = ['pnpm-workspace.yaml', 'nx.json', '.git'];\nconst DEFAULT_LOG_DIR = path.join('logs', 'telemetry');\nconst DEFAULT_MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024;\nconst DEFAULT_MAX_FILE_COUNT = 5;\n\nexport type TelemetryLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\nexport interface NodeTelemetryLogOptions {\n attributes?: Attributes;\n context?: Context;\n exception?: unknown;\n}\n\nexport interface NodeTelemetryLogger {\n trace(message: string, options?: NodeTelemetryLogOptions): void;\n debug(message: string, options?: NodeTelemetryLogOptions): void;\n info(message: string, options?: NodeTelemetryLogOptions): void;\n warn(message: string, options?: NodeTelemetryLogOptions): void;\n error(message: string, options?: NodeTelemetryLogOptions): void;\n fatal(message: string, options?: NodeTelemetryLogOptions): void;\n getTraceContext(): { traceId?: string; spanId?: string };\n flush(): Promise<void>;\n shutdown(): Promise<void>;\n}\n\nexport interface NodeTelemetryOptions {\n env?: NodeJS.ProcessEnv;\n serviceName: string;\n serviceVersion?: string;\n workspaceRoot?: string;\n enableTraces?: boolean;\n enableLogs?: boolean;\n logDir?: string;\n logFileName?: string;\n maxFileSizeBytes?: number;\n maxFileCount?: number;\n}\n\nexport interface NodeTelemetryHandle {\n backend: 'logsink' | 'file';\n enabled: boolean;\n trace: typeof trace;\n log: typeof logs;\n logger: NodeTelemetryLogger;\n endpoint?: string;\n filePath?: string;\n flush(): Promise<void>;\n shutdown(): Promise<void>;\n}\n\ninterface FileSinkOptions {\n filePath: string;\n maxFileSizeBytes: number;\n maxFileCount: number;\n}\n\nfunction resolveWorkspaceRoot(startPath = process.cwd()): string {\n let currentDir = path.resolve(startPath);\n\n while (true) {\n for (const marker of WORKSPACE_MARKERS) {\n if (existsSync(path.join(currentDir, marker))) {\n return currentDir;\n }\n }\n\n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) {\n return process.cwd();\n }\n\n currentDir = parentDir;\n }\n}\n\nfunction isLogSinkWorkspaceSupported(workspaceRoot: string): boolean {\n return existsSync(path.join(workspaceRoot, 'packages/mcp/log-sink-mcp/package.json'));\n}\n\nasync function resolveLogSinkEndpoint(env: NodeJS.ProcessEnv, workspaceRoot: string): Promise<string | undefined> {\n const result = await resolveLogSinkPort({ env, workspaceRoot });\n return result?.endpoint;\n}\n\nfunction withSignalPath(baseUrl: string, signal: 'traces' | 'logs'): string {\n const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;\n if (normalizedBaseUrl.endsWith(`/v1/${signal}/`) || normalizedBaseUrl.endsWith(`/v1/${signal}`)) {\n return baseUrl;\n }\n\n return new URL(`v1/${signal}`, normalizedBaseUrl).toString();\n}\n\nfunction toAttributeValue(value: unknown): string | number | boolean {\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return value;\n }\n\n if (value == null) {\n return '';\n }\n\n return JSON.stringify(value);\n}\n\nfunction sanitizeAttributes(attributes?: Attributes): Attributes | undefined {\n if (!attributes) {\n return undefined;\n }\n\n const sanitized: Attributes = {};\n for (const [key, value] of Object.entries(attributes)) {\n if (value === undefined || value === null) {\n continue;\n }\n\n sanitized[key] = toAttributeValue(value);\n }\n\n return Object.keys(sanitized).length > 0 ? sanitized : undefined;\n}\n\nfunction mapSeverity(level: TelemetryLevel): SeverityNumber {\n switch (level) {\n case 'trace':\n return SeverityNumber.TRACE;\n case 'debug':\n return SeverityNumber.DEBUG;\n case 'info':\n return SeverityNumber.INFO;\n case 'warn':\n return SeverityNumber.WARN;\n case 'error':\n return SeverityNumber.ERROR;\n case 'fatal':\n return SeverityNumber.FATAL;\n }\n}\n\nfunction getActiveSpanContext(): { traceId?: string; spanId?: string } {\n const activeSpan = trace.getSpan(context.active());\n if (!activeSpan) {\n return {};\n }\n\n const spanContext = activeSpan.spanContext();\n return {\n traceId: spanContext.traceId,\n spanId: spanContext.spanId,\n };\n}\n\nfunction serializeLogRecord(level: TelemetryLevel, message: string, options: NodeTelemetryLogOptions = {}): string {\n const activeSpan = trace.getSpan(options.context ?? context.active());\n const spanContext = activeSpan?.spanContext();\n\n return JSON.stringify({\n timestamp: new Date().toISOString(),\n level,\n message,\n traceId: spanContext?.traceId,\n spanId: spanContext?.spanId,\n attributes: options.attributes ? sanitizeAttributes(options.attributes) : undefined,\n exception:\n options.exception instanceof Error\n ? { name: options.exception.name, message: options.exception.message, stack: options.exception.stack }\n : options.exception,\n });\n}\n\nclass RotatingFileSink {\n private pending: Promise<void> = Promise.resolve();\n\n constructor(private readonly options: FileSinkOptions) {}\n\n write(level: TelemetryLevel, message: string, options?: NodeTelemetryLogOptions): void {\n this.pending = this.pending\n .then(async () => {\n const entry = `${serializeLogRecord(level, message, options)}\\n`;\n await this.ensureDirectory();\n await this.rotateIfNeeded(Buffer.byteLength(entry));\n await appendFile(this.options.filePath, entry, 'utf8');\n })\n .catch((error) => {\n console.error(`[log-sink-mcp telemetry] Failed to write log file ${this.options.filePath}:`, error);\n });\n }\n\n async flush(): Promise<void> {\n await this.pending;\n }\n\n async shutdown(): Promise<void> {\n await this.flush();\n }\n\n private async ensureDirectory(): Promise<void> {\n await mkdir(path.dirname(this.options.filePath), { recursive: true });\n }\n\n private async rotateIfNeeded(incomingBytes: number): Promise<void> {\n let currentSize = 0;\n try {\n currentSize = (await stat(this.options.filePath)).size;\n } catch {\n currentSize = 0;\n }\n\n if (currentSize + incomingBytes <= this.options.maxFileSizeBytes) {\n return;\n }\n\n for (let index = this.options.maxFileCount - 1; index >= 1; index -= 1) {\n const source = `${this.options.filePath}.${index}`;\n const target = `${this.options.filePath}.${index + 1}`;\n if (existsSync(source)) {\n await rename(source, target).catch(() => undefined);\n }\n }\n\n if (existsSync(this.options.filePath)) {\n await rename(this.options.filePath, `${this.options.filePath}.1`).catch(() => undefined);\n }\n }\n}\n\nfunction createOtelLogger(\n logger: OtelLogger,\n sink: { flush(): Promise<void>; shutdown(): Promise<void> },\n): NodeTelemetryLogger {\n return {\n trace(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.TRACE,\n severityText: 'TRACE',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n debug(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.DEBUG,\n severityText: 'DEBUG',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n info(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.INFO,\n severityText: 'INFO',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n warn(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.WARN,\n severityText: 'WARN',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n error(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.ERROR,\n severityText: 'ERROR',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n fatal(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.FATAL,\n severityText: 'FATAL',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n getTraceContext: getActiveSpanContext,\n flush: sink.flush,\n shutdown: sink.shutdown,\n };\n}\n\nfunction createFileLogger(sink: RotatingFileSink): NodeTelemetryLogger {\n return {\n trace(message, options) {\n sink.write('trace', message, options);\n },\n debug(message, options) {\n sink.write('debug', message, options);\n },\n info(message, options) {\n sink.write('info', message, options);\n },\n warn(message, options) {\n sink.write('warn', message, options);\n },\n error(message, options) {\n sink.write('error', message, options);\n },\n fatal(message, options) {\n sink.write('fatal', message, options);\n },\n getTraceContext: getActiveSpanContext,\n flush: () => sink.flush(),\n shutdown: () => sink.shutdown(),\n };\n}\n\nexport async function createNodeTelemetry(options: NodeTelemetryOptions): Promise<NodeTelemetryHandle> {\n const env = options.env ?? process.env;\n const workspaceRoot = options.workspaceRoot ?? resolveWorkspaceRoot(process.cwd());\n const serviceName = options.serviceName;\n const serviceVersion = options.serviceVersion ?? env.npm_package_version;\n const enableTraces = options.enableTraces !== false;\n const enableLogs = options.enableLogs !== false;\n const maxFileSizeBytes =\n options.maxFileSizeBytes ?? Number(env.LOG_SINK_FILE_MAX_BYTES ?? DEFAULT_MAX_FILE_SIZE_BYTES);\n const maxFileCount = options.maxFileCount ?? Number(env.LOG_SINK_FILE_MAX_FILES ?? DEFAULT_MAX_FILE_COUNT);\n const logDir = options.logDir ?? path.join(workspaceRoot, DEFAULT_LOG_DIR);\n const logFileName = options.logFileName ?? `${serviceName}.jsonl`;\n const filePath = path.join(logDir, logFileName);\n\n const sinkEndpoint = isLogSinkWorkspaceSupported(workspaceRoot)\n ? await resolveLogSinkEndpoint(env, workspaceRoot)\n : undefined;\n if (sinkEndpoint) {\n const resourceAttributes: Attributes = {\n 'service.name': serviceName,\n };\n if (serviceVersion) {\n resourceAttributes['service.version'] = serviceVersion;\n }\n\n const resource = resourceFromAttributes(resourceAttributes);\n const tracerProvider = enableTraces\n ? new NodeTracerProvider({\n resource,\n spanProcessors: [\n new BatchSpanProcessor(\n new OTLPTraceExporter({\n url: withSignalPath(sinkEndpoint, 'traces'),\n }),\n ),\n ],\n })\n : undefined;\n tracerProvider?.register();\n\n const loggerProvider = enableLogs\n ? new LoggerProvider({\n resource,\n processors: [\n new BatchLogRecordProcessor(\n new OTLPLogExporter({\n url: withSignalPath(sinkEndpoint, 'logs'),\n }),\n ),\n ],\n })\n : undefined;\n if (loggerProvider) {\n logs.setGlobalLoggerProvider(loggerProvider);\n }\n\n const sinkLogger = loggerProvider?.getLogger(serviceName, serviceVersion);\n const logger = sinkLogger\n ? createOtelLogger(sinkLogger, {\n flush: async () => {\n await Promise.allSettled([tracerProvider?.forceFlush(), loggerProvider?.forceFlush()]);\n },\n shutdown: async () => {\n await Promise.allSettled([tracerProvider?.shutdown(), loggerProvider?.shutdown()]);\n },\n })\n : createFileLogger(\n new RotatingFileSink({\n filePath,\n maxFileSizeBytes,\n maxFileCount,\n }),\n );\n\n return {\n backend: 'logsink',\n enabled: true,\n trace,\n log: logs,\n logger,\n endpoint: sinkEndpoint,\n flush: async () => {\n await Promise.allSettled([tracerProvider?.forceFlush(), loggerProvider?.forceFlush()]);\n },\n shutdown: async () => {\n await Promise.allSettled([tracerProvider?.shutdown(), loggerProvider?.shutdown()]);\n },\n };\n }\n\n const fileSink = new RotatingFileSink({\n filePath,\n maxFileSizeBytes,\n maxFileCount,\n });\n const logger = createFileLogger(fileSink);\n\n return {\n backend: 'file',\n enabled: true,\n trace,\n log: logs,\n logger,\n filePath,\n flush: () => fileSink.flush(),\n shutdown: () => fileSink.shutdown(),\n };\n}\n\nexport { trace, logs as log };\n"],"mappings":"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"}
|
package/dist/node-DnZY4eWX.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require(`./chunk-DjWAcSYV.cjs`);let t=require(`node:fs`),n=require(`node:path`);n=e.t(n);let r=require(`@agimon-ai/foundation-port-registry`),i=require(`node:fs/promises`),a=require(`@opentelemetry/api`),o=require(`@opentelemetry/api-logs`),s=require(`@opentelemetry/exporter-logs-otlp-http`),c=require(`@opentelemetry/exporter-trace-otlp-http`),l=require(`@opentelemetry/resources`),u=require(`@opentelemetry/sdk-logs`),d=require(`@opentelemetry/sdk-trace-node`);const f=`log-sink-mcp-http`;async function p(e){let{env:t=process.env,workspaceRoot:n,healthCheck:i=!0}=e,a=t.PORT_REGISTRY_PATH??r.DEFAULT_REGISTRY_PATH,o=(0,r.normalizeRepositoryPath)(n),s=t.NODE_ENV||`development`,c=new r.PortRegistryService(a);try{let e=await c.getPort({repositoryPath:o,serviceName:f,serviceType:`tool`,environment:s});if(!e.success||!e.port)return;let t=e.record?.host??`127.0.0.1`,n=`http://${t}:${e.port}`;if(!i)return{port:e.port,host:t,endpoint:n};try{let r=await fetch(`${n}/health`);if(!r.ok)return;let i=await r.json();return i.status!==`healthy`||i.serviceName!==f&&i.service!==f?void 0:{port:e.port,host:t,endpoint:n}}catch{return}}catch{return}}const m=[`pnpm-workspace.yaml`,`nx.json`,`.git`],h=n.default.join(`logs`,`telemetry`),g=10*1024*1024,_=5;function v(e=process.cwd()){let r=n.default.resolve(e);for(;;){for(let e of m)if((0,t.existsSync)(n.default.join(r,e)))return r;let e=n.default.dirname(r);if(e===r)return process.cwd();r=e}}function y(e){return(0,t.existsSync)(n.default.join(e,`packages/mcp/log-sink-mcp/package.json`))}async function b(e,t){return(await p({env:e,workspaceRoot:t}))?.endpoint}function x(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return n.endsWith(`/v1/${t}/`)||n.endsWith(`/v1/${t}`)?e:new URL(`v1/${t}`,n).toString()}function S(e){return typeof e==`string`||typeof e==`number`||typeof e==`boolean`?e:e==null?``:JSON.stringify(e)}function C(e){if(!e)return;let t={};for(let[n,r]of Object.entries(e))r!=null&&(t[n]=S(r));return Object.keys(t).length>0?t:void 0}function w(){let e=a.trace.getSpan(a.context.active());if(!e)return{};let t=e.spanContext();return{traceId:t.traceId,spanId:t.spanId}}function T(e,t,n={}){let r=a.trace.getSpan(n.context??a.context.active())?.spanContext();return JSON.stringify({timestamp:new Date().toISOString(),level:e,message:t,traceId:r?.traceId,spanId:r?.spanId,attributes:n.attributes?C(n.attributes):void 0,exception:n.exception instanceof Error?{name:n.exception.name,message:n.exception.message,stack:n.exception.stack}:n.exception})}var E=class{pending=Promise.resolve();constructor(e){this.options=e}write(e,t,n){this.pending=this.pending.then(async()=>{let r=`${T(e,t,n)}\n`;await this.ensureDirectory(),await this.rotateIfNeeded(Buffer.byteLength(r)),await(0,i.appendFile)(this.options.filePath,r,`utf8`)}).catch(e=>{console.error(`[log-sink-mcp telemetry] Failed to write log file ${this.options.filePath}:`,e)})}async flush(){await this.pending}async shutdown(){await this.flush()}async ensureDirectory(){await(0,i.mkdir)(n.default.dirname(this.options.filePath),{recursive:!0})}async rotateIfNeeded(e){let n=0;try{n=(await(0,i.stat)(this.options.filePath)).size}catch{n=0}if(!(n+e<=this.options.maxFileSizeBytes)){for(let e=this.options.maxFileCount-1;e>=1;--e){let n=`${this.options.filePath}.${e}`,r=`${this.options.filePath}.${e+1}`;(0,t.existsSync)(n)&&await(0,i.rename)(n,r).catch(()=>void 0)}(0,t.existsSync)(this.options.filePath)&&await(0,i.rename)(this.options.filePath,`${this.options.filePath}.1`).catch(()=>void 0)}}};function D(e,t){return{trace(t,n){e.emit({severityNumber:o.SeverityNumber.TRACE,severityText:`TRACE`,body:t,attributes:C(n?.attributes),context:n?.context??a.context.active(),exception:n?.exception})},debug(t,n){e.emit({severityNumber:o.SeverityNumber.DEBUG,severityText:`DEBUG`,body:t,attributes:C(n?.attributes),context:n?.context??a.context.active(),exception:n?.exception})},info(t,n){e.emit({severityNumber:o.SeverityNumber.INFO,severityText:`INFO`,body:t,attributes:C(n?.attributes),context:n?.context??a.context.active(),exception:n?.exception})},warn(t,n){e.emit({severityNumber:o.SeverityNumber.WARN,severityText:`WARN`,body:t,attributes:C(n?.attributes),context:n?.context??a.context.active(),exception:n?.exception})},error(t,n){e.emit({severityNumber:o.SeverityNumber.ERROR,severityText:`ERROR`,body:t,attributes:C(n?.attributes),context:n?.context??a.context.active(),exception:n?.exception})},fatal(t,n){e.emit({severityNumber:o.SeverityNumber.FATAL,severityText:`FATAL`,body:t,attributes:C(n?.attributes),context:n?.context??a.context.active(),exception:n?.exception})},getTraceContext:w,flush:t.flush,shutdown:t.shutdown}}function O(e){return{trace(t,n){e.write(`trace`,t,n)},debug(t,n){e.write(`debug`,t,n)},info(t,n){e.write(`info`,t,n)},warn(t,n){e.write(`warn`,t,n)},error(t,n){e.write(`error`,t,n)},fatal(t,n){e.write(`fatal`,t,n)},getTraceContext:w,flush:()=>e.flush(),shutdown:()=>e.shutdown()}}async function k(e){let t=e.env??process.env,r=e.workspaceRoot??v(process.cwd()),i=e.serviceName,f=e.serviceVersion??t.npm_package_version,p=e.enableTraces!==!1,m=e.enableLogs!==!1,g=e.maxFileSizeBytes??Number(t.LOG_SINK_FILE_MAX_BYTES??10485760),_=e.maxFileCount??Number(t.LOG_SINK_FILE_MAX_FILES??5),S=e.logDir??n.default.join(r,h),C=e.logFileName??`${i}.jsonl`,w=n.default.join(S,C),T=y(r)?await b(t,r):void 0;if(T){let e={"service.name":i};f&&(e[`service.version`]=f);let t=(0,l.resourceFromAttributes)(e),n=p?new d.NodeTracerProvider({resource:t,spanProcessors:[new d.BatchSpanProcessor(new c.OTLPTraceExporter({url:x(T,`traces`)}))]}):void 0;n?.register();let r=m?new u.LoggerProvider({resource:t,processors:[new u.BatchLogRecordProcessor(new s.OTLPLogExporter({url:x(T,`logs`)}))]}):void 0;r&&o.logs.setGlobalLoggerProvider(r);let h=r?.getLogger(i,f);return{backend:`logsink`,enabled:!0,trace:a.trace,log:o.logs,logger:h?D(h,{flush:async()=>{await Promise.allSettled([n?.forceFlush(),r?.forceFlush()])},shutdown:async()=>{await Promise.allSettled([n?.shutdown(),r?.shutdown()])}}):O(new E({filePath:w,maxFileSizeBytes:g,maxFileCount:_})),endpoint:T,flush:async()=>{await Promise.allSettled([n?.forceFlush(),r?.forceFlush()])},shutdown:async()=>{await Promise.allSettled([n?.shutdown(),r?.shutdown()])}}}let k=new E({filePath:w,maxFileSizeBytes:g,maxFileCount:_});return{backend:`file`,enabled:!0,trace:a.trace,log:o.logs,logger:O(k),filePath:w,flush:()=>k.flush(),shutdown:()=>k.shutdown()}}Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return k}});
|
|
2
|
-
//# sourceMappingURL=node-DnZY4eWX.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"node-DnZY4eWX.cjs","names":["DEFAULT_REGISTRY_PATH","PortRegistryService","path","sanitized: Attributes","trace","context","options: FileSinkOptions","SeverityNumber","resourceAttributes: Attributes","NodeTracerProvider","BatchSpanProcessor","OTLPTraceExporter","LoggerProvider","BatchLogRecordProcessor","OTLPLogExporter","logs"],"sources":["../src/utils/resolveLogSinkPort.ts","../src/telemetry/node.ts"],"sourcesContent":["import {\n DEFAULT_REGISTRY_PATH,\n PortRegistryService,\n normalizeRepositoryPath,\n} from '@agimon-ai/foundation-port-registry';\n\nconst LOG_SINK_SERVICE_NAME = 'log-sink-mcp-http';\n\nexport interface LogSinkPortResult {\n port: number;\n host: string;\n endpoint: string;\n}\n\nexport interface ResolveLogSinkPortOptions {\n env?: NodeJS.ProcessEnv;\n workspaceRoot: string;\n healthCheck?: boolean;\n}\n\nexport async function resolveLogSinkPort(options: ResolveLogSinkPortOptions): Promise<LogSinkPortResult | undefined> {\n const { env = process.env, workspaceRoot, healthCheck = true } = options;\n const registryPath = env.PORT_REGISTRY_PATH ?? DEFAULT_REGISTRY_PATH;\n const repositoryPath = normalizeRepositoryPath(workspaceRoot);\n const environment = env.NODE_ENV || 'development';\n const portRegistry = new PortRegistryService(registryPath);\n\n try {\n const result = await portRegistry.getPort({\n repositoryPath,\n serviceName: LOG_SINK_SERVICE_NAME,\n serviceType: 'tool',\n environment,\n });\n\n if (!result.success || !result.port) {\n return undefined;\n }\n\n const host = result.record?.host ?? '127.0.0.1';\n const endpoint = `http://${host}:${result.port}`;\n\n if (!healthCheck) {\n return { port: result.port, host, endpoint };\n }\n\n try {\n const health = await fetch(`${endpoint}/health`);\n if (!health.ok) {\n return undefined;\n }\n\n const payload = (await health.json()) as { status?: string; serviceName?: string; service?: string };\n if (payload.status !== 'healthy') {\n return undefined;\n }\n\n if (payload.serviceName !== LOG_SINK_SERVICE_NAME && payload.service !== LOG_SINK_SERVICE_NAME) {\n return undefined;\n }\n\n return { port: result.port, host, endpoint };\n } catch {\n return undefined;\n }\n } catch {\n return undefined;\n }\n}\n","import { existsSync } from 'node:fs';\nimport { appendFile, mkdir, rename, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport { context, trace, type Attributes, type Context } from '@opentelemetry/api';\nimport { logs, SeverityNumber, type Logger as OtelLogger } from '@opentelemetry/api-logs';\nimport { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';\nimport { resourceFromAttributes } from '@opentelemetry/resources';\nimport { BatchLogRecordProcessor, LoggerProvider } from '@opentelemetry/sdk-logs';\nimport { BatchSpanProcessor, NodeTracerProvider } from '@opentelemetry/sdk-trace-node';\nimport { resolveLogSinkPort } from '../utils/resolveLogSinkPort.js';\n\nconst WORKSPACE_MARKERS = ['pnpm-workspace.yaml', 'nx.json', '.git'];\nconst DEFAULT_LOG_DIR = path.join('logs', 'telemetry');\nconst DEFAULT_MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024;\nconst DEFAULT_MAX_FILE_COUNT = 5;\n\nexport type TelemetryLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\nexport interface NodeTelemetryLogOptions {\n attributes?: Attributes;\n context?: Context;\n exception?: unknown;\n}\n\nexport interface NodeTelemetryLogger {\n trace(message: string, options?: NodeTelemetryLogOptions): void;\n debug(message: string, options?: NodeTelemetryLogOptions): void;\n info(message: string, options?: NodeTelemetryLogOptions): void;\n warn(message: string, options?: NodeTelemetryLogOptions): void;\n error(message: string, options?: NodeTelemetryLogOptions): void;\n fatal(message: string, options?: NodeTelemetryLogOptions): void;\n getTraceContext(): { traceId?: string; spanId?: string };\n flush(): Promise<void>;\n shutdown(): Promise<void>;\n}\n\nexport interface NodeTelemetryOptions {\n env?: NodeJS.ProcessEnv;\n serviceName: string;\n serviceVersion?: string;\n workspaceRoot?: string;\n enableTraces?: boolean;\n enableLogs?: boolean;\n logDir?: string;\n logFileName?: string;\n maxFileSizeBytes?: number;\n maxFileCount?: number;\n}\n\nexport interface NodeTelemetryHandle {\n backend: 'logsink' | 'file';\n enabled: boolean;\n trace: typeof trace;\n log: typeof logs;\n logger: NodeTelemetryLogger;\n endpoint?: string;\n filePath?: string;\n flush(): Promise<void>;\n shutdown(): Promise<void>;\n}\n\ninterface FileSinkOptions {\n filePath: string;\n maxFileSizeBytes: number;\n maxFileCount: number;\n}\n\nfunction resolveWorkspaceRoot(startPath = process.cwd()): string {\n let currentDir = path.resolve(startPath);\n\n while (true) {\n for (const marker of WORKSPACE_MARKERS) {\n if (existsSync(path.join(currentDir, marker))) {\n return currentDir;\n }\n }\n\n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) {\n return process.cwd();\n }\n\n currentDir = parentDir;\n }\n}\n\nfunction isLogSinkWorkspaceSupported(workspaceRoot: string): boolean {\n return existsSync(path.join(workspaceRoot, 'packages/mcp/log-sink-mcp/package.json'));\n}\n\nasync function resolveLogSinkEndpoint(env: NodeJS.ProcessEnv, workspaceRoot: string): Promise<string | undefined> {\n const result = await resolveLogSinkPort({ env, workspaceRoot });\n return result?.endpoint;\n}\n\nfunction withSignalPath(baseUrl: string, signal: 'traces' | 'logs'): string {\n const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;\n if (normalizedBaseUrl.endsWith(`/v1/${signal}/`) || normalizedBaseUrl.endsWith(`/v1/${signal}`)) {\n return baseUrl;\n }\n\n return new URL(`v1/${signal}`, normalizedBaseUrl).toString();\n}\n\nfunction toAttributeValue(value: unknown): string | number | boolean {\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return value;\n }\n\n if (value == null) {\n return '';\n }\n\n return JSON.stringify(value);\n}\n\nfunction sanitizeAttributes(attributes?: Attributes): Attributes | undefined {\n if (!attributes) {\n return undefined;\n }\n\n const sanitized: Attributes = {};\n for (const [key, value] of Object.entries(attributes)) {\n if (value === undefined || value === null) {\n continue;\n }\n\n sanitized[key] = toAttributeValue(value);\n }\n\n return Object.keys(sanitized).length > 0 ? sanitized : undefined;\n}\n\nfunction mapSeverity(level: TelemetryLevel): SeverityNumber {\n switch (level) {\n case 'trace':\n return SeverityNumber.TRACE;\n case 'debug':\n return SeverityNumber.DEBUG;\n case 'info':\n return SeverityNumber.INFO;\n case 'warn':\n return SeverityNumber.WARN;\n case 'error':\n return SeverityNumber.ERROR;\n case 'fatal':\n return SeverityNumber.FATAL;\n }\n}\n\nfunction getActiveSpanContext(): { traceId?: string; spanId?: string } {\n const activeSpan = trace.getSpan(context.active());\n if (!activeSpan) {\n return {};\n }\n\n const spanContext = activeSpan.spanContext();\n return {\n traceId: spanContext.traceId,\n spanId: spanContext.spanId,\n };\n}\n\nfunction serializeLogRecord(level: TelemetryLevel, message: string, options: NodeTelemetryLogOptions = {}): string {\n const activeSpan = trace.getSpan(options.context ?? context.active());\n const spanContext = activeSpan?.spanContext();\n\n return JSON.stringify({\n timestamp: new Date().toISOString(),\n level,\n message,\n traceId: spanContext?.traceId,\n spanId: spanContext?.spanId,\n attributes: options.attributes ? sanitizeAttributes(options.attributes) : undefined,\n exception:\n options.exception instanceof Error\n ? { name: options.exception.name, message: options.exception.message, stack: options.exception.stack }\n : options.exception,\n });\n}\n\nclass RotatingFileSink {\n private pending: Promise<void> = Promise.resolve();\n\n constructor(private readonly options: FileSinkOptions) {}\n\n write(level: TelemetryLevel, message: string, options?: NodeTelemetryLogOptions): void {\n this.pending = this.pending\n .then(async () => {\n const entry = `${serializeLogRecord(level, message, options)}\\n`;\n await this.ensureDirectory();\n await this.rotateIfNeeded(Buffer.byteLength(entry));\n await appendFile(this.options.filePath, entry, 'utf8');\n })\n .catch((error) => {\n console.error(`[log-sink-mcp telemetry] Failed to write log file ${this.options.filePath}:`, error);\n });\n }\n\n async flush(): Promise<void> {\n await this.pending;\n }\n\n async shutdown(): Promise<void> {\n await this.flush();\n }\n\n private async ensureDirectory(): Promise<void> {\n await mkdir(path.dirname(this.options.filePath), { recursive: true });\n }\n\n private async rotateIfNeeded(incomingBytes: number): Promise<void> {\n let currentSize = 0;\n try {\n currentSize = (await stat(this.options.filePath)).size;\n } catch {\n currentSize = 0;\n }\n\n if (currentSize + incomingBytes <= this.options.maxFileSizeBytes) {\n return;\n }\n\n for (let index = this.options.maxFileCount - 1; index >= 1; index -= 1) {\n const source = `${this.options.filePath}.${index}`;\n const target = `${this.options.filePath}.${index + 1}`;\n if (existsSync(source)) {\n await rename(source, target).catch(() => undefined);\n }\n }\n\n if (existsSync(this.options.filePath)) {\n await rename(this.options.filePath, `${this.options.filePath}.1`).catch(() => undefined);\n }\n }\n}\n\nfunction createOtelLogger(\n logger: OtelLogger,\n sink: { flush(): Promise<void>; shutdown(): Promise<void> },\n): NodeTelemetryLogger {\n return {\n trace(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.TRACE,\n severityText: 'TRACE',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n debug(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.DEBUG,\n severityText: 'DEBUG',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n info(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.INFO,\n severityText: 'INFO',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n warn(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.WARN,\n severityText: 'WARN',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n error(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.ERROR,\n severityText: 'ERROR',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n fatal(message, options) {\n logger.emit({\n severityNumber: SeverityNumber.FATAL,\n severityText: 'FATAL',\n body: message,\n attributes: sanitizeAttributes(options?.attributes),\n context: options?.context ?? context.active(),\n exception: options?.exception,\n });\n },\n getTraceContext: getActiveSpanContext,\n flush: sink.flush,\n shutdown: sink.shutdown,\n };\n}\n\nfunction createFileLogger(sink: RotatingFileSink): NodeTelemetryLogger {\n return {\n trace(message, options) {\n sink.write('trace', message, options);\n },\n debug(message, options) {\n sink.write('debug', message, options);\n },\n info(message, options) {\n sink.write('info', message, options);\n },\n warn(message, options) {\n sink.write('warn', message, options);\n },\n error(message, options) {\n sink.write('error', message, options);\n },\n fatal(message, options) {\n sink.write('fatal', message, options);\n },\n getTraceContext: getActiveSpanContext,\n flush: () => sink.flush(),\n shutdown: () => sink.shutdown(),\n };\n}\n\nexport async function createNodeTelemetry(options: NodeTelemetryOptions): Promise<NodeTelemetryHandle> {\n const env = options.env ?? process.env;\n const workspaceRoot = options.workspaceRoot ?? resolveWorkspaceRoot(process.cwd());\n const serviceName = options.serviceName;\n const serviceVersion = options.serviceVersion ?? env.npm_package_version;\n const enableTraces = options.enableTraces !== false;\n const enableLogs = options.enableLogs !== false;\n const maxFileSizeBytes =\n options.maxFileSizeBytes ?? Number(env.LOG_SINK_FILE_MAX_BYTES ?? DEFAULT_MAX_FILE_SIZE_BYTES);\n const maxFileCount = options.maxFileCount ?? Number(env.LOG_SINK_FILE_MAX_FILES ?? DEFAULT_MAX_FILE_COUNT);\n const logDir = options.logDir ?? path.join(workspaceRoot, DEFAULT_LOG_DIR);\n const logFileName = options.logFileName ?? `${serviceName}.jsonl`;\n const filePath = path.join(logDir, logFileName);\n\n const sinkEndpoint = isLogSinkWorkspaceSupported(workspaceRoot)\n ? await resolveLogSinkEndpoint(env, workspaceRoot)\n : undefined;\n if (sinkEndpoint) {\n const resourceAttributes: Attributes = {\n 'service.name': serviceName,\n };\n if (serviceVersion) {\n resourceAttributes['service.version'] = serviceVersion;\n }\n\n const resource = resourceFromAttributes(resourceAttributes);\n const tracerProvider = enableTraces\n ? new NodeTracerProvider({\n resource,\n spanProcessors: [\n new BatchSpanProcessor(\n new OTLPTraceExporter({\n url: withSignalPath(sinkEndpoint, 'traces'),\n }),\n ),\n ],\n })\n : undefined;\n tracerProvider?.register();\n\n const loggerProvider = enableLogs\n ? new LoggerProvider({\n resource,\n processors: [\n new BatchLogRecordProcessor(\n new OTLPLogExporter({\n url: withSignalPath(sinkEndpoint, 'logs'),\n }),\n ),\n ],\n })\n : undefined;\n if (loggerProvider) {\n logs.setGlobalLoggerProvider(loggerProvider);\n }\n\n const sinkLogger = loggerProvider?.getLogger(serviceName, serviceVersion);\n const logger = sinkLogger\n ? createOtelLogger(sinkLogger, {\n flush: async () => {\n await Promise.allSettled([tracerProvider?.forceFlush(), loggerProvider?.forceFlush()]);\n },\n shutdown: async () => {\n await Promise.allSettled([tracerProvider?.shutdown(), loggerProvider?.shutdown()]);\n },\n })\n : createFileLogger(\n new RotatingFileSink({\n filePath,\n maxFileSizeBytes,\n maxFileCount,\n }),\n );\n\n return {\n backend: 'logsink',\n enabled: true,\n trace,\n log: logs,\n logger,\n endpoint: sinkEndpoint,\n flush: async () => {\n await Promise.allSettled([tracerProvider?.forceFlush(), loggerProvider?.forceFlush()]);\n },\n shutdown: async () => {\n await Promise.allSettled([tracerProvider?.shutdown(), loggerProvider?.shutdown()]);\n },\n };\n }\n\n const fileSink = new RotatingFileSink({\n filePath,\n maxFileSizeBytes,\n maxFileCount,\n });\n const logger = createFileLogger(fileSink);\n\n return {\n backend: 'file',\n enabled: true,\n trace,\n log: logs,\n logger,\n filePath,\n flush: () => fileSink.flush(),\n shutdown: () => fileSink.shutdown(),\n };\n}\n\nexport { trace, logs as log };\n"],"mappings":"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"}
|