github.com/newrelic/go-agent@v3.26.0+incompatible/_integrations/nrgrpc/nrgrpc_client_test.go (about) 1 // Copyright 2020 New Relic Corporation. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 package nrgrpc 5 6 import ( 7 "context" 8 "encoding/json" 9 "io" 10 "testing" 11 12 newrelic "github.com/newrelic/go-agent" 13 "github.com/newrelic/go-agent/_integrations/nrgrpc/testapp" 14 "github.com/newrelic/go-agent/internal" 15 "github.com/newrelic/go-agent/internal/integrationsupport" 16 "google.golang.org/grpc/metadata" 17 ) 18 19 func TestGetURL(t *testing.T) { 20 testcases := []struct { 21 method string 22 target string 23 expected string 24 }{ 25 { 26 method: "/TestApplication/DoUnaryUnary", 27 target: "", 28 expected: "grpc:///TestApplication/DoUnaryUnary", 29 }, 30 { 31 method: "TestApplication/DoUnaryUnary", 32 target: "", 33 expected: "grpc://TestApplication/DoUnaryUnary", 34 }, 35 { 36 method: "/TestApplication/DoUnaryUnary", 37 target: ":8080", 38 expected: "grpc://:8080/TestApplication/DoUnaryUnary", 39 }, 40 { 41 method: "/TestApplication/DoUnaryUnary", 42 target: "localhost:8080", 43 expected: "grpc://localhost:8080/TestApplication/DoUnaryUnary", 44 }, 45 { 46 method: "TestApplication/DoUnaryUnary", 47 target: "localhost:8080", 48 expected: "grpc://localhost:8080/TestApplication/DoUnaryUnary", 49 }, 50 { 51 method: "/TestApplication/DoUnaryUnary", 52 target: "dns:///localhost:8080", 53 expected: "grpc://localhost:8080/TestApplication/DoUnaryUnary", 54 }, 55 { 56 method: "/TestApplication/DoUnaryUnary", 57 target: "unix:/path/to/socket", 58 expected: "grpc://localhost/TestApplication/DoUnaryUnary", 59 }, 60 { 61 method: "/TestApplication/DoUnaryUnary", 62 target: "unix:///path/to/socket", 63 expected: "grpc://localhost/TestApplication/DoUnaryUnary", 64 }, 65 } 66 67 for _, test := range testcases { 68 actual := getURL(test.method, test.target) 69 if actual.String() != test.expected { 70 t.Errorf("incorrect URL:\n\tmethod=%s,\n\ttarget=%s,\n\texpected=%s,\n\tactual=%s", 71 test.method, test.target, test.expected, actual.String()) 72 } 73 } 74 } 75 76 func testApp() integrationsupport.ExpectApp { 77 return integrationsupport.NewTestApp(replyFn, configFn) 78 } 79 80 var replyFn = func(reply *internal.ConnectReply) { 81 reply.AdaptiveSampler = internal.SampleEverything{} 82 reply.AccountID = "123" 83 reply.TrustedAccountKey = "123" 84 reply.PrimaryAppID = "456" 85 } 86 87 var configFn = func(cfg *newrelic.Config) { 88 cfg.Enabled = false 89 cfg.DistributedTracer.Enabled = true 90 cfg.TransactionTracer.SegmentThreshold = 0 91 cfg.TransactionTracer.Threshold.IsApdexFailing = false 92 cfg.TransactionTracer.Threshold.Duration = 0 93 } 94 95 func TestUnaryClientInterceptor(t *testing.T) { 96 app := testApp() 97 txn := app.StartTransaction("UnaryUnary", nil, nil) 98 ctx := newrelic.NewContext(context.Background(), txn) 99 100 s, conn := newTestServerAndConn(t, nil) 101 defer s.Stop() 102 defer conn.Close() 103 104 client := testapp.NewTestApplicationClient(conn) 105 resp, err := client.DoUnaryUnary(ctx, &testapp.Message{}) 106 if nil != err { 107 t.Fatal("client call to DoUnaryUnary failed", err) 108 } 109 var hdrs map[string][]string 110 err = json.Unmarshal([]byte(resp.Text), &hdrs) 111 if nil != err { 112 t.Fatal("cannot unmarshall client response", err) 113 } 114 if hdr, ok := hdrs["newrelic"]; !ok || len(hdr) != 1 || "" == hdr[0] { 115 t.Error("distributed trace header not sent", hdrs) 116 } 117 txn.End() 118 119 app.ExpectMetrics(t, []internal.WantMetric{ 120 {Name: "OtherTransaction/Go/UnaryUnary", Scope: "", Forced: true, Data: nil}, 121 {Name: "OtherTransaction/all", Scope: "", Forced: true, Data: nil}, 122 {Name: "OtherTransactionTotalTime", Scope: "", Forced: true, Data: nil}, 123 {Name: "OtherTransactionTotalTime/Go/UnaryUnary", Scope: "", Forced: false, Data: nil}, 124 {Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/all", Scope: "", Forced: false, Data: nil}, 125 {Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/allOther", Scope: "", Forced: false, Data: nil}, 126 {Name: "External/all", Scope: "", Forced: true, Data: nil}, 127 {Name: "External/allOther", Scope: "", Forced: true, Data: nil}, 128 {Name: "External/bufnet/all", Scope: "", Forced: false, Data: nil}, 129 {Name: "External/bufnet/gRPC/TestApplication/DoUnaryUnary", Scope: "OtherTransaction/Go/UnaryUnary", Forced: false, Data: nil}, 130 {Name: "Supportability/DistributedTrace/CreatePayload/Success", Scope: "", Forced: true, Data: nil}, 131 }) 132 app.ExpectSpanEvents(t, []internal.WantEvent{ 133 { 134 Intrinsics: map[string]interface{}{ 135 "category": "generic", 136 "name": "OtherTransaction/Go/UnaryUnary", 137 "nr.entryPoint": true, 138 }, 139 UserAttributes: map[string]interface{}{}, 140 AgentAttributes: map[string]interface{}{}, 141 }, 142 { 143 Intrinsics: map[string]interface{}{ 144 "category": "http", 145 "component": "gRPC", 146 "name": "External/bufnet/gRPC/TestApplication/DoUnaryUnary", 147 "parentId": internal.MatchAnything, 148 "span.kind": "client", 149 }, 150 UserAttributes: map[string]interface{}{}, 151 AgentAttributes: map[string]interface{}{}, 152 }, 153 }) 154 app.ExpectTxnTraces(t, []internal.WantTxnTrace{{ 155 MetricName: "OtherTransaction/Go/UnaryUnary", 156 Root: internal.WantTraceSegment{ 157 SegmentName: "ROOT", 158 Attributes: map[string]interface{}{}, 159 Children: []internal.WantTraceSegment{{ 160 SegmentName: "OtherTransaction/Go/UnaryUnary", 161 Attributes: map[string]interface{}{"exclusive_duration_millis": internal.MatchAnything}, 162 Children: []internal.WantTraceSegment{ 163 { 164 SegmentName: "External/bufnet/gRPC/TestApplication/DoUnaryUnary", 165 Attributes: map[string]interface{}{}, 166 }, 167 }, 168 }}, 169 }, 170 }}) 171 } 172 173 func TestUnaryStreamClientInterceptor(t *testing.T) { 174 app := testApp() 175 txn := app.StartTransaction("UnaryStream", nil, nil) 176 ctx := newrelic.NewContext(context.Background(), txn) 177 178 s, conn := newTestServerAndConn(t, nil) 179 defer s.Stop() 180 defer conn.Close() 181 182 client := testapp.NewTestApplicationClient(conn) 183 stream, err := client.DoUnaryStream(ctx, &testapp.Message{}) 184 if nil != err { 185 t.Fatal("client call to DoUnaryStream failed", err) 186 } 187 var recved int 188 for { 189 msg, err := stream.Recv() 190 if err == io.EOF { 191 break 192 } 193 if nil != err { 194 t.Fatal("error receiving message", err) 195 } 196 var hdrs map[string][]string 197 err = json.Unmarshal([]byte(msg.Text), &hdrs) 198 if nil != err { 199 t.Fatal("cannot unmarshall client response", err) 200 } 201 if hdr, ok := hdrs["newrelic"]; !ok || len(hdr) != 1 || "" == hdr[0] { 202 t.Error("distributed trace header not sent", hdrs) 203 } 204 recved++ 205 } 206 if recved != 3 { 207 t.Fatal("received incorrect number of messages from server", recved) 208 } 209 txn.End() 210 211 app.ExpectMetrics(t, []internal.WantMetric{ 212 {Name: "OtherTransaction/Go/UnaryStream", Scope: "", Forced: true, Data: nil}, 213 {Name: "OtherTransaction/all", Scope: "", Forced: true, Data: nil}, 214 {Name: "OtherTransactionTotalTime", Scope: "", Forced: true, Data: nil}, 215 {Name: "OtherTransactionTotalTime/Go/UnaryStream", Scope: "", Forced: false, Data: nil}, 216 {Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/all", Scope: "", Forced: false, Data: nil}, 217 {Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/allOther", Scope: "", Forced: false, Data: nil}, 218 {Name: "External/all", Scope: "", Forced: true, Data: nil}, 219 {Name: "External/allOther", Scope: "", Forced: true, Data: nil}, 220 {Name: "External/bufnet/all", Scope: "", Forced: false, Data: nil}, 221 {Name: "External/bufnet/gRPC/TestApplication/DoUnaryStream", Scope: "OtherTransaction/Go/UnaryStream", Forced: false, Data: nil}, 222 {Name: "Supportability/DistributedTrace/CreatePayload/Success", Scope: "", Forced: true, Data: nil}, 223 }) 224 app.ExpectSpanEvents(t, []internal.WantEvent{ 225 { 226 Intrinsics: map[string]interface{}{ 227 "category": "generic", 228 "name": "OtherTransaction/Go/UnaryStream", 229 "nr.entryPoint": true, 230 }, 231 UserAttributes: map[string]interface{}{}, 232 AgentAttributes: map[string]interface{}{}, 233 }, 234 { 235 Intrinsics: map[string]interface{}{ 236 "category": "http", 237 "component": "gRPC", 238 "name": "External/bufnet/gRPC/TestApplication/DoUnaryStream", 239 "parentId": internal.MatchAnything, 240 "span.kind": "client", 241 }, 242 UserAttributes: map[string]interface{}{}, 243 AgentAttributes: map[string]interface{}{}, 244 }, 245 }) 246 app.ExpectTxnTraces(t, []internal.WantTxnTrace{{ 247 MetricName: "OtherTransaction/Go/UnaryStream", 248 Root: internal.WantTraceSegment{ 249 SegmentName: "ROOT", 250 Attributes: map[string]interface{}{}, 251 Children: []internal.WantTraceSegment{{ 252 SegmentName: "OtherTransaction/Go/UnaryStream", 253 Attributes: map[string]interface{}{"exclusive_duration_millis": internal.MatchAnything}, 254 Children: []internal.WantTraceSegment{ 255 { 256 SegmentName: "External/bufnet/gRPC/TestApplication/DoUnaryStream", 257 Attributes: map[string]interface{}{}, 258 }, 259 }, 260 }}, 261 }, 262 }}) 263 } 264 265 func TestStreamUnaryClientInterceptor(t *testing.T) { 266 app := testApp() 267 txn := app.StartTransaction("StreamUnary", nil, nil) 268 ctx := newrelic.NewContext(context.Background(), txn) 269 270 s, conn := newTestServerAndConn(t, nil) 271 defer s.Stop() 272 defer conn.Close() 273 274 client := testapp.NewTestApplicationClient(conn) 275 stream, err := client.DoStreamUnary(ctx) 276 if nil != err { 277 t.Fatal("client call to DoStreamUnary failed", err) 278 } 279 for i := 0; i < 3; i++ { 280 if err := stream.Send(&testapp.Message{Text: "Hello DoStreamUnary"}); nil != err { 281 if err == io.EOF { 282 break 283 } 284 t.Fatal("failure to Send", err) 285 } 286 } 287 msg, err := stream.CloseAndRecv() 288 if nil != err { 289 t.Fatal("failure to CloseAndRecv", err) 290 } 291 var hdrs map[string][]string 292 err = json.Unmarshal([]byte(msg.Text), &hdrs) 293 if nil != err { 294 t.Fatal("cannot unmarshall client response", err) 295 } 296 if hdr, ok := hdrs["newrelic"]; !ok || len(hdr) != 1 || "" == hdr[0] { 297 t.Error("distributed trace header not sent", hdrs) 298 } 299 txn.End() 300 301 app.ExpectMetrics(t, []internal.WantMetric{ 302 {Name: "OtherTransaction/Go/StreamUnary", Scope: "", Forced: true, Data: nil}, 303 {Name: "OtherTransaction/all", Scope: "", Forced: true, Data: nil}, 304 {Name: "OtherTransactionTotalTime", Scope: "", Forced: true, Data: nil}, 305 {Name: "OtherTransactionTotalTime/Go/StreamUnary", Scope: "", Forced: false, Data: nil}, 306 {Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/all", Scope: "", Forced: false, Data: nil}, 307 {Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/allOther", Scope: "", Forced: false, Data: nil}, 308 {Name: "External/all", Scope: "", Forced: true, Data: nil}, 309 {Name: "External/allOther", Scope: "", Forced: true, Data: nil}, 310 {Name: "External/bufnet/all", Scope: "", Forced: false, Data: nil}, 311 {Name: "External/bufnet/gRPC/TestApplication/DoStreamUnary", Scope: "OtherTransaction/Go/StreamUnary", Forced: false, Data: nil}, 312 {Name: "Supportability/DistributedTrace/CreatePayload/Success", Scope: "", Forced: true, Data: nil}, 313 }) 314 app.ExpectSpanEvents(t, []internal.WantEvent{ 315 { 316 Intrinsics: map[string]interface{}{ 317 "category": "generic", 318 "name": "OtherTransaction/Go/StreamUnary", 319 "nr.entryPoint": true, 320 }, 321 UserAttributes: map[string]interface{}{}, 322 AgentAttributes: map[string]interface{}{}, 323 }, 324 { 325 Intrinsics: map[string]interface{}{ 326 "category": "http", 327 "component": "gRPC", 328 "name": "External/bufnet/gRPC/TestApplication/DoStreamUnary", 329 "parentId": internal.MatchAnything, 330 "span.kind": "client", 331 }, 332 UserAttributes: map[string]interface{}{}, 333 AgentAttributes: map[string]interface{}{}, 334 }, 335 }) 336 app.ExpectTxnTraces(t, []internal.WantTxnTrace{{ 337 MetricName: "OtherTransaction/Go/StreamUnary", 338 Root: internal.WantTraceSegment{ 339 SegmentName: "ROOT", 340 Attributes: map[string]interface{}{}, 341 Children: []internal.WantTraceSegment{{ 342 SegmentName: "OtherTransaction/Go/StreamUnary", 343 Attributes: map[string]interface{}{"exclusive_duration_millis": internal.MatchAnything}, 344 Children: []internal.WantTraceSegment{ 345 { 346 SegmentName: "External/bufnet/gRPC/TestApplication/DoStreamUnary", 347 Attributes: map[string]interface{}{}, 348 }, 349 }, 350 }}, 351 }, 352 }}) 353 } 354 355 func TestStreamStreamClientInterceptor(t *testing.T) { 356 app := testApp() 357 txn := app.StartTransaction("StreamStream", nil, nil) 358 ctx := newrelic.NewContext(context.Background(), txn) 359 360 s, conn := newTestServerAndConn(t, nil) 361 defer s.Stop() 362 defer conn.Close() 363 364 client := testapp.NewTestApplicationClient(conn) 365 stream, err := client.DoStreamStream(ctx) 366 if nil != err { 367 t.Fatal("client call to DoStreamStream failed", err) 368 } 369 waitc := make(chan struct{}) 370 go func() { 371 defer close(waitc) 372 var recved int 373 for { 374 msg, err := stream.Recv() 375 if err == io.EOF { 376 break 377 } 378 if err != nil { 379 t.Fatal("failure to Recv", err) 380 } 381 var hdrs map[string][]string 382 err = json.Unmarshal([]byte(msg.Text), &hdrs) 383 if nil != err { 384 t.Fatal("cannot unmarshall client response", err) 385 } 386 if hdr, ok := hdrs["newrelic"]; !ok || len(hdr) != 1 || "" == hdr[0] { 387 t.Error("distributed trace header not sent", hdrs) 388 } 389 recved++ 390 } 391 if recved != 3 { 392 t.Fatal("received incorrect number of messages from server", recved) 393 } 394 }() 395 for i := 0; i < 3; i++ { 396 if err := stream.Send(&testapp.Message{Text: "Hello DoStreamStream"}); err != nil { 397 t.Fatal("failure to Send", err) 398 } 399 } 400 stream.CloseSend() 401 <-waitc 402 txn.End() 403 404 app.ExpectMetrics(t, []internal.WantMetric{ 405 {Name: "OtherTransaction/Go/StreamStream", Scope: "", Forced: true, Data: nil}, 406 {Name: "OtherTransaction/all", Scope: "", Forced: true, Data: nil}, 407 {Name: "OtherTransactionTotalTime", Scope: "", Forced: true, Data: nil}, 408 {Name: "OtherTransactionTotalTime/Go/StreamStream", Scope: "", Forced: false, Data: nil}, 409 {Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/all", Scope: "", Forced: false, Data: nil}, 410 {Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/allOther", Scope: "", Forced: false, Data: nil}, 411 {Name: "External/all", Scope: "", Forced: true, Data: nil}, 412 {Name: "External/allOther", Scope: "", Forced: true, Data: nil}, 413 {Name: "External/bufnet/all", Scope: "", Forced: false, Data: nil}, 414 {Name: "External/bufnet/gRPC/TestApplication/DoStreamStream", Scope: "OtherTransaction/Go/StreamStream", Forced: false, Data: nil}, 415 {Name: "Supportability/DistributedTrace/CreatePayload/Success", Scope: "", Forced: true, Data: nil}, 416 }) 417 app.ExpectSpanEvents(t, []internal.WantEvent{ 418 { 419 Intrinsics: map[string]interface{}{ 420 "category": "generic", 421 "name": "OtherTransaction/Go/StreamStream", 422 "nr.entryPoint": true, 423 }, 424 UserAttributes: map[string]interface{}{}, 425 AgentAttributes: map[string]interface{}{}, 426 }, 427 { 428 Intrinsics: map[string]interface{}{ 429 "category": "http", 430 "component": "gRPC", 431 "name": "External/bufnet/gRPC/TestApplication/DoStreamStream", 432 "parentId": internal.MatchAnything, 433 "span.kind": "client", 434 }, 435 UserAttributes: map[string]interface{}{}, 436 AgentAttributes: map[string]interface{}{}, 437 }, 438 }) 439 app.ExpectTxnTraces(t, []internal.WantTxnTrace{{ 440 MetricName: "OtherTransaction/Go/StreamStream", 441 Root: internal.WantTraceSegment{ 442 SegmentName: "ROOT", 443 Attributes: map[string]interface{}{}, 444 Children: []internal.WantTraceSegment{{ 445 SegmentName: "OtherTransaction/Go/StreamStream", 446 Attributes: map[string]interface{}{"exclusive_duration_millis": internal.MatchAnything}, 447 Children: []internal.WantTraceSegment{ 448 { 449 SegmentName: "External/bufnet/gRPC/TestApplication/DoStreamStream", 450 Attributes: map[string]interface{}{}, 451 }, 452 }, 453 }}, 454 }, 455 }}) 456 } 457 458 func TestClientUnaryMetadata(t *testing.T) { 459 // Test that metadata on the outgoing request are presevered 460 app := testApp() 461 txn := app.StartTransaction("metadata", nil, nil) 462 ctx := newrelic.NewContext(context.Background(), txn) 463 464 md := metadata.New(map[string]string{ 465 "testing": "hello world", 466 "newrelic": "payload", 467 }) 468 ctx = metadata.NewOutgoingContext(ctx, md) 469 470 s, conn := newTestServerAndConn(t, nil) 471 defer s.Stop() 472 defer conn.Close() 473 474 client := testapp.NewTestApplicationClient(conn) 475 resp, err := client.DoUnaryUnary(ctx, &testapp.Message{}) 476 if nil != err { 477 t.Fatal("client call to DoUnaryUnary failed", err) 478 } 479 var hdrs map[string][]string 480 err = json.Unmarshal([]byte(resp.Text), &hdrs) 481 if nil != err { 482 t.Fatal("cannot unmarshall client response", err) 483 } 484 if hdr, ok := hdrs["newrelic"]; !ok || len(hdr) != 1 || "" == hdr[0] || "payload" == hdr[0] { 485 t.Error("distributed trace header not sent", hdrs) 486 } 487 if hdr, ok := hdrs["testing"]; !ok || len(hdr) != 1 || "hello world" != hdr[0] { 488 t.Error("testing header not sent", hdrs) 489 } 490 } 491 492 func TestNilTxnClientUnary(t *testing.T) { 493 s, conn := newTestServerAndConn(t, nil) 494 defer s.Stop() 495 defer conn.Close() 496 497 client := testapp.NewTestApplicationClient(conn) 498 resp, err := client.DoUnaryUnary(context.Background(), &testapp.Message{}) 499 if nil != err { 500 t.Fatal("client call to DoUnaryUnary failed", err) 501 } 502 var hdrs map[string][]string 503 err = json.Unmarshal([]byte(resp.Text), &hdrs) 504 if nil != err { 505 t.Fatal("cannot unmarshall client response", err) 506 } 507 if _, ok := hdrs["newrelic"]; ok { 508 t.Error("distributed trace header sent", hdrs) 509 } 510 } 511 512 func TestNilTxnClientStreaming(t *testing.T) { 513 s, conn := newTestServerAndConn(t, nil) 514 defer s.Stop() 515 defer conn.Close() 516 517 client := testapp.NewTestApplicationClient(conn) 518 stream, err := client.DoStreamUnary(context.Background()) 519 if nil != err { 520 t.Fatal("client call to DoStreamUnary failed", err) 521 } 522 for i := 0; i < 3; i++ { 523 if err := stream.Send(&testapp.Message{Text: "Hello DoStreamUnary"}); nil != err { 524 if err == io.EOF { 525 break 526 } 527 t.Fatal("failure to Send", err) 528 } 529 } 530 msg, err := stream.CloseAndRecv() 531 if nil != err { 532 t.Fatal("failure to CloseAndRecv", err) 533 } 534 var hdrs map[string][]string 535 err = json.Unmarshal([]byte(msg.Text), &hdrs) 536 if nil != err { 537 t.Fatal("cannot unmarshall client response", err) 538 } 539 if _, ok := hdrs["newrelic"]; ok { 540 t.Error("distributed trace header sent", hdrs) 541 } 542 } 543 544 func TestClientStreamingError(t *testing.T) { 545 // Test that when creating the stream returns an error, no external 546 // segments are created 547 app := testApp() 548 txn := app.StartTransaction("UnaryStream", nil, nil) 549 550 s, conn := newTestServerAndConn(t, nil) 551 defer s.Stop() 552 defer conn.Close() 553 554 client := testapp.NewTestApplicationClient(conn) 555 556 ctx, cancel := context.WithTimeout(context.Background(), 0) 557 defer cancel() 558 ctx = newrelic.NewContext(ctx, txn) 559 _, err := client.DoUnaryStream(ctx, &testapp.Message{}) 560 if nil == err { 561 t.Fatal("client call to DoUnaryStream did not return error") 562 } 563 txn.End() 564 565 app.ExpectMetrics(t, []internal.WantMetric{ 566 {Name: "OtherTransaction/Go/UnaryStream", Scope: "", Forced: true, Data: nil}, 567 {Name: "OtherTransaction/all", Scope: "", Forced: true, Data: nil}, 568 {Name: "OtherTransactionTotalTime", Scope: "", Forced: true, Data: nil}, 569 {Name: "OtherTransactionTotalTime/Go/UnaryStream", Scope: "", Forced: false, Data: nil}, 570 {Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/all", Scope: "", Forced: false, Data: nil}, 571 {Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/allOther", Scope: "", Forced: false, Data: nil}, 572 {Name: "Supportability/DistributedTrace/CreatePayload/Success", Scope: "", Forced: true, Data: nil}, 573 }) 574 app.ExpectSpanEvents(t, []internal.WantEvent{ 575 { 576 Intrinsics: map[string]interface{}{ 577 "category": "generic", 578 "name": "OtherTransaction/Go/UnaryStream", 579 "nr.entryPoint": true, 580 }, 581 UserAttributes: map[string]interface{}{}, 582 AgentAttributes: map[string]interface{}{}, 583 }, 584 }) 585 app.ExpectTxnTraces(t, []internal.WantTxnTrace{{ 586 MetricName: "OtherTransaction/Go/UnaryStream", 587 Root: internal.WantTraceSegment{ 588 SegmentName: "ROOT", 589 Attributes: map[string]interface{}{}, 590 Children: []internal.WantTraceSegment{{ 591 SegmentName: "OtherTransaction/Go/UnaryStream", 592 Attributes: map[string]interface{}{"exclusive_duration_millis": internal.MatchAnything}, 593 Children: []internal.WantTraceSegment{}, 594 }}, 595 }, 596 }}) 597 }