diff --git a/jvm/core/src/main/kotlin/com/m3/tracing/M3Tracer.kt b/jvm/core/src/main/kotlin/com/m3/tracing/M3Tracer.kt index eedfb2a..b9c46b7 100644 --- a/jvm/core/src/main/kotlin/com/m3/tracing/M3Tracer.kt +++ b/jvm/core/src/main/kotlin/com/m3/tracing/M3Tracer.kt @@ -2,6 +2,7 @@ package com.m3.tracing import com.m3.tracing.http.HttpRequestInfo import com.m3.tracing.http.HttpRequestSpan +import com.m3.tracing.http.MutableHttpRequestInfo import javax.annotation.CheckReturnValue import javax.annotation.concurrent.ThreadSafe @@ -34,7 +35,7 @@ interface M3Tracer: AutoCloseable, TraceContext { * Caller MUST close the [HttpRequestSpan] to prevent leak. */ @CheckReturnValue - fun processOutgoingHttpRequest(request: HttpRequestInfo): HttpRequestSpan + fun processOutgoingHttpRequest(request: MutableHttpRequestInfo): HttpRequestSpan /** * Returns context bound to current thread / call stack. diff --git a/jvm/core/src/main/kotlin/com/m3/tracing/http/HttpRequestInfo.kt b/jvm/core/src/main/kotlin/com/m3/tracing/http/HttpRequestInfo.kt index 0e1162e..21692b9 100644 --- a/jvm/core/src/main/kotlin/com/m3/tracing/http/HttpRequestInfo.kt +++ b/jvm/core/src/main/kotlin/com/m3/tracing/http/HttpRequestInfo.kt @@ -22,11 +22,6 @@ interface HttpRequestInfo { * @return If given header is not available, return null. */ fun tryGetHeader(name: String): String? - - /** - * Set value into header. - */ - fun trySetHeader(name: String, value: String) } /** diff --git a/jvm/core/src/main/kotlin/com/m3/tracing/http/MutableHttpRequestInfo.kt b/jvm/core/src/main/kotlin/com/m3/tracing/http/MutableHttpRequestInfo.kt new file mode 100644 index 0000000..d2754a0 --- /dev/null +++ b/jvm/core/src/main/kotlin/com/m3/tracing/http/MutableHttpRequestInfo.kt @@ -0,0 +1,16 @@ +package com.m3.tracing.http + +/** + * Represents mutable HTTP request. + * Implementation depends on framework (Servlet, Play Framework, ...). + * + * This interface is intended NOT to consume stream of request body to prevent breaking application. + * Thus this interface does NOT provide any information depends on request body (includes request "parameter"). + */ +interface MutableHttpRequestInfo : HttpRequestInfo { + /** + * Set value into header. + * Should restrict name. Especially encoding/charset header must NOT be modified. + */ + fun trySetHeader(name: String, value: String) +} diff --git a/jvm/core/src/main/kotlin/com/m3/tracing/tracer/logging/M3LoggingTracer.kt b/jvm/core/src/main/kotlin/com/m3/tracing/tracer/logging/M3LoggingTracer.kt index 7850804..b60a221 100644 --- a/jvm/core/src/main/kotlin/com/m3/tracing/tracer/logging/M3LoggingTracer.kt +++ b/jvm/core/src/main/kotlin/com/m3/tracing/tracer/logging/M3LoggingTracer.kt @@ -6,6 +6,7 @@ import com.m3.tracing.TraceSpan import com.m3.tracing.http.HttpRequestInfo import com.m3.tracing.http.HttpRequestSpan import com.m3.tracing.http.HttpResponseInfo +import com.m3.tracing.http.MutableHttpRequestInfo import org.slf4j.LoggerFactory /** @@ -38,7 +39,7 @@ class M3LoggingTracer: M3Tracer { override fun startChildSpan(name: String): TraceSpan = TraceSpanImpl(name) } - override fun processOutgoingHttpRequest(request: HttpRequestInfo): HttpRequestSpan = object: TraceSpanImpl("HTTP ${request.url}"), HttpRequestSpan { + override fun processOutgoingHttpRequest(request: MutableHttpRequestInfo): HttpRequestSpan = object: TraceSpanImpl("HTTP ${request.url}"), HttpRequestSpan { private var e: Throwable? = null override fun setError(e: Throwable?) { this.e = e diff --git a/jvm/opencensus/src/main/kotlin/com/m3/tracing/tracer/opencensus/HttpRequestTracer.kt b/jvm/opencensus/src/main/kotlin/com/m3/tracing/tracer/opencensus/HttpRequestTracer.kt index 3f1b4b5..7918172 100644 --- a/jvm/opencensus/src/main/kotlin/com/m3/tracing/tracer/opencensus/HttpRequestTracer.kt +++ b/jvm/opencensus/src/main/kotlin/com/m3/tracing/tracer/opencensus/HttpRequestTracer.kt @@ -22,8 +22,8 @@ internal class HttpRequestTracer( } } @VisibleForTesting - internal val setter = object: TextFormat.Setter() { - override fun put(carrier: HttpRequestInfo, key: String, value: String) { + internal val setter = object: TextFormat.Setter() { + override fun put(carrier: MutableHttpRequestInfo, key: String, value: String) { return carrier.trySetHeader(key, value) } } @@ -38,7 +38,7 @@ internal class HttpRequestTracer( it.init() } - fun processClientRequest(request: HttpRequestInfo) = HttpClientRequestSpanImpl(clientHandler, tracer, request).also { + fun processClientRequest(request: MutableHttpRequestInfo) = HttpClientRequestSpanImpl(clientHandler, tracer, request).also { it.init() } } @@ -100,9 +100,9 @@ internal class HttpRequestSpanImpl( } internal class HttpClientRequestSpanImpl( - private val handler: HttpClientHandler, + private val handler: HttpClientHandler, override val tracer: Tracer, - private val request: HttpRequestInfo + private val request: MutableHttpRequestInfo ): TraceSpanImpl(null), HttpRequestSpan { companion object { private val logger = LoggerFactory.getLogger(HttpRequestTracer::class.java) diff --git a/jvm/opencensus/src/main/kotlin/com/m3/tracing/tracer/opencensus/M3OpenCensusTracer.kt b/jvm/opencensus/src/main/kotlin/com/m3/tracing/tracer/opencensus/M3OpenCensusTracer.kt index 0a90fcc..6de615a 100644 --- a/jvm/opencensus/src/main/kotlin/com/m3/tracing/tracer/opencensus/M3OpenCensusTracer.kt +++ b/jvm/opencensus/src/main/kotlin/com/m3/tracing/tracer/opencensus/M3OpenCensusTracer.kt @@ -6,6 +6,7 @@ import com.m3.tracing.TraceContext import com.m3.tracing.TraceSpan import com.m3.tracing.http.HttpRequestInfo import com.m3.tracing.http.HttpRequestSpan +import com.m3.tracing.http.MutableHttpRequestInfo import com.m3.tracing.internal.Config import io.grpc.Context import io.opencensus.common.Scope @@ -65,7 +66,7 @@ class M3OpenCensusTracer internal constructor( override fun processIncomingHttpRequest(request: HttpRequestInfo): HttpRequestSpan = httpRequestTracer.processRequest(request) - override fun processOutgoingHttpRequest(request: HttpRequestInfo): HttpRequestSpan = httpRequestTracer.processClientRequest(request) + override fun processOutgoingHttpRequest(request: MutableHttpRequestInfo): HttpRequestSpan = httpRequestTracer.processClientRequest(request) private fun createSampler() = SamplerFactory.createSampler( Config[samplingConfigName] ?: "never" diff --git a/jvm/servlet/src/main/kotlin/com/m3/tracing/tracer/servlet/ServletHttpRequestInfo.kt b/jvm/servlet/src/main/kotlin/com/m3/tracing/tracer/servlet/ServletHttpRequestInfo.kt index 1e0130f..7dc6e6e 100644 --- a/jvm/servlet/src/main/kotlin/com/m3/tracing/tracer/servlet/ServletHttpRequestInfo.kt +++ b/jvm/servlet/src/main/kotlin/com/m3/tracing/tracer/servlet/ServletHttpRequestInfo.kt @@ -10,7 +10,6 @@ open class ServletHttpRequestInfo(protected val req: HttpServletRequest): HttpRe // Thus this filter should not do anything breaks setCharacterEncoding() even after FilterCain. override fun tryGetHeader(name: String): String? = req.getHeader(name) - override fun trySetHeader(name: String, value: String) = Unit // Do nothing @Suppress("UNCHECKED_CAST", "IMPLICIT_ANY") override fun tryGetMetadata(key: HttpRequestMetadataKey): T? = when(key) { diff --git a/jvm/spring-web/src/main/kotlin/com/m3/tracing/spring/http/client/SpringHttpRequestInfo.kt b/jvm/spring-web/src/main/kotlin/com/m3/tracing/spring/http/client/SpringHttpRequestInfo.kt index 952b7b0..df7100a 100644 --- a/jvm/spring-web/src/main/kotlin/com/m3/tracing/spring/http/client/SpringHttpRequestInfo.kt +++ b/jvm/spring-web/src/main/kotlin/com/m3/tracing/spring/http/client/SpringHttpRequestInfo.kt @@ -2,11 +2,26 @@ package com.m3.tracing.spring.http.client import com.m3.tracing.http.HttpRequestInfo import com.m3.tracing.http.HttpRequestMetadataKey +import com.m3.tracing.http.MutableHttpRequestInfo +import org.slf4j.LoggerFactory import org.springframework.http.HttpRequest -open class SpringHttpRequestInfo(protected val req: HttpRequest): HttpRequestInfo { +open class SpringHttpRequestInfo(protected val req: HttpRequest): MutableHttpRequestInfo { + companion object { + private val acceptableHeaders = listOf( + "traceparent", "tracestate", + "X-B3-TraceId", "X-B3-SpanId", "X-B3-Sampled", + "X-Cloud-Trace-Context" + ) + private val logger = LoggerFactory.getLogger(SpringHttpRequestInfo::class.java) + } + override fun tryGetHeader(name: String): String? = req.headers.getFirst(name) - override fun trySetHeader(name: String, value: String) = req.headers.set(name, value) + override fun trySetHeader(name: String, value: String) = if (acceptableHeaders.contains(name)) { + req.headers.set(name, value) + } else { + logger.error("Failed to set header name: ${name}, value: ${value}, it's not accepatable") + } @Suppress("UNCHECKED_CAST", "IMPLICIT_ANY") override fun tryGetMetadata(key: HttpRequestMetadataKey): T? = when(key) {