Skip to content

Commit 4d989fe

Browse files
authored
Add more tracing tests (#58)
Motivation: The OTel tracing interceptors have a few shortcomings which need fixing. This includes ending the span too early. This change introduces a number of new tests which test client and server end-to-end. These tests currently fail because of the aforementioned issues so are disabled. Modifications: - Add echo service - Add tracing tests Result: Better test coverage
1 parent 3b9e5a5 commit 4d989fe

File tree

5 files changed

+545
-3
lines changed

5 files changed

+545
-3
lines changed

Package.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ let dependencies: [Package.Dependency] = [
5555
),
5656
.package(
5757
url: "https://github.com/apple/swift-distributed-tracing.git",
58-
from: "1.1.2"
58+
from: "1.3.0"
5959
),
6060
.package(
6161
url: "https://github.com/swift-server/swift-service-lifecycle.git",
@@ -145,8 +145,10 @@ let targets: [Target] = [
145145
dependencies: [
146146
.target(name: "GRPCOTelTracingInterceptors"),
147147
.product(name: "GRPCCore", package: "grpc-swift-2"),
148+
.product(name: "GRPCInProcessTransport", package: "grpc-swift-2"),
148149
.product(name: "GRPCProtobuf", package: "grpc-swift-protobuf"),
149150
.product(name: "Tracing", package: "swift-distributed-tracing"),
151+
.product(name: "InMemoryTracing", package: "swift-distributed-tracing"),
150152
],
151153
swiftSettings: defaultSwiftSettings
152154
),

Sources/GRPCOTelTracingInterceptors/Tracing/ClientOTelTracingInterceptor.swift

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public struct ClientOTelTracingInterceptor: ClientInterceptor {
3838
private let traceEachMessage: Bool
3939
private var includeRequestMetadata: Bool
4040
private var includeResponseMetadata: Bool
41+
private let tracerOverride: (any Tracer)?
4142

4243
/// Create a new instance of a ``ClientOTelTracingInterceptor``.
4344
///
@@ -80,13 +81,32 @@ public struct ClientOTelTracingInterceptor: ClientInterceptor {
8081
traceEachMessage: Bool = true,
8182
includeRequestMetadata: Bool = false,
8283
includeResponseMetadata: Bool = false
84+
) {
85+
self.init(
86+
serverHostname: serverHostname,
87+
networkTransportMethod: networkTransportMethod,
88+
traceEachMessage: traceEachMessage,
89+
includeRequestMetadata: includeRequestMetadata,
90+
includeResponseMetadata: includeResponseMetadata,
91+
tracerOverride: nil
92+
)
93+
}
94+
95+
package init(
96+
serverHostname: String,
97+
networkTransportMethod: String,
98+
traceEachMessage: Bool,
99+
includeRequestMetadata: Bool,
100+
includeResponseMetadata: Bool,
101+
tracerOverride: (any Tracer)?
83102
) {
84103
self.injector = ClientRequestInjector()
85104
self.serverHostname = serverHostname
86105
self.networkTransportMethod = networkTransportMethod
87106
self.traceEachMessage = traceEachMessage
88107
self.includeRequestMetadata = includeRequestMetadata
89108
self.includeResponseMetadata = includeResponseMetadata
109+
self.tracerOverride = tracerOverride
90110
}
91111

92112
/// This interceptor will inject as the request's metadata whatever `ServiceContext` key-value pairs
@@ -108,7 +128,7 @@ public struct ClientOTelTracingInterceptor: ClientInterceptor {
108128
) async throws -> StreamingClientResponse<Output>
109129
) async throws -> StreamingClientResponse<Output> where Input: Sendable, Output: Sendable {
110130
try await self.intercept(
111-
tracer: InstrumentationSystem.tracer,
131+
tracer: self.tracerOverride ?? InstrumentationSystem.tracer,
112132
request: request,
113133
context: context,
114134
next: next

Sources/GRPCOTelTracingInterceptors/Tracing/ServerOTelTracingInterceptor.swift

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ public struct ServerOTelTracingInterceptor: ServerInterceptor {
3838
private var includeRequestMetadata: Bool
3939
private var includeResponseMetadata: Bool
4040

41+
private var tracerOverride: (any Tracer)?
42+
4143
/// Create a new instance of a ``ServerOTelTracingInterceptor``.
4244
///
4345
/// - Parameters:
@@ -79,13 +81,32 @@ public struct ServerOTelTracingInterceptor: ServerInterceptor {
7981
traceEachMessage: Bool = true,
8082
includeRequestMetadata: Bool = false,
8183
includeResponseMetadata: Bool = false
84+
) {
85+
self.init(
86+
serverHostname: serverHostname,
87+
networkTransportMethod: networkTransportMethod,
88+
traceEachMessage: traceEachMessage,
89+
includeRequestMetadata: includeRequestMetadata,
90+
includeResponseMetadata: includeResponseMetadata,
91+
tracerOverride: nil
92+
)
93+
}
94+
95+
package init(
96+
serverHostname: String,
97+
networkTransportMethod: String,
98+
traceEachMessage: Bool,
99+
includeRequestMetadata: Bool,
100+
includeResponseMetadata: Bool,
101+
tracerOverride: (any Tracer)?
82102
) {
83103
self.extractor = ServerRequestExtractor()
84104
self.traceEachMessage = traceEachMessage
85105
self.serverHostname = serverHostname
86106
self.networkTransportMethod = networkTransportMethod
87107
self.includeRequestMetadata = includeRequestMetadata
88108
self.includeResponseMetadata = includeResponseMetadata
109+
self.tracerOverride = tracerOverride
89110
}
90111

91112
/// This interceptor will extract whatever `ServiceContext` key-value pairs have been inserted into the
@@ -107,7 +128,7 @@ public struct ServerOTelTracingInterceptor: ServerInterceptor {
107128
StreamingServerResponse<Output>
108129
) async throws -> StreamingServerResponse<Output> where Input: Sendable, Output: Sendable {
109130
try await self.intercept(
110-
tracer: InstrumentationSystem.tracer,
131+
tracer: self.tracerOverride ?? InstrumentationSystem.tracer,
111132
request: request,
112133
context: context,
113134
next: next
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2025, gRPC Authors All rights reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
internal import GRPCCore
18+
internal import SwiftProtobuf
19+
20+
@available(gRPCSwiftExtras 2.0, *)
21+
struct EchoService: Echo_Echo.ServiceProtocol {
22+
func get(
23+
request: ServerRequest<Echo_EchoRequest>,
24+
context: ServerContext
25+
) async throws -> ServerResponse<Echo_EchoResponse> {
26+
return ServerResponse(message: .with { $0.text = request.message.text })
27+
}
28+
29+
func collect(
30+
request: StreamingServerRequest<Echo_EchoRequest>,
31+
context: ServerContext
32+
) async throws -> ServerResponse<Echo_EchoResponse> {
33+
let messages = try await request.messages.reduce(into: []) { $0.append($1.text) }
34+
let joined = messages.joined(separator: " ")
35+
return ServerResponse(message: .with { $0.text = joined })
36+
}
37+
38+
func expand(
39+
request: ServerRequest<Echo_EchoRequest>,
40+
context: ServerContext
41+
) async throws -> StreamingServerResponse<Echo_EchoResponse> {
42+
return StreamingServerResponse { response in
43+
let parts = request.message.text.split(separator: " ")
44+
let messages = parts.map { part in Echo_EchoResponse.with { $0.text = String(part) } }
45+
try await response.write(contentsOf: messages)
46+
47+
return [:]
48+
}
49+
}
50+
51+
func update(
52+
request: StreamingServerRequest<Echo_EchoRequest>,
53+
context: ServerContext
54+
) async throws -> StreamingServerResponse<Echo_EchoResponse> {
55+
return StreamingServerResponse { response in
56+
for try await message in request.messages {
57+
try await response.write(.with { $0.text = message.text })
58+
}
59+
60+
return [:]
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)