UNPKG

dd-trace

Version:

Datadog APM tracing client for JavaScript

147 lines (131 loc) 4.08 kB
'use strict' const { fnv64 } = require('../datastreams/fnv') const log = require('../log') /** * PropagationHashManager is a singleton that manages the propagation hash computation. * The propagation hash is an FNV-1a 64-bit hash combining: * - Process tags (entrypoint info, package.json name, etc.) * - Container tags hash (received from the Datadog agent) * * This hash is used to correlate traces with database operations (DBM) and * data stream pathways (DSM) for enhanced observability. */ class PropagationHashManager { _containerTagsHash = null _cachedHash = null _cachedHashString = null _cachedHashBase64 = null /** @type {import('../config/config-base') | null} */ _config = null /** * Configure the propagation hash manager with tracer config * @param {import('../config/config-base')} config - Tracer configuration */ configure (config) { this._config = config } /** * Check if process tags propagation is enabled * @returns {boolean} */ isEnabled () { return this._config?.propagateProcessTags?.enabled === true } /** * Update the container tags hash received from the agent * @param {string} hash - Container tags hash from agent response */ updateContainerTagsHash (hash) { if (hash !== this._containerTagsHash) { log.debug('Updating container tags hash: %s', hash) this._containerTagsHash = hash this._invalidateCache() } } /** * Get the propagation hash as a BigInt * @returns {bigint | null} The propagation hash or null if disabled/unavailable */ getHash () { if (!this.isEnabled()) { return null } if (this._cachedHash) { return this._cachedHash } this._computeHash() return this._cachedHash } /** * Get the propagation hash as a hexadecimal string * @returns {string|null} The propagation hash in hex format or null if disabled/unavailable */ getHashString () { const hash = this.getHash() if (!hash) { return null } if (!this._cachedHashString) { this._cachedHashString = hash.toString(16) } return this._cachedHashString } /** * Get the propagation hash as a base64 string * @returns {string|null} The propagation hash in base64 format or null if disabled/unavailable */ getHashBase64 () { const hash = this.getHash() if (!hash) { return null } if (!this._cachedHashBase64) { // Convert BigInt to 8-byte buffer (64-bit hash) const buffer = Buffer.allocUnsafe(8) // Write as big-endian 64-bit unsigned integer buffer.writeBigUInt64BE(hash, 0) this._cachedHashBase64 = buffer.toString('base64') } return this._cachedHashBase64 } /** * Compute the propagation hash using FNV-1a algorithm * @private */ _computeHash () { try { const processTags = require('../process-tags') // Combine process tags and container tags hash // Process tags are already serialized as a comma-separated string const input = processTags.serialized + (this._containerTagsHash || '') if (!input) { // If both are empty, don't compute a hash this._cachedHash = null this._cachedHashString = null this._cachedHashBase64 = null return } // Compute FNV-1a 64-bit hash this._cachedHash = fnv64(input) this._cachedHashString = null // Will be computed on demand this._cachedHashBase64 = null // Will be computed on demand log.debug('Computed propagation hash from input (length=%s): "%s"', input.length, this._cachedHash.toString(16)) } catch (e) { log.error('Error computing propagation hash', e) this._cachedHash = null this._cachedHashString = null this._cachedHashBase64 = null } } /** * Invalidate the cached hash * @private */ _invalidateCache () { this._cachedHash = null this._cachedHashString = null this._cachedHashBase64 = null } } // Export singleton instance module.exports = new PropagationHashManager()