|
| 1 | +const { initTracer: jaegerInitTracer } = require('jaeger-client'); |
| 2 | + |
| 3 | +// Initialize tracer |
| 4 | +export const initTracerImpl = (config) => { |
| 5 | + const tracerConfig = { |
| 6 | + serviceName: config.serviceName || 'unknown-service', |
| 7 | + sampler: config.sampler || { |
| 8 | + type: 'const', |
| 9 | + param: 1, |
| 10 | + }, |
| 11 | + reporter: config.reporter || { |
| 12 | + logSpans: false, |
| 13 | + }, |
| 14 | + }; |
| 15 | + |
| 16 | + // Optional configuration |
| 17 | + if (config.traceId128bit !== undefined) { |
| 18 | + tracerConfig.traceId128bit = config.traceId128bit; |
| 19 | + } |
| 20 | + |
| 21 | + if (config.shareRpcSpan !== undefined) { |
| 22 | + tracerConfig.shareRpcSpan = config.shareRpcSpan; |
| 23 | + } |
| 24 | + |
| 25 | + const options = {}; |
| 26 | + |
| 27 | + return jaegerInitTracer(tracerConfig, options); |
| 28 | +}; |
| 29 | + |
| 30 | +// Start span |
| 31 | +export const startSpanImpl = (tracer, operationName, options) => { |
| 32 | + const spanOptions = {}; |
| 33 | + |
| 34 | + // Handle childOf |
| 35 | + if (options.childOf) { |
| 36 | + spanOptions.childOf = options.childOf; |
| 37 | + } |
| 38 | + |
| 39 | + // Handle references - array of { refType, spanContext } |
| 40 | + if (options.references) { |
| 41 | + spanOptions.references = options.references.map(ref => { |
| 42 | + const refType = ref.refType; // SpanReferenceType ADT |
| 43 | + const type = refType.constructor.name === 'ChildOf' ? 'child_of' : 'follows_from'; |
| 44 | + return tracer.reference(type, ref.spanContext); |
| 45 | + }); |
| 46 | + } |
| 47 | + |
| 48 | + // Handle tags - Object TagValue |
| 49 | + if (options.tags) { |
| 50 | + const jsTags = {}; |
| 51 | + for (const [key, tagValue] of Object.entries(options.tags)) { |
| 52 | + jsTags[key] = tagValueToJS(tagValue); |
| 53 | + } |
| 54 | + spanOptions.tags = jsTags; |
| 55 | + } |
| 56 | + |
| 57 | + // Handle startTime - Instant is milliseconds since epoch |
| 58 | + if (options.startTime !== undefined) { |
| 59 | + spanOptions.startTime = options.startTime; |
| 60 | + } |
| 61 | + |
| 62 | + return tracer.startSpan(operationName, spanOptions); |
| 63 | +}; |
| 64 | + |
| 65 | +// Start span as child |
| 66 | +export const startSpanAsChildImpl = (tracer, operationName, parentSpan) => { |
| 67 | + return tracer.startSpan(operationName, { |
| 68 | + childOf: parentSpan.context(), |
| 69 | + }); |
| 70 | +}; |
| 71 | + |
| 72 | +// Get span context |
| 73 | +export const getSpanContextImpl = (span) => { |
| 74 | + return span.context(); |
| 75 | +}; |
| 76 | + |
| 77 | +// Convert TagValue ADT to JS value |
| 78 | +const tagValueToJS = (tagValue) => { |
| 79 | + // TagValue is an ADT: TagString, TagNumber, or TagBoolean |
| 80 | + if (tagValue.constructor.name === 'TagString') { |
| 81 | + return tagValue.value0; |
| 82 | + } else if (tagValue.constructor.name === 'TagNumber') { |
| 83 | + return tagValue.value0; |
| 84 | + } else if (tagValue.constructor.name === 'TagBoolean') { |
| 85 | + return tagValue.value0; |
| 86 | + } |
| 87 | + return tagValue; // fallback |
| 88 | +}; |
| 89 | + |
| 90 | +// Set tag |
| 91 | +export const setTagImpl = (span, key, tagValue) => { |
| 92 | + span.setTag(key, tagValueToJS(tagValue)); |
| 93 | +}; |
| 94 | + |
| 95 | +// Set multiple tags - convert Object TagValue to Object of JS values |
| 96 | +export const setTagsImpl = (span, tags) => { |
| 97 | + const jsTags = {}; |
| 98 | + for (const [key, tagValue] of Object.entries(tags)) { |
| 99 | + jsTags[key] = tagValueToJS(tagValue); |
| 100 | + } |
| 101 | + span.addTags(jsTags); |
| 102 | +}; |
| 103 | + |
| 104 | +// Log |
| 105 | +export const logImpl = (span, fields) => { |
| 106 | + span.log(fields); |
| 107 | +}; |
| 108 | + |
| 109 | +// Log with timestamp - Instant is milliseconds since epoch |
| 110 | +export const logWithTimestampImpl = (span, fields, instant) => { |
| 111 | + // Instant is a newtype wrapping milliseconds (Number) |
| 112 | + const timestamp = instant; |
| 113 | + span.log(fields, timestamp); |
| 114 | +}; |
| 115 | + |
| 116 | +// Set baggage item |
| 117 | +export const setBaggageItemImpl = (span, key, value) => { |
| 118 | + span.setBaggageItem(key, value); |
| 119 | +}; |
| 120 | + |
| 121 | +// Get baggage item |
| 122 | +export const getBaggageItemImpl = (span, key) => { |
| 123 | + return span.getBaggageItem(key) || null; |
| 124 | +}; |
| 125 | + |
| 126 | +// Set operation name |
| 127 | +export const setOperationNameImpl = (span, operationName) => { |
| 128 | + span.setOperationName(operationName); |
| 129 | +}; |
| 130 | + |
| 131 | +// Finish span |
| 132 | +export const finishSpanImpl = (span) => { |
| 133 | + span.finish(); |
| 134 | +}; |
| 135 | + |
| 136 | +// Finish span with timestamp - Instant is milliseconds since epoch |
| 137 | +export const finishSpanWithTimestampImpl = (span, instant) => { |
| 138 | + const timestamp = instant; |
| 139 | + span.finish(timestamp); |
| 140 | +}; |
| 141 | + |
| 142 | +// Close tracer |
| 143 | +export const closeTracerImpl = (tracer) => { |
| 144 | + return new Promise((resolve, reject) => { |
| 145 | + tracer.close((err) => { |
| 146 | + if (err) { |
| 147 | + reject(err); |
| 148 | + } else { |
| 149 | + resolve(); |
| 150 | + } |
| 151 | + }); |
| 152 | + }); |
| 153 | +}; |
| 154 | + |
| 155 | +// Inject span context into carrier - returns Object String |
| 156 | +export const injectImpl = (tracer, spanContext, format) => { |
| 157 | + const carrier = {}; |
| 158 | + tracer.inject(spanContext, format, carrier); |
| 159 | + return carrier; |
| 160 | +}; |
| 161 | + |
| 162 | +// Extract span context from carrier - takes Object String |
| 163 | +export const extractImpl = (tracer, format, carrier) => { |
| 164 | + return tracer.extract(format, carrier) || null; |
| 165 | +}; |
0 commit comments