UNPKG

dd-trace

Version:

Datadog APM tracing client for JavaScript

127 lines (110 loc) 3.71 kB
'use strict' const request = require('../exporters/common/request') const log = require('../log') const { isTrue } = require('../util') const { getEnvironmentVariable } = require('../config-helper') let agentTelemetry = true function getHeaders (config, application, reqType) { const headers = { 'content-type': 'application/json', 'dd-telemetry-api-version': 'v2', 'dd-telemetry-request-type': reqType, 'dd-client-library-language': application.language_name, 'dd-client-library-version': application.tracer_version } const debug = config.telemetry && config.telemetry.debug if (debug) { headers['dd-telemetry-debug-enabled'] = 'true' } if (config.apiKey) { headers['dd-api-key'] = config.apiKey } return headers } function getAgentlessTelemetryEndpoint (site) { if (site === 'datad0g.com') { // staging return 'https://all-http-intake.logs.datad0g.com' } return `https://instrumentation-telemetry-intake.${site}` } let seqId = 0 function getPayload (payload) { // Some telemetry endpoints payloads accept collections of elements such as the 'logs' endpoint. // 'logs' request type payload is meant to send library logs to Datadog’s backend. if (Array.isArray(payload)) { return payload } const { logger, tags, serviceMapping, ...trimmedPayload } = payload return trimmedPayload } function sendData (config, application, host, reqType, payload = {}, cb = () => {}) { const { hostname, port, isCiVisibility } = config let url = config.url const isCiVisibilityAgentlessMode = isCiVisibility && isTrue(getEnvironmentVariable('DD_CIVISIBILITY_AGENTLESS_ENABLED')) if (isCiVisibilityAgentlessMode) { try { url = url || new URL(getAgentlessTelemetryEndpoint(config.site)) } catch (err) { log.error('Telemetry endpoint url is invalid', err) // No point to do the request if the URL is invalid return cb(err, { payload, reqType }) } } const options = { url, hostname, port, method: 'POST', path: isCiVisibilityAgentlessMode ? '/api/v2/apmtelemetry' : '/telemetry/proxy/api/v2/apmtelemetry', headers: getHeaders(config, application, reqType) } const data = JSON.stringify({ api_version: 'v2', naming_schema_version: config.spanAttributeSchema ?? '', request_type: reqType, tracer_time: Math.floor(Date.now() / 1000), runtime_id: config.tags['runtime-id'], seq_id: ++seqId, payload: getPayload(payload), application, host }) request(data, options, (error) => { if (error && getEnvironmentVariable('DD_API_KEY') && config.site) { if (agentTelemetry) { log.warn('Agent telemetry failed, started agentless telemetry') agentTelemetry = false } // figure out which data center to send to const backendUrl = getAgentlessTelemetryEndpoint(config.site) const backendHeader = { ...options.headers, 'DD-API-KEY': getEnvironmentVariable('DD_API_KEY') } const backendOptions = { ...options, url: backendUrl, headers: backendHeader, path: '/api/v2/apmtelemetry' } if (backendUrl) { request(data, backendOptions, (error) => { if (error) { log.error('Error sending telemetry data', error) } }) } else { log.error('Invalid Telemetry URL') } } if (!error && !agentTelemetry) { agentTelemetry = true log.info('Started agent telemetry') } // call the callback function so that we can track the error and payload cb(error, { payload, reqType }) }) } module.exports = { sendData }