Skip to content

Commit

Permalink
Fix bug where tracing span name isnt set (#480)
Browse files Browse the repository at this point in the history
This fixes an issue where the Tracing middleware wasn't updating the span name with the correct endpoint path when using RouterBuilder
  • Loading branch information
adam-fowler authored Jun 20, 2024
1 parent b2798b0 commit c1ff423
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 6 deletions.
14 changes: 8 additions & 6 deletions Sources/Hummingbird/Middleware/TracingMiddleware.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,8 @@ public struct TracingMiddleware<Context: RequestContext>: RouterMiddleware {
var serviceContext = ServiceContext.current ?? ServiceContext.topLevel
InstrumentationSystem.instrument.extract(request.headers, into: &serviceContext, using: HTTPHeadersExtractor())

let operationName: String = {
guard let endpointPath = context.endpointPath else {
return "HTTP \(request.method.rawValue) route not found"
}
return endpointPath
}()
// span name is updated after route has run
let operationName = "HTTP \(request.method.rawValue) route not found"

let span = InstrumentationSystem.tracer.startSpan(operationName, context: serviceContext, ofKind: .server)
span.updateAttributes { attributes in
Expand Down Expand Up @@ -85,6 +81,9 @@ public struct TracingMiddleware<Context: RequestContext>: RouterMiddleware {
do {
return try await ServiceContext.$current.withValue(span.context) {
var response = try await next(request, context)
if let endpointPath = context.endpointPath {
span.operationName = endpointPath
}
span.updateAttributes { attributes in
attributes = self.recordHeaders(response.headers, toSpanAttributes: attributes, withPrefix: "http.response.header.")

Expand All @@ -98,6 +97,9 @@ public struct TracingMiddleware<Context: RequestContext>: RouterMiddleware {
return response
}
} catch {
if let endpointPath = context.endpointPath {
span.operationName = endpointPath
}
let statusCode = (error as? HTTPResponseError)?.status.code ?? 500
span.attributes["http.status_code"] = statusCode
if 500..<600 ~= statusCode {
Expand Down
39 changes: 39 additions & 0 deletions Tests/HummingbirdTests/TracingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import HTTPTypes
import Hummingbird
import HummingbirdRouter
import HummingbirdTesting
@testable import Instrumentation
import Tracing
Expand Down Expand Up @@ -67,6 +68,44 @@ final class TracingTests: XCTestCase {
])
}

func testTracingMiddlewareWithRouterBuilder() async throws {
let expectation = expectation(description: "Expected span to be ended.")

let tracer = TestTracer()
tracer.onEndSpan = { _ in expectation.fulfill() }
InstrumentationSystem.bootstrapInternal(tracer)

let router = RouterBuilder(context: BasicRouterRequestContext.self) {
TracingMiddleware(attributes: ["net.host.name": "127.0.0.1", "net.host.port": 8080])
Get("users/{id}") { _, _ in "42" }
}
let app = Application(responder: router.buildResponder())
try await app.test(.router) { client in
try await client.execute(uri: "/users/42", method: .get) { response in
XCTAssertEqual(response.status, .ok)
XCTAssertEqual(String(buffer: response.body), "42")
}
}

await self.wait(for: [expectation], timeout: 1)

let span = try XCTUnwrap(tracer.spans.first)

XCTAssertEqual(span.operationName, "/users/{id}")
XCTAssertEqual(span.kind, .server)
XCTAssertNil(span.status)
XCTAssertTrue(span.recordedErrors.isEmpty)

XCTAssertSpanAttributesEqual(span.attributes, [
"http.method": "GET",
"http.target": "/users/42",
"http.status_code": 200,
"http.response_content_length": 2,
"net.host.name": "127.0.0.1",
"net.host.port": 8080,
])
}

func testTracingMiddlewareServerError() async throws {
let expectation = expectation(description: "Expected span to be ended.")

Expand Down

0 comments on commit c1ff423

Please sign in to comment.