From ac43c0476c239a9cf1c20e838b0fd212b20161e1 Mon Sep 17 00:00:00 2001 From: Ivan Topolnjak Date: Tue, 4 Sep 2018 18:32:36 +0200 Subject: basic testing for the HTTP server instrumentation --- kamon-core-tests/src/test/resources/reference.conf | 126 ++++----------------- .../HttpServerInstrumentationSpec.scala | 65 +++++++++-- 2 files changed, 77 insertions(+), 114 deletions(-) (limited to 'kamon-core-tests') diff --git a/kamon-core-tests/src/test/resources/reference.conf b/kamon-core-tests/src/test/resources/reference.conf index d165249e..6615bb7b 100644 --- a/kamon-core-tests/src/test/resources/reference.conf +++ b/kamon-core-tests/src/test/resources/reference.conf @@ -7,117 +7,31 @@ kamon { kamon { - instrumentation { - http-server { - noop { - - # - # Configuration for HTTP context propagation - # - propagation { - - # Enables or disables HTTP context propagation on this HTTP server instrumentation. Please note that if - # propagation is disabled then some distributed tracing features will not be work as expected (e.g. Spans can - # be created and reported but will not be linked across boundaries nor take trace identifiers from tags). - enabled = no - - # HTTP propagation channel to b used by this instrumentation. Take a look at the kamon.propagation.http.default - # configuration for more details on how to configure the detault HTTP context propagation. - channel = "default" - } - - - # - # Configuration for HTTP server metrics collection - # - metrics { - - # Enables collection of HTTP server metrics - enabled = no - - # Tags to include on the HTTP server metrics. The available options are: - # - method: HTTP method from the request. - # - status-code: HTTP status code from the responses. - # - tags = [ - "method", - "status-code" - ] - } - - - # - # Configuration for HTTP request tracing - # - tracing { - - # Enables HTTP request tracing. When enabled the instrumentation will create Spans for incoming requests - # and finish them when the response is sent back to the clients. - enabled = no - - # Select a context tag that provides a custom trace identifier. The custom trace identifier will be used - # only if all these conditions are met: - # - the context tag is present. - # - there is no parent Span on the incoming context (i.e. this is the first service on the trace). - # - the identifier is valued in accordance to the identity provider. - trace-id-tag = "none" - # Enables collection of span metrics using the `span.processing-time` metric. - span-metrics = on - - # Select which tags should be included as span and span metric tags. The possible options are: - # - span: the tag is added as a Span tag (i.e. using span.tag(...)) - # - metric: the tag is added a a Span metric tag (i.e. using span.tagMetric(...)) - # - off: the tag is not used. - # - tags { - - # Use the http.url tag. - url = span - - # Use the http.method tag. - method = metric - - # Use the http.status_code tag. - status-code = metric - - # Copy tags from the context into the Spans with the specified purpouse. - from-context { - - # The peer tag identifiest the service that is calling the current service. It is added by default with - # the HttpClient instrumentation. - peer = metric - } - } + trace { + sampler = always + } - # Custom mappings between routes and operation names. - operations { + propagation.http.default { + tags.mappings { + "correlation-id" = "x-correlation-id" + } + } - # Operation name for Spans created on requests that could not be handled by any route in the current - # application. - unhandled = "unhandled" + instrumentation { + http-server { + default { + tracing.trace-id-tag = "correlation-id" + } - # Provides custom mappings from HTTP paths into operation names. Meant to be used in cases where the bytecode - # instrumentation is not able to provide a sensible operation name that is free of high cardinality values. - # For example, with the following configuration: - # mappings { - # "/organization/*/user/*/profile" = "/organization/:orgID/user/:userID/profile" - # "/events/*/rsvps" = "EventRSVPs" - # } - # - # Requests to "/organization/3651/user/39652/profile" and "/organization/22234/user/54543/profile" will have - # the same operation name "/organization/:orgID/user/:userID/profile". - # - # Similarly, requests to "/events/aaa-bb-ccc/rsvps" and "/events/1234/rsvps" will have the same operation - # name "EventRSVPs". - # - # The patterns are expressed as globs and the operation names are free form. - # - mappings { + no-span-metrics { + tracing.span-metrics = off + } - } - } - } + noop { + propagation.enabled = no + metrics.enabled = no + tracing.enabled = no } } } diff --git a/kamon-core-tests/src/test/scala/kamon/instrumentation/HttpServerInstrumentationSpec.scala b/kamon-core-tests/src/test/scala/kamon/instrumentation/HttpServerInstrumentationSpec.scala index a3662127..e31382a5 100644 --- a/kamon-core-tests/src/test/scala/kamon/instrumentation/HttpServerInstrumentationSpec.scala +++ b/kamon-core-tests/src/test/scala/kamon/instrumentation/HttpServerInstrumentationSpec.scala @@ -11,8 +11,7 @@ class HttpServerInstrumentationSpec extends WordSpec with Matchers with SpanInsp "the HTTP server instrumentation" when { "configured for context propagation" should { "read context entries and tags from the incoming request" in { - val httpServer = HttpServer.from("default", port = 8080, "http.server") - val handler = httpServer.handle(fakeRequest("http://localhost:8080/", "/", "GET", Map( + val handler = httpServer().receive(fakeRequest("http://localhost:8080/", "/", "GET", Map( "context-tags" -> "tag=value;none=0011223344556677;", "custom-trace-id" -> "0011223344556677" ))) @@ -24,8 +23,7 @@ class HttpServerInstrumentationSpec extends WordSpec with Matchers with SpanInsp } "use the configured HTTP propagation channel" in { - val httpServer = HttpServer.from("default", port = 8080, "http.server") - val handler = httpServer.handle(fakeRequest("http://localhost:8080/", "/", "GET", Map( + val handler = httpServer().receive(fakeRequest("http://localhost:8080/", "/", "GET", Map( "context-tags" -> "tag=value;none=0011223344556677;", "custom-trace-id" -> "0011223344556677" ))) @@ -41,15 +39,63 @@ class HttpServerInstrumentationSpec extends WordSpec with Matchers with SpanInsp span.tag("http.url").value shouldBe "http://localhost:8080/" val responseHeaders = mutable.Map.empty[String, String] - handler.startResponse(fakeResponse(200, responseHeaders), handler.context.withTag("hello", "world")) + handler.send(fakeResponse(200, responseHeaders), handler.context.withTag("hello", "world")) } } - "when all capabilities are disabled" should { + "configured for distributed tracing" should { + "create a span representing the current HTTP operation" in { + val handler = httpServer().receive(fakeRequest("http://localhost:8080/", "/", "GET", Map.empty)) + handler.send(fakeResponse(200, mutable.Map.empty), handler.context) + + val span = inspect(handler.span) + span.tag("http.method").value shouldBe "GET" + span.tag("http.url").value shouldBe "http://localhost:8080/" + span.tag("http.status_code").value shouldBe "200" + } + + "adopt a traceID when explicitly provided" in { + val handler = httpServer().receive(fakeRequest("http://localhost:8080/", "/", "GET", Map( + "context-tags" -> "tag=value;none=0011223344556677;", + "x-correlation-id" -> "0011223344556677" + ))) + + handler.span.context().traceID.string shouldBe "0011223344556677" + } + + "record span metrics when enabled" in { + val handler = httpServer().receive(fakeRequest("http://localhost:8080/", "/", "GET", Map.empty)) + handler.send(fakeResponse(200, mutable.Map.empty), handler.context) + + val span = inspect(handler.span) + span.hasMetricsEnabled() shouldBe true + } + + "not record span metrics when disabled" in { + val handler = HttpServer.from("no-span-metrics", port = 8081, "http.server") + .receive(fakeRequest("http://localhost:8080/", "/", "GET", Map.empty)) + handler.send(fakeResponse(200, mutable.Map.empty), handler.context) + + val span = inspect(handler.span) + span.hasMetricsEnabled() shouldBe false + } + + "receive tags from context when available" in { + val handler = httpServer().receive(fakeRequest("http://localhost:8080/", "/", "GET", Map( + "context-tags" -> "tag=value;none=0011223344556677;peer=superservice;", + "custom-trace-id" -> "0011223344556677" + ))) + + val span = inspect(handler.span) + span.tag("peer").value shouldBe "superservice" + } + } + + "all capabilities are disabled" should { "not read any context from the incoming requests" in { val httpServer = HttpServer.from("noop", port = 8081, "http.server") - val handler = httpServer.handle(fakeRequest("http://localhost:8080/", "/", "GET", Map( + val handler = httpServer.receive(fakeRequest("http://localhost:8080/", "/", "GET", Map( "context-tags" -> "tag=value;none=0011223344556677;", "custom-trace-id" -> "0011223344556677" ))) @@ -59,7 +105,7 @@ class HttpServerInstrumentationSpec extends WordSpec with Matchers with SpanInsp "not create any span to represent the server request" in { val httpServer = HttpServer.from("noop", port = 8081, "http.server") - val handler = httpServer.handle(fakeRequest("http://localhost:8080/", "/", "GET", Map( + val handler = httpServer.receive(fakeRequest("http://localhost:8080/", "/", "GET", Map( "context-tags" -> "tag=value;none=0011223344556677;", "custom-trace-id" -> "0011223344556677" ))) @@ -71,6 +117,9 @@ class HttpServerInstrumentationSpec extends WordSpec with Matchers with SpanInsp } } + def httpServer(): HttpServer = HttpServer.from("default", port = 8081, "http.server") + def noopHttpServer(): HttpServer = HttpServer.from("noop", port = 8081, "http.server") + def fakeRequest(requestUrl: String, requestPath: String, requestMethod: String, headers: Map[String, String]): HttpRequest = new HttpRequest { override def url: String = requestUrl -- cgit v1.2.3