Ich habe den benutzerdefinierten Ausbreitungsmechanismus implementiert, da ich einen anderen Headernamen (nicht x-b3-Traceid) zur Verfolgung verwenden möchte. Wie kann ich dieses Verhalten wiederholen, aber anstatt B3Propagation zu verwenden, verwenden Sie meine eigene Implementierung?
Ich habe den benutzerdefinierten Ausbreitungsmechanismus implementiert, da ich einen anderen Headernamen (nicht x-b3-Traceid) zur Verfolgung verwenden möchte. Wie kann ich dieses Verhalten wiederholen, aber anstatt B3Propagation zu verwenden, verwenden Sie meine eigene Implementierung?[code]package com.example.demo
@Component class CustomPropagator : Propagation.Factory(), Propagation {
override fun keys(): List { return HEADER_KEYS }
override fun injector(setter: Propagation.Setter): TraceContext.Injector { return TraceContext.Injector { traceContext: TraceContext, request: R -> setter.put(request, ApplicationHeaders.TRACE_ID, traceContext.traceIdString()) setter.put(request, ApplicationHeaders.SPAN_ID, traceContext.spanIdString()) val parentId: String = traceContext.parentIdString() if (!parentId.isEmpty()) setter.put(request, B3_PARENT_SPAN_ID, parentId) if (traceContext.debug()) { setter.put(request, B3_FLAGS, "1") } else if (traceContext.sampled() != null) { setter.put(request, B3_SAMPLED, if (traceContext.sampled()) "1" else "0") } } }
override fun extractor(getter: Propagation.Getter): TraceContext.Extractor {
return TraceContext.Extractor { request: R -> if (request == null) throw NullPointerException("request == null") val sampled = getter[request, B3_SAMPLED] val sampledV: Boolean? sampledV = if (sampled == null) { null // defer decision } else if (sampled.length == 1) { // handle fast valid paths val sampledC = sampled[0] if (sampledC == '1') { true } else if (sampledC == '0') { false } else { // todo Platform.get().log(B3_SAMPLED_MALFORMED, sampled, null) return@Extractor TraceContextOrSamplingFlags.EMPTY // trace context is malformed so return empty } } else if (sampled.equals("true", ignoreCase = true)) { // old clients true } else if (sampled.equals("false", ignoreCase = true)) { // old clients false } else { Platform.get().log(B3_SAMPLED_MALFORMED, sampled, null) return@Extractor TraceContextOrSamplingFlags.EMPTY // Restart trace instead of propagating false }
// The only flag we action is 1, but it could be that any integer is present. // Here, we leniently parse as debug is not a primary consideration of the trace context. val debug = "1" == getter[request, B3_FLAGS]
val traceIdString = getter[request, B3_TRACE_ID] ?: getter[request, ApplicationHeaders.TRACE_ID] val spanIdString = getter[request, B3_SPAN_ID] ?: getter[request, ApplicationHeaders.SPAN_ID]
// It is ok to go without a trace ID, if sampling or debug is set if (traceIdString == null) { if (debug) return@Extractor TraceContextOrSamplingFlags.DEBUG if (sampledV != null) { return@Extractor if (sampledV) TraceContextOrSamplingFlags.SAMPLED else TraceContextOrSamplingFlags.NOT_SAMPLED } }
// Try to parse the trace IDs into the context val traceContextBuilder = TraceContext.newBuilder() val traceIdFilled = traceContextBuilder.fillTraceId(traceIdString, "trace id") val spanIdFilled = traceContextBuilder.fillSpanId(spanIdString, "span id") val parentIdFilled = traceContextBuilder.fillParentId(getter, request, "parent id") if (traceIdFilled && spanIdFilled && parentIdFilled) { if (sampledV != null) traceContextBuilder.sampled(sampledV) if (debug) traceContextBuilder.debug(true) return@Extractor TraceContextOrSamplingFlags.create(traceContextBuilder.build()) }
override fun create(keyFactory: Propagation.KeyFactory): Propagation { return StringPropagationAdapter.create(this, keyFactory) }
companion object { const val B3_TRACE_ID = "X-B3-TraceId" const val B3_SPAN_ID = "X-B3-SpanId" const val B3_PARENT_SPAN_ID = "X-B3-ParentSpanId" const val B3_SAMPLED = "X-B3-Sampled" const val B3_SAMPLED_MALFORMED = "Invalid input: expected 0 or 1 for $B3_SAMPLED, but found '{0}'" const val B3_FLAGS = "X-B3-Flags" val HEADER_KEYS = listOf( B3_TRACE_ID, B3_SPAN_ID, B3_PARENT_SPAN_ID, B3_SAMPLED, B3_FLAGS, "X-trace-id" "X-span-id" ) } }
private fun TraceContext.Builder.fillParentId( getter: Propagation.Getter, request: R, key: String ): Boolean { val parentIdString = getter[request, key] ?: return true // absent parent is ok
val length = parentIdString.length if (isIdLengthInvalid(key, length, 16)) return false
val parentIdLong = HexCodec.lenientLowerHexToUnsignedLong(parentIdString, 0, length) parentId(parentIdLong) if (parentIdLong != 0L) return true Platform.get().log("{0} is not a lower-hex string", parentIdString, null) return false }
private fun TraceContext.Builder.fillSpanId(spanIdString: String?, key: String): Boolean { if (spanIdString == null) return false val length = spanIdString.length if (isIdLengthInvalid(key, length, 16)) return false
val spanIdLong = HexCodec.lenientLowerHexToUnsignedLong(spanIdString, 0, length) spanId(spanIdLong) if (spanIdLong == 0L) { if (isAllZeros(spanIdString, 0, length)) { Platform.get().log("Invalid input: spanId was all zeros", null) return false } Platform.get().log("{0} is not a lower-hex string", spanIdString, null) return false } return true }
private fun TraceContext.Builder.fillTraceId(traceIdString: String?, key: String): Boolean { if (traceIdString == null) return false val length = traceIdString.length if (isIdLengthInvalid(key, length, 32)) return false var traceIdHighAllZeros = false var traceIdAllZeros = false // left-most characters, if any, are the high bits val traceIdIndex = Math.max(0, length - 16) var traceIdHigh = 0L if (traceIdIndex > 0) { traceIdHigh = HexCodec.lenientLowerHexToUnsignedLong(traceIdString, 0, traceIdIndex) traceIdHigh(HexCodec.lenientLowerHexToUnsignedLong(traceIdString, 0, traceIdIndex)) if (traceIdHigh == 0L) { traceIdHighAllZeros = isAllZeros(traceIdString, 0, traceIdIndex) if (!traceIdHighAllZeros) { Platform.get().log("{0} is not a lower-hex string", traceIdString, null) return false } } } else { traceIdHighAllZeros = true }
// right-most up to 16 characters are the low bits val traceIdLong = HexCodec.lenientLowerHexToUnsignedLong(traceIdString, traceIdIndex, length) traceId(HexCodec.lenientLowerHexToUnsignedLong(traceIdString, traceIdIndex, length)) if (traceIdLong == 0L) { traceIdAllZeros = isAllZeros(traceIdString, traceIdIndex, length) if (!traceIdAllZeros) { Platform.get().log("{0} is not a lower-hex string", traceIdString, null) return false } } if (traceIdHighAllZeros && traceIdAllZeros) { Platform.get().log("Invalid input: traceId was all zeros", null) } return traceIdHigh != 0L || traceIdLong != 0L }
fun isIdLengthInvalid(key: String, length: Int, max: Int): Boolean { if (length > 1 && length Hier sind Eigenschaften: < /p> spring.sleuth.baggage.remote-fields=kek spring.sleuth.baggage.correlation-fields=kek spring.sleuth.baggage.tag-fields=kek spring.sleuth.propagation.type=custom < /code> Hier ist das Logback -Muster < /p> [%d{yyyy-MM-dd HH:mm:ss.SSS}] [%X{traceId:-}/%X{spanId:-}] [%X{kek:-}] %highlight(%-5level) %cyan(%-40.40logger{39}) : %message %n%whitespace_exception [/code] Wenn ich CustomPropagator kommentiere, funktioniert es wie erwartet, der Header -Wert "KEK" erscheint in den Protokollen.[code]2020.0.3
Ich implementiere BFS (Breite erster Suche) nach dem Diagramm, aber ich erhalte einen Fehler, während ich den Startwert des Vektors an eine Ganzzahl übergeben kann, damit die DFS -Funktion wie in der...
Nach dem Upgrade auf Spring Boot 3.4.0 (Spring Web 6.2.0) schlugen meine Gateway-Filtertests fehl. Die Tests haben zuvor überprüft, dass die Anforderungsheader korrekt geändert wurden, aber jetzt...
Ich habe einen Datenfluss in einer Fastapi -Anwendung, bei der ein potenziell sehr großer HTTP -Put -Körper hochgeladen wird, und ich muss dies auf Google Cloud -Speicher streamen. Ich verwende die...