Skip to main content
Glama

New Relic MCP Server

by cloudbring
otel-setup.ts5.08 kB
import { SpanKind, SpanStatusCode, trace } from '@opentelemetry/api'; import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'; import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; import { WinstonInstrumentation } from '@opentelemetry/instrumentation-winston'; import { Resource } from '@opentelemetry/resources'; import { NodeSDK } from '@opentelemetry/sdk-node'; import { BatchSpanProcessor, ConsoleSpanExporter, SimpleSpanProcessor, } from '@opentelemetry/sdk-trace-base'; import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions'; const isTest = process.env.NODE_ENV === 'test'; // Create resource with service information const createResource = () => { return Resource.default().merge( new Resource({ [ATTR_SERVICE_NAME]: process.env.OTEL_SERVICE_NAME || 'newrelic-mcp', [ATTR_SERVICE_VERSION]: process.env.npm_package_version || '1.0.0', environment: process.env.NODE_ENV || 'development', 'newrelic.account.id': process.env.NEW_RELIC_ACCOUNT_ID, }) ); }; // Configure trace exporter based on environment const createTraceExporter = () => { if (isTest) { // Use console exporter for tests return new ConsoleSpanExporter(); } if (process.env.OTEL_EXPORTER_OTLP_ENDPOINT) { // Use OTLP exporter for production/staging return new OTLPTraceExporter({ url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT, headers: process.env.OTEL_EXPORTER_OTLP_HEADERS ? JSON.parse(process.env.OTEL_EXPORTER_OTLP_HEADERS) : undefined, }); } // Default to console for development return new ConsoleSpanExporter(); }; // Create and configure the OpenTelemetry SDK let otelSDK: NodeSDK | null = null; export const initializeOpenTelemetry = () => { if (otelSDK) { return otelSDK; } const exporter = createTraceExporter(); const spanProcessor = isTest ? new SimpleSpanProcessor(exporter) : new BatchSpanProcessor(exporter); otelSDK = new NodeSDK({ resource: createResource(), spanProcessors: [spanProcessor], instrumentations: [ getNodeAutoInstrumentations({ '@opentelemetry/instrumentation-fs': { enabled: false, // Disable fs instrumentation for tests }, '@opentelemetry/instrumentation-http': { enabled: !isTest, }, }), new WinstonInstrumentation({ enabled: true, logHook: (span, record) => { // Add trace context to log records const spanContext = span.spanContext(); record['trace.id'] = spanContext.traceId; record['span.id'] = spanContext.spanId; record['trace.flags'] = spanContext.traceFlags; }, }), ], }); if (!isTest) { otelSDK.start(); console.log('OpenTelemetry initialized'); } return otelSDK; }; // Shutdown OpenTelemetry gracefully export const shutdownOpenTelemetry = async () => { if (otelSDK) { try { await otelSDK.shutdown(); console.log('OpenTelemetry shut down successfully'); otelSDK = null; } catch (error) { console.error('Error shutting down OpenTelemetry', error); } } }; // Get the current tracer export const getTracer = (name: string = 'newrelic-mcp') => { return trace.getTracer(name, process.env.npm_package_version || '1.0.0'); }; // Helper to create a span for a tool execution export const withToolSpan = async <T>( toolName: string, operation: string, fn: () => Promise<T>, attributes?: Record<string, unknown> ): Promise<T> => { const tracer = getTracer(); return tracer.startActiveSpan( `tool.${toolName}.${operation}`, { kind: SpanKind.INTERNAL, attributes: { 'tool.name': toolName, 'tool.operation': operation, ...attributes, }, }, async (span) => { try { const result = await fn(); span.setStatus({ code: SpanStatusCode.OK }); return result; } catch (error) { span.setStatus({ code: SpanStatusCode.ERROR, message: error instanceof Error ? error.message : 'Unknown error', }); span.recordException(error as Error); throw error; } finally { span.end(); } } ); }; // Helper to add custom attributes to the current span export const addSpanAttributes = (attributes: Record<string, unknown>) => { const span = trace.getActiveSpan(); if (span) { Object.entries(attributes).forEach(([key, value]) => { if (value !== undefined && value !== null) { span.setAttribute(key, value); } }); } }; // Helper to create a span event export const addSpanEvent = (name: string, attributes?: Record<string, unknown>) => { const span = trace.getActiveSpan(); if (span) { span.addEvent(name, attributes); } }; // Export for test utilities export const getTestTracer = () => { if (!isTest) { throw new Error('getTestTracer should only be used in test environment'); } return getTracer('test'); };

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cloudbring/newrelic-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server