feat: production hardening — JWT security, WAL reader, tracing, 2PC real RPC, stress test fix
- JWT: getEffectiveJwtSecret() helper + warning log when not configured - WAL: readEntries() with timestamp filter for PITR - Tracing: core/tracing.nim with span recording + executeQuery integration - 2PC: real TCP RPC via sendDistTxnRpc (host='' = local fallback) - Stress test: updated comment, 10K ops confirmed with internal locks - SSTable metadata comments clarified (offsets patched correctly) - addParticipant has default params (host='', port=0)
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
## Tracing — lightweight OpenTelemetry-compatible span recording
|
||||
import std/json
|
||||
import std/times
|
||||
import std/monotimes
|
||||
import std/tables
|
||||
|
||||
type
|
||||
SpanStatus* = enum
|
||||
ssOk = "OK"
|
||||
ssError = "ERROR"
|
||||
|
||||
Span* = ref object
|
||||
traceId*: string
|
||||
spanId*: string
|
||||
parentSpanId*: string
|
||||
name*: string
|
||||
startTime*: int64 # monotonic ticks
|
||||
endTime*: int64
|
||||
durationMs*: float64
|
||||
status*: SpanStatus
|
||||
attributes*: Table[string, string]
|
||||
|
||||
Tracer* = ref object
|
||||
spans*: seq[Span]
|
||||
activeSpan*: Span
|
||||
enabled*: bool
|
||||
nextId*: uint64
|
||||
|
||||
var defaultTracer* = Tracer(spans: @[], activeSpan: nil, enabled: false, nextId: 1)
|
||||
|
||||
proc genId(tracer: Tracer): string =
|
||||
result = $tracer.nextId
|
||||
inc tracer.nextId
|
||||
|
||||
proc beginSpan*(tracer: Tracer, name: string, attributes: Table[string, string] = initTable[string, string]()): Span =
|
||||
if not tracer.enabled: return nil
|
||||
let span = Span(
|
||||
traceId: if tracer.activeSpan != nil: tracer.activeSpan.traceId else: genId(tracer),
|
||||
spanId: genId(tracer),
|
||||
parentSpanId: if tracer.activeSpan != nil: tracer.activeSpan.spanId else: "",
|
||||
name: name,
|
||||
startTime: getMonoTime().ticks(),
|
||||
attributes: attributes,
|
||||
)
|
||||
tracer.spans.add(span)
|
||||
tracer.activeSpan = span
|
||||
return span
|
||||
|
||||
proc endSpan*(tracer: Tracer, span: Span, status: SpanStatus = ssOk) =
|
||||
if span == nil or not tracer.enabled: return
|
||||
span.endTime = getMonoTime().ticks()
|
||||
span.durationMs = float64(span.endTime - span.startTime) / 1_000_000.0
|
||||
span.status = status
|
||||
if span.parentSpanId.len > 0:
|
||||
for s in tracer.spans:
|
||||
if s.spanId == span.parentSpanId:
|
||||
tracer.activeSpan = s
|
||||
return
|
||||
tracer.activeSpan = nil
|
||||
|
||||
proc setSpanError*(span: Span, msg: string) =
|
||||
if span == nil: return
|
||||
span.status = ssError
|
||||
span.attributes["error.message"] = msg
|
||||
|
||||
proc flushSpans*(tracer: Tracer): JsonNode =
|
||||
result = newJArray()
|
||||
for span in tracer.spans:
|
||||
result.add(%*{
|
||||
"traceId": span.traceId,
|
||||
"spanId": span.spanId,
|
||||
"parentSpanId": span.parentSpanId,
|
||||
"name": span.name,
|
||||
"durationMs": span.durationMs,
|
||||
"status": $span.status,
|
||||
"attributes": span.attributes,
|
||||
})
|
||||
tracer.spans = @[]
|
||||
|
||||
proc enable*(tracer: Tracer) =
|
||||
tracer.enabled = true
|
||||
|
||||
proc disable*(tracer: Tracer) =
|
||||
tracer.enabled = false
|
||||
Reference in New Issue
Block a user