veloze
Version:
A modern and fast express-like webserver for the web
71 lines (63 loc) • 1.75 kB
JavaScript
import { nanoid, HEX } from './random64.js'
const isHex = (str, len) => {
const reHex = new RegExp(`^[0-9a-f]{${len}}$`)
const reZero = new RegExp(`^[0]{${len}}$`)
return reHex.test(str) && !reZero.test(str)
}
/**
* @see https://www.w3.org/TR/trace-context/#traceparent-header
*/
export class TraceParent {
static VERSION = '00'
/**
* @param {{traceId?:string, parentId?:string, sampled?:boolean}} param0
*/
constructor({ traceId, parentId, sampled = false } = {}) {
this.traceId = isHex(traceId, 32) ? traceId : nanoid(32, HEX)
this.parentId = isHex(parentId, 16) ? parentId : nanoid(16, HEX)
this.sampled = !!sampled
}
/**
* parse header value
* @param {string} value
* @returns {TraceParent}
*/
static parse(value) {
if (!value || typeof value !== 'string' || value.length !== 55) {
return new TraceParent()
}
const parts = value.split('-')
if (
parts.length === 4 &&
parts[0] === TraceParent.VERSION &&
isHex(parts[1], 32) &&
isHex(parts[2], 16)
) {
// always create a new parentId as id for this request
return new TraceParent({ traceId: parts[1] })
}
return new TraceParent()
}
/**
* @param {boolean} [sampled]
* @returns {this} self
*/
update(sampled) {
this.sampled = !!sampled
this._res?.setHeader('traceparent', this.toString())
return this
}
/**
* add response object to update header on change
* @param {import('http').ServerResponse} res
*/
addResponse(res) {
this._res = res
this.update()
return this
}
toString() {
const traceFlags = this.sampled ? '01' : '00'
return `${TraceParent.VERSION}-${this.traceId}-${this.parentId}-${traceFlags}`
}
}