Skip to main content
Glama
client.ts5.9 kB
import axios from 'axios'; import { z } from 'zod'; // Define the schema for incident data export const IncidentSchema = z.object({ id: z.string(), number: z.number(), count: z.number(), lastOccurredAt: z.string(), actionNames: z.array(z.string()), exceptionName: z.string(), state: z.string(), namespace: z.string(), firstBacktraceLine: z.string().optional(), errorGroupingStrategy: z.string().optional(), severity: z.string().optional(), }); export type Incident = z.infer<typeof IncidentSchema>; // Define the schema for sample data export const SampleSchema = z.object({ id: z.string(), appId: z.string(), time: z.string(), revision: z.string().optional(), action: z.string(), namespace: z.string(), overview: z.array(z.object({ key: z.string(), value: z.string(), })), exception: z.object({ name: z.string(), message: z.string(), backtrace: z.array(z.object({ original: z.string().optional(), line: z.number().optional(), column: z.number().optional(), path: z.string().optional(), method: z.string().optional(), url: z.string().optional(), type: z.string().optional(), code: z.object({ line: z.number().optional(), source: z.string().optional(), }).optional(), error: z.object({ class: z.string().optional(), message: z.string().optional(), }).optional(), })), }), }); export type Sample = z.infer<typeof SampleSchema>; export class AppSignalClient { private apiToken: string; private appId: string; private baseUrl: string; constructor(apiToken: string, appId: string) { this.apiToken = apiToken; this.appId = appId; this.baseUrl = 'https://appsignal.com/graphql'; } /** * Execute a GraphQL query against the AppSignal API */ private async executeQuery<T>(query: string, variables: Record<string, any>): Promise<T> { try { const response = await axios.post( `${this.baseUrl}?token=${this.apiToken}`, { query, variables, }, { headers: { 'Content-Type': 'application/json', }, } ); if (response.data.errors) { throw new Error(`GraphQL Error: ${JSON.stringify(response.data.errors)}`); } return response.data.data as T; } catch (error) { if (axios.isAxiosError(error)) { throw new Error(`API Error: ${error.message}`); } throw error; } } /** * Fetch an incident by its number */ async getIncident(incidentNumber: number): Promise<Incident> { const query = ` query IncidentQuery($appId: String!, $incidentNumber: Int!) { app(id: $appId) { id incident(incidentNumber: $incidentNumber) { ... on ExceptionIncident { id number count lastOccurredAt actionNames exceptionName state namespace firstBacktraceLine errorGroupingStrategy severity } } } } `; const result = await this.executeQuery<{ app: { id: string; incident: Incident; }; }>(query, { appId: this.appId, incidentNumber, }); return result.app.incident; } /** * Fetch a sample for a specific incident */ async getIncidentSample(incidentNumber: number, sampleId?: string): Promise<Sample> { const query = ` query IncidentSampleQuery($appId: String!, $incidentNumber: Int!, $sampleId: String) { app(id: $appId) { id incident(incidentNumber: $incidentNumber) { ... on ExceptionIncident { sample(id: $sampleId) { id appId time revision action namespace overview { key value } exception { name message backtrace { original line column path method url type code { line source } error { class message } } } } } } } } `; const result = await this.executeQuery<{ app: { id: string; incident: { sample: Sample; }; }; }>(query, { appId: this.appId, incidentNumber, sampleId, }); return result.app.incident.sample; } /** * List incidents with optional filtering */ async listIncidents(limit: number = 25, state?: string): Promise<Incident[]> { const query = ` query ExceptionIncidentsQuery( $appId: String! $limit: Int $state: IncidentStateEnum ) { app(id: $appId) { id exceptionIncidents( limit: $limit state: $state ) { id number count lastOccurredAt actionNames exceptionName state namespace firstBacktraceLine errorGroupingStrategy severity } } } `; const result = await this.executeQuery<{ app: { id: string; exceptionIncidents: Incident[]; }; }>(query, { appId: this.appId, limit, state, }); return result.app.exceptionIncidents; } }

Latest Blog Posts

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/c20020207/mcp-appsignal'

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