Skip to main content
Glama
telemetry.ts6.38 kB
import { RUNNER_ACCEPT_HEADER } from '../../constants.js'; import { PostmanAPIClient } from '../../clients/postman.js'; import { ExecutionResult, TelemetryPayload } from './models.js'; import { v4 as uuidv4 } from 'uuid'; export function buildTelemetryPayload( collectionId: string, collectionName: string, result: ExecutionResult ): TelemetryPayload { const durationMs = result.durationMs; const stats = result.summary?.run?.stats || {}; const iterations = stats.iterations || { total: 0, pending: 0, failed: 0 }; const items = stats.items || { total: 0, pending: 0, failed: 0 }; const scripts = stats.scripts || { total: 0, pending: 0, failed: 0 }; const prerequests = stats.prerequests || { total: 0, pending: 0, failed: 0 }; const requests = stats.requests || { total: 0, pending: 0, failed: 0 }; const tests = stats.tests || { total: 0, pending: 0, failed: 0 }; const assertions = stats.assertions || { total: 0, pending: 0, failed: 0 }; const testScripts = stats.testScripts || { total: 0, pending: 0, failed: 0 }; const prerequestScripts = stats.prerequestScripts || { total: 0, pending: 0, failed: 0 }; const responses = result.summary?.run?.executions || []; const totalResponseTime = responses.reduce((sum: number, exec: any) => { return sum + (exec?.response?.responseTime || 0); }, 0); const averageResponseTime = responses.length > 0 ? totalResponseTime / responses.length : 0; const totalDataReceived = responses.reduce((sum: number, exec: any) => { return sum + (exec?.response?.responseSize || 0); }, 0); const iterationsData = (result.summary?.run?.executions || []).map((exec: any) => { const item = exec.item || {}; const request = exec.request || {}; const response = exec.response || {}; const assertions = exec.assertions || []; const testResults = assertions.map((assertion: any) => ({ name: assertion.assertion || 'Unnamed test', status: assertion.error ? 'fail' : 'pass', error: assertion.error ? { name: assertion.error.name || 'AssertionError', message: assertion.error.message || 'Unknown error', stack: assertion.error.stack || '', } : null, })); const requestData: any = { url: request.url?.toString() || '', method: request.method || 'GET', headers: request.headers || {}, }; if (request.body) { requestData.body = { mode: request.body.mode || 'raw', raw: request.body.raw || '', }; if (request.body.options) { requestData.body.options = request.body.options; } } const responseData: any = { code: response.code || 0, name: response.status || '', time: response.responseTime || 0, size: response.responseSize || 0, headers: response.headers || [], }; if (response.stream) { try { responseData.body = response.stream.toString(); } catch { responseData.body = ''; } } return { id: uuidv4(), name: item.name || 'Request', error: exec.requestError ? { name: exec.requestError.name || 'Error', message: exec.requestError.message || 'Unknown error', } : null, tests: testResults, request: requestData, response: responseData, }; }); return { collectionRun: { id: uuidv4(), collection: collectionId, name: collectionName, status: 'finished', source: 'postman-cli', delay: 0, currentIteration: iterations.total || 1, failedTestCount: result.testStats.failed, skippedTestCount: 0, passedTestCount: result.testStats.passed, totalTestCount: result.testStats.total, iterations: iterationsData.length > 0 ? [iterationsData] : [], totalTime: durationMs, totalRequests: requests.total || 0, startedAt: result.startTime, createdAt: result.endTime, branchSource: 'local', branch: process.env.GIT_BRANCH || 'main', }, runOverview: { collectionName: collectionName, runDurationInMiliseconds: durationMs, averageResponseTimeInMiliseconds: Math.round(averageResponseTime), totalDataReceivedInBytes: totalDataReceived, statistics: { iterations: { total: iterations.total || 0, pending: iterations.pending || 0, failed: iterations.failed || 0, }, items: { total: items.total || 0, pending: items.pending || 0, failed: items.failed || 0, }, scripts: { total: scripts.total || 0, pending: scripts.pending || 0, failed: scripts.failed || 0, }, prerequests: { total: prerequests.total || 0, pending: prerequests.pending || 0, failed: prerequests.failed || 0, }, requests: { total: requests.total || 0, pending: requests.pending || 0, failed: requests.failed || 0, }, tests: { total: tests.total || 0, pending: tests.pending || 0, failed: tests.failed || 0, }, assertions: { total: assertions.total || 0, pending: assertions.pending || 0, failed: assertions.failed || 0, }, testScripts: { total: testScripts.total || 0, pending: testScripts.pending || 0, failed: testScripts.failed || 0, }, prerequestScripts: { total: prerequestScripts.total || 0, pending: prerequestScripts.pending || 0, failed: prerequestScripts.failed || 0, }, responses: { total: responses.length || 0, pending: 0, failed: requests.failed || 0, totalResponseTime: Math.round(totalResponseTime), }, }, }, }; } export function reportTelemetryAsync(payload: TelemetryPayload, client: PostmanAPIClient): void { setImmediate(async () => { try { await client.post('/collectionruns', { body: JSON.stringify(payload), headers: { Accept: RUNNER_ACCEPT_HEADER, }, }); } catch (error: any) { console.error('[TelemetryReporter] Failed to post collection run data:', error.message); } }); }

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/postmanlabs/postman-mcp-server'

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