UNPKG

signoz-mcp-server

Version:

Model Context Protocol server for SigNoz observability platform

449 lines 13.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SigNozApiClient = void 0; const axios_1 = __importDefault(require("axios")); const ws_1 = __importDefault(require("ws")); const eventsource_1 = __importDefault(require("eventsource")); class SigNozApiClient { axios; baseURL; apiKey; constructor(options) { this.baseURL = options.baseURL.replace(/\/+$/, ''); // Remove trailing slashes this.apiKey = options.apiKey || ''; this.axios = axios_1.default.create({ baseURL: this.baseURL, timeout: options.timeout || 30000, headers: { 'Content-Type': 'application/json', ...(this.apiKey && { 'SIGNOZ-API-KEY': this.apiKey }), }, }); // Add retry logic this.setupRetryInterceptor(options.retries || 3); } setupRetryInterceptor(retries) { this.axios.interceptors.response.use((response) => response, async (error) => { const config = error.config; if (!config || !config.retry) { config.retry = 0; } if (config.retry < retries && this.shouldRetry(error)) { config.retry += 1; const delay = Math.pow(2, config.retry) * 1000; // Exponential backoff await new Promise(resolve => setTimeout(resolve, delay)); return this.axios.request(config); } return Promise.reject(error); }); } shouldRetry(error) { return (error.code === 'ECONNRESET' || error.code === 'ETIMEDOUT' || error.code === 'ENOTFOUND' || (error.response && [408, 429, 500, 502, 503, 504].includes(error.response.status))); } async request(config) { try { const response = await this.axios.request(config); if (response.data.status === 'error') { throw new Error(response.data.error || 'Unknown API error'); } return response.data.data || response.data; } catch (error) { if (error.response) { const errorData = error.response.data; const errorMsg = typeof errorData.error === 'string' ? errorData.error : JSON.stringify(errorData.error || errorData); throw new Error(`SigNoz API Error: ${errorMsg || error.message}`); } throw error; } } // ========== System & Health ========== async getVersion() { return this.request({ method: 'GET', url: '/api/v1/version', }); } async getHealth() { return this.request({ method: 'GET', url: '/api/v1/health', }); } async getFeatures() { return this.request({ method: 'GET', url: '/api/v1/features', }); } // ========== Query & Metrics ========== async queryRange(request) { return this.request({ method: 'POST', url: '/api/v3/query_range', data: request, }); } async queryRangeV4(request) { return this.request({ method: 'POST', url: '/api/v4/query_range', data: request, }); } async queryRangeV5(request) { return this.request({ method: 'POST', url: '/api/v5/query_range', data: request, }); } async prometheusQuery(query, time) { return this.request({ method: 'GET', url: '/api/v1/query', params: { query, time }, }); } async prometheusQueryRange(query, start, end, step) { return this.request({ method: 'GET', url: '/api/v1/query_range', params: { query, start, end, step }, }); } // ========== Services & Traces ========== async getServices(timeRange, filters) { return this.request({ method: 'POST', url: '/api/v1/services', data: { start: Math.floor(timeRange.start / 1000).toString(), end: Math.floor(timeRange.end / 1000).toString(), ...filters, }, }); } async getServicesList() { return this.request({ method: 'GET', url: '/api/v1/services/list', }); } async getTrace(traceId) { return this.request({ method: 'GET', url: `/api/v1/traces/${traceId}`, }); } async getTopOperations(service, timeRange) { return this.request({ method: 'POST', url: '/api/v1/service/top_operations', data: { service, start: Math.floor(timeRange.start / 1000).toString(), end: Math.floor(timeRange.end / 1000).toString(), }, }); } async getDependencyGraph(timeRange) { return this.request({ method: 'POST', url: '/api/v1/dependency_graph', data: { start: Math.floor(timeRange.start / 1000).toString(), end: Math.floor(timeRange.end / 1000).toString(), }, }); } // ========== Logs ========== async getLogs(params) { return this.request({ method: 'GET', url: '/api/v1/logs', params, }); } async searchLogsV3(params) { const compositeQuery = { queryType: 'builder', panelType: 'list', builderQueries: { A: { queryName: 'A', stepInterval: 60, dataSource: 'logs', aggregateOperator: 'noop', aggregateAttribute: { key: '', dataType: '', type: '', isColumn: false, isJSON: false, id: '', }, filters: params.query ? { op: 'AND', items: [ { key: 'body', op: 'contains', value: params.query, }, ], } : { op: 'AND', items: [] }, expression: 'A', disabled: false, having: [], orderBy: params.orderBy ? [{ columnName: params.orderBy, order: params.order || 'desc' }] : [], groupBy: [], limit: params.limit || 100, offset: params.offset || 0, }, }, }; return this.request({ method: 'POST', url: '/api/v3/logs', data: { start: params.start, end: params.end, compositeQuery, }, }); } async getLogFields() { return this.request({ method: 'GET', url: '/api/v1/logs/fields', }); } async aggregateLogs(params) { return this.request({ method: 'GET', url: '/api/v1/logs/aggregate', params, }); } // Live tail logs using Server-Sent Events liveTailLogs(params, onLog, onError) { const searchParams = new URLSearchParams(); if (params.q) searchParams.append('q', params.q); if (params.filters) searchParams.append('filters', params.filters); const url = `${this.baseURL}/api/v3/logs/livetail?${searchParams.toString()}`; const eventSource = new eventsource_1.default(url, { headers: { 'SIGNOZ-API-KEY': this.apiKey, }, }); eventSource.onmessage = (event) => { try { const log = JSON.parse(event.data); onLog(log); } catch (error) { onError?.(error); } }; eventSource.onerror = (error) => { onError?.(error); }; return () => eventSource.close(); } // ========== Dashboards ========== async getDashboards() { return this.request({ method: 'GET', url: '/api/v1/dashboards', }); } async getDashboard(id) { return this.request({ method: 'GET', url: `/api/v1/dashboards/${id}`, }); } async createDashboard(dashboard) { return this.request({ method: 'POST', url: '/api/v1/dashboards', data: dashboard, }); } async updateDashboard(id, dashboard) { return this.request({ method: 'PUT', url: `/api/v1/dashboards/${id}`, data: dashboard, }); } async deleteDashboard(id) { return this.request({ method: 'DELETE', url: `/api/v1/dashboards/${id}`, }); } // ========== Alerts ========== async getAlertRules() { return this.request({ method: 'GET', url: '/api/v1/rules', }); } async getAlertRule(id) { return this.request({ method: 'GET', url: `/api/v1/rules/${id}`, }); } async createAlertRule(rule) { return this.request({ method: 'POST', url: '/api/v1/rules', data: rule, }); } async updateAlertRule(id, rule) { return this.request({ method: 'PUT', url: `/api/v1/rules/${id}`, data: rule, }); } async deleteAlertRule(id) { return this.request({ method: 'DELETE', url: `/api/v1/rules/${id}`, }); } async testAlertRule(rule) { return this.request({ method: 'POST', url: '/api/v1/testRule', data: rule, }); } async getActiveAlerts() { return this.request({ method: 'GET', url: '/api/v1/alerts', }); } // ========== Notification Channels ========== async getNotificationChannels() { return this.request({ method: 'GET', url: '/api/v1/channels', }); } async createNotificationChannel(channel) { return this.request({ method: 'POST', url: '/api/v1/channels', data: channel, }); } async testNotificationChannel(channel) { return this.request({ method: 'POST', url: '/api/v1/testChannel', data: channel, }); } // ========== Infrastructure Monitoring ========== async getHosts(params) { return this.request({ method: 'POST', url: '/api/v1/hosts/list', data: params, }); } async getPods(params) { return this.request({ method: 'POST', url: '/api/v1/pods/list', data: params, }); } async getHostAttributeKeys() { return this.request({ method: 'GET', url: '/api/v1/hosts/attribute_keys', }); } async getPodAttributeKeys() { return this.request({ method: 'GET', url: '/api/v1/pods/attribute_keys', }); } // ========== Metrics Explorer ========== async getMetrics() { return this.request({ method: 'POST', url: '/api/v1/metrics', }); } async getMetricFilterKeys() { return this.request({ method: 'GET', url: '/api/v1/metrics/filters/keys', }); } async getMetricFilterValues(params) { return this.request({ method: 'POST', url: '/api/v1/metrics/filters/values', data: params, }); } // ========== Enterprise Features ========== async getActiveLicense() { return this.request({ method: 'GET', url: '/api/v3/licenses/active', }); } async activateLicense(key) { return this.request({ method: 'POST', url: '/api/v3/licenses', data: { key }, }); } // ========== WebSocket Connections ========== connectQueryProgress(queryId, onProgress, onError) { const wsUrl = this.baseURL.replace(/^http/, 'ws') + `/ws/query_progress?q=${queryId}`; const ws = new ws_1.default(wsUrl, { headers: { 'Sec-WebSocket-Protocol': this.apiKey, }, }); ws.on('message', (data) => { try { const progress = JSON.parse(data.toString()); onProgress(progress); } catch (error) { onError?.(error); } }); ws.on('error', (error) => { onError?.(error); }); return () => ws.close(); } } exports.SigNozApiClient = SigNozApiClient; //# sourceMappingURL=client.js.map