@@ -50,8 +50,8 @@ struct OTelTracingClientInterceptorTests {
5050 traceEachMessage: false
5151 )
5252 let methodDescriptor = MethodDescriptor (
53- fullyQualifiedService: " TracingInterceptorTests " ,
54- method: " testClientInterceptor "
53+ fullyQualifiedService: " OTelTracingClientInterceptorTests " ,
54+ method: " testSuccessfulRPC "
5555 )
5656 let testValues = self . getTestValues (
5757 addressType: addressType,
@@ -122,8 +122,8 @@ struct OTelTracingClientInterceptorTests {
122122 traceEachMessage: true
123123 )
124124 let methodDescriptor = MethodDescriptor (
125- fullyQualifiedService: " TracingInterceptorTests " ,
126- method: " testClientInterceptorAllEventsRecorded "
125+ fullyQualifiedService: " OTelTracingClientInterceptorTests " ,
126+ method: " testAllEventsRecorded "
127127 )
128128 let testValues = self . getTestValues ( addressType: . ipv4, methodDescriptor: methodDescriptor)
129129 let response = try await interceptor. intercept (
@@ -181,8 +181,8 @@ struct OTelTracingClientInterceptorTests {
181181 }
182182 }
183183
184- @Test ( " RPC resulting in error is correctly recorded " )
185- func testClientInterceptorErrorEncountered ( ) async throws {
184+ @Test ( " RPC that throws is correctly recorded " )
185+ func testThrowingRPC ( ) async throws {
186186 var serviceContext = ServiceContext . topLevel
187187 let traceIDString = UUID ( ) . uuidString
188188 serviceContext. traceID = traceIDString
@@ -197,8 +197,8 @@ struct OTelTracingClientInterceptorTests {
197197 traceEachMessage: false
198198 )
199199 let methodDescriptor = MethodDescriptor (
200- fullyQualifiedService: " TracingInterceptorTests " ,
201- method: " testClientInterceptorErrorEncountered "
200+ fullyQualifiedService: " OTelTracingClientInterceptorTests " ,
201+ method: " testThrowingRPC "
202202 )
203203 do {
204204 let _: StreamingClientResponse < Void > = try await interceptor. intercept (
@@ -244,8 +244,8 @@ struct OTelTracingClientInterceptorTests {
244244 }
245245 }
246246
247- @Test ( " RPC with error response is correctly recorded " )
248- func testClientInterceptorErrorReponse ( ) async throws {
247+ @Test ( " RPC with a failure response is correctly recorded " )
248+ func testFailedRPC ( ) async throws {
249249 var serviceContext = ServiceContext . topLevel
250250 let traceIDString = UUID ( ) . uuidString
251251 let ( requestStream, requestStreamContinuation) = AsyncStream< String> . makeStream( )
@@ -261,8 +261,8 @@ struct OTelTracingClientInterceptorTests {
261261 traceEachMessage: false
262262 )
263263 let methodDescriptor = MethodDescriptor (
264- fullyQualifiedService: " TracingInterceptorTests " ,
265- method: " testClientInterceptor "
264+ fullyQualifiedService: " OTelTracingClientInterceptorTests " ,
265+ method: " testFailedRPC "
266266 )
267267 let response : StreamingClientResponse < Void > = try await interceptor. intercept (
268268 tracer: self . tracer,
@@ -323,6 +323,96 @@ struct OTelTracingClientInterceptorTests {
323323 }
324324 }
325325
326+ @Test ( " Accepted server-streaming RPC that throws error during response is correctly recorded " )
327+ func testAcceptedRPCWithError( ) async throws {
328+ var serviceContext = ServiceContext . topLevel
329+ let traceIDString = UUID ( ) . uuidString
330+ serviceContext. traceID = traceIDString
331+
332+ // FIXME: use 'ServiceContext.withValue(serviceContext)'
333+ //
334+ // This is blocked on: https://github.com/apple/swift-service-context/pull/46
335+ try await ServiceContext . $current. withValue ( serviceContext) {
336+ let interceptor = ClientOTelTracingInterceptor (
337+ serverHostname: " someserver.com " ,
338+ networkTransportMethod: " tcp " ,
339+ traceEachMessage: false
340+ )
341+ let methodDescriptor = MethodDescriptor (
342+ fullyQualifiedService: " OTelTracingClientInterceptorTests " ,
343+ method: " testAcceptedRPCWithError "
344+ )
345+ let response : StreamingClientResponse < String > = try await interceptor. intercept (
346+ tracer: self . tracer,
347+ request: . init( producer: { writer in
348+ try await writer. write ( contentsOf: [ " request " ] )
349+ } ) ,
350+ context: ClientContext (
351+ descriptor: methodDescriptor,
352+ remotePeer: " ipv4:10.1.2.80:567 " ,
353+ localPeer: " ipv4:10.1.2.80:123 "
354+ )
355+ ) { stream, _ in
356+ // Assert the metadata contains the injected context key-value.
357+ #expect( stream. metadata == [ " trace-id " : " \( traceIDString) " ] )
358+
359+ return . init(
360+ metadata: [ ] ,
361+ bodyParts: RPCAsyncSequence (
362+ wrapping: AsyncThrowingStream < StreamingClientResponse . Contents . BodyPart , any Error > {
363+ $0. finish ( throwing: RPCError ( code: . unavailable, message: " This should be thrown " ) )
364+ }
365+ )
366+ )
367+ }
368+
369+ switch response. accepted {
370+ case . success( let success) :
371+ do {
372+ for try await _ in success. bodyParts {
373+ // We don't care about any received messages here - we're not even writing any.
374+ }
375+ } catch {
376+ #expect(
377+ error as? RPCError
378+ == RPCError (
379+ code: . unavailable,
380+ message: " This should be thrown "
381+ )
382+ )
383+ }
384+
385+ case . failure:
386+ Issue . record ( " Response should have been successful " )
387+ return
388+ }
389+
390+ assertTestSpanComponents ( forMethod: methodDescriptor) { events in
391+ // No events are recorded
392+ #expect( events. isEmpty)
393+ } assertAttributes: { attributes in
394+ #expect(
395+ attributes == [
396+ " rpc.system " : " grpc " ,
397+ " rpc.method " : . string( methodDescriptor. method) ,
398+ " rpc.service " : . string( methodDescriptor. service. fullyQualifiedService) ,
399+ " rpc.grpc.status_code " : 14 , // this is unavailable's raw code
400+ " server.address " : " someserver.com " ,
401+ " server.port " : 567 ,
402+ " network.peer.address " : " 10.1.2.80 " ,
403+ " network.peer.port " : 567 ,
404+ " network.transport " : " tcp " ,
405+ " network.type " : " ipv4 " ,
406+ ]
407+ )
408+ } assertStatus: { status in
409+ #expect( status == . some( . init( code: . error) ) )
410+ } assertErrors: { errors in
411+ #expect( errors. count == 1 )
412+ }
413+ }
414+ }
415+
326416 // - MARK: Utilities
327417
328418 private func getTestValues(
0 commit comments