github.com/instana/go-sensor@v1.62.2-0.20240520081010-4919868049e1/registered_span.go (about) 1 // (c) Copyright IBM Corp. 2021 2 // (c) Copyright Instana Inc. 2021 3 4 package instana 5 6 import ( 7 "strings" 8 9 "github.com/opentracing/opentracing-go/ext" 10 ) 11 12 // Registered types supported by Instana. The span type is determined based on 13 // the operation name passed to the `StartSpan()` call of a tracer. 14 // 15 // It is NOT RECOMMENDED to use operation names that match any of these constants in your 16 // custom instrumentation code unless you explicitly wish to send data as a registered span. 17 // The list of supported tags can be found in the godoc of the respective span tags type below. 18 const ( 19 // SDK span, a generic span containing arbitrary data. Spans with operation name 20 // not listed in the subsequent list will be sent as an SDK spans forwarding all 21 // attached tags to the agent 22 SDKSpanType = RegisteredSpanType("sdk") 23 // HTTP server and client spans 24 HTTPServerSpanType = RegisteredSpanType("g.http") 25 HTTPClientSpanType = RegisteredSpanType("http") 26 // RPC server and client spans 27 RPCServerSpanType = RegisteredSpanType("rpc-server") 28 RPCClientSpanType = RegisteredSpanType("rpc-client") 29 // Kafka consumer/producer span 30 KafkaSpanType = RegisteredSpanType("kafka") 31 // Google Cloud Storage client span 32 GCPStorageSpanType = RegisteredSpanType("gcs") 33 // Google Cloud PubSub client span 34 GCPPubSubSpanType = RegisteredSpanType("gcps") 35 // AWS Lambda entry span 36 AWSLambdaEntrySpanType = RegisteredSpanType("aws.lambda.entry") 37 // AWS S3 client span 38 AWSS3SpanType = RegisteredSpanType("s3") 39 // AWS SQS client span 40 AWSSQSSpanType = RegisteredSpanType("sqs") 41 // AWS SNS client span 42 AWSSNSSpanType = RegisteredSpanType("sns") 43 // AWS DynamoDB client span 44 AWSDynamoDBSpanType = RegisteredSpanType("dynamodb") 45 // AWS Lambda invoke span 46 AWSLambdaInvokeSpanType = RegisteredSpanType("aws.lambda.invoke") 47 // Logging span 48 LogSpanType = RegisteredSpanType("log.go") 49 // MongoDB client span 50 MongoDBSpanType = RegisteredSpanType("mongo") 51 // PostgreSQL client span 52 PostgreSQLSpanType = RegisteredSpanType("postgres") 53 // MySQL client span 54 MySQLSpanType = RegisteredSpanType("mysql") 55 // Redis client span 56 RedisSpanType = RegisteredSpanType("redis") 57 // Couchbase client span 58 CouchbaseSpanType = RegisteredSpanType("couchbase") 59 // Cosmos client span 60 CosmosSpanType = RegisteredSpanType("cosmos") 61 // RabbitMQ client span 62 RabbitMQSpanType = RegisteredSpanType("rabbitmq") 63 // Azure function span 64 AzureFunctionType = RegisteredSpanType("azf") 65 // GraphQL server span 66 GraphQLServerType = RegisteredSpanType("graphql.server") 67 // GraphQL client span 68 GraphQLClientType = RegisteredSpanType("graphql.client") 69 ) 70 71 // RegisteredSpanType represents the span type supported by Instana 72 type RegisteredSpanType string 73 74 // extractData is a factory method to create the `data` section for a typed span 75 func (st RegisteredSpanType) extractData(span *spanS) typedSpanData { 76 switch st { 77 case HTTPServerSpanType, HTTPClientSpanType: 78 return newHTTPSpanData(span) 79 case RPCServerSpanType, RPCClientSpanType: 80 return newRPCSpanData(span) 81 case KafkaSpanType: 82 return newKafkaSpanData(span) 83 case GCPStorageSpanType: 84 return newGCPStorageSpanData(span) 85 case GCPPubSubSpanType: 86 return newGCPPubSubSpanData(span) 87 case AWSLambdaEntrySpanType: 88 return newAWSLambdaSpanData(span) 89 case AWSS3SpanType: 90 return newAWSS3SpanData(span) 91 case AWSSQSSpanType: 92 return newAWSSQSSpanData(span) 93 case AWSSNSSpanType: 94 return newAWSSNSSpanData(span) 95 case AWSDynamoDBSpanType: 96 return newAWSDynamoDBSpanData(span) 97 case AWSLambdaInvokeSpanType: 98 return newAWSLambdaInvokeSpanData(span) 99 case LogSpanType: 100 return newLogSpanData(span) 101 case MongoDBSpanType: 102 return newMongoDBSpanData(span) 103 case PostgreSQLSpanType: 104 return newPostgreSQLSpanData(span) 105 case CouchbaseSpanType: 106 return newCouchbaseSpanData(span) 107 case CosmosSpanType: 108 return newCosmosSpanData(span) 109 case MySQLSpanType: 110 return newMySQLSpanData(span) 111 case RedisSpanType: 112 return newRedisSpanData(span) 113 case RabbitMQSpanType: 114 return newRabbitMQSpanData(span) 115 case AzureFunctionType: 116 return newAZFSpanData(span) 117 case GraphQLServerType, GraphQLClientType: 118 return newGraphQLSpanData(span) 119 default: 120 return newSDKSpanData(span) 121 } 122 } 123 124 // TagsNames returns a set of tag names known to the registered span type 125 func (st RegisteredSpanType) TagsNames() map[string]struct{} { 126 var yes struct{} 127 128 switch st { 129 case HTTPServerSpanType, HTTPClientSpanType: 130 return map[string]struct{}{ 131 "http.url": yes, string(ext.HTTPUrl): yes, 132 "http.status": yes, "http.status_code": yes, 133 "http.method": yes, string(ext.HTTPMethod): yes, 134 "http.path": yes, 135 "http.params": yes, 136 "http.header": yes, 137 "http.path_tpl": yes, 138 "http.route_id": yes, 139 "http.host": yes, 140 "http.protocol": yes, 141 "http.error": yes, 142 } 143 case RPCServerSpanType, RPCClientSpanType: 144 return map[string]struct{}{ 145 "rpc.host": yes, 146 "rpc.port": yes, 147 "rpc.call": yes, 148 "rpc.call_type": yes, 149 "rpc.flavor": yes, 150 "rpc.error": yes, 151 } 152 case KafkaSpanType: 153 return map[string]struct{}{ 154 "kafka.service": yes, 155 "kafka.access": yes, 156 } 157 case GCPStorageSpanType: 158 return map[string]struct{}{ 159 "gcs.op": yes, 160 "gcs.bucket": yes, 161 "gcs.object": yes, 162 "gcs.entity": yes, 163 "gcs.range": yes, 164 "gcs.sourceBucket": yes, 165 "gcs.sourceObject": yes, 166 "gcs.destinationBucket": yes, 167 "gcs.destinationObject": yes, 168 "gcs.numberOfOperations": yes, 169 "gcs.projectId": yes, 170 "gcs.accessId": yes, 171 } 172 case GCPPubSubSpanType: 173 return map[string]struct{}{ 174 "gcps.projid": yes, 175 "gcps.op": yes, 176 "gcps.top": yes, 177 "gcps.sub": yes, 178 "gcps.msgid": yes, 179 } 180 case AWSLambdaEntrySpanType: 181 return map[string]struct{}{ 182 "lambda.arn": yes, 183 "lambda.name": yes, 184 "lambda.version": yes, 185 "lambda.trigger": yes, 186 "lambda.coldStart": yes, 187 "lambda.msleft": yes, 188 "lambda.error": yes, 189 "cloudwatch.events.id": yes, 190 "cloudwatch.events.resources": yes, 191 "cloudwatch.logs.group": yes, 192 "cloudwatch.logs.stream": yes, 193 "cloudwatch.logs.decodingError": yes, 194 "cloudwatch.logs.events": yes, 195 "s3.events": yes, 196 "sqs.messages": yes, 197 } 198 case AWSS3SpanType: 199 return map[string]struct{}{ 200 "s3.region": yes, 201 "s3.op": yes, 202 "s3.bucket": yes, 203 "s3.key": yes, 204 "s3.error": yes, 205 } 206 case AWSSQSSpanType: 207 return map[string]struct{}{ 208 "sqs.sort": yes, 209 "sqs.queue": yes, 210 "sqs.type": yes, 211 "sqs.group": yes, 212 "sqs.size": yes, 213 "sqs.error": yes, 214 } 215 case AWSSNSSpanType: 216 return map[string]struct{}{ 217 "sns.topic": yes, 218 "sns.target": yes, 219 "sns.phone": yes, 220 "sns.subject": yes, 221 "sns.error": yes, 222 } 223 case AWSDynamoDBSpanType: 224 return map[string]struct{}{ 225 "dynamodb.table": yes, 226 "dynamodb.op": yes, 227 "dynamodb.error": yes, 228 } 229 case AWSLambdaInvokeSpanType: 230 return map[string]struct{}{ 231 "function": yes, 232 "type": yes, 233 "error": yes, 234 } 235 case LogSpanType: 236 return map[string]struct{}{ 237 "log.message": yes, 238 "log.level": yes, 239 "log.parameters": yes, 240 "log.logger": yes, 241 } 242 case MongoDBSpanType: 243 return map[string]struct{}{ 244 "mongo.service": yes, 245 "mongo.namespace": yes, 246 "mongo.command": yes, 247 "mongo.query": yes, 248 "mongo.json": yes, 249 "mongo.filter": yes, 250 "mongo.error": yes, 251 } 252 case PostgreSQLSpanType: 253 return map[string]struct{}{ 254 "pg.db": yes, 255 "pg.user": yes, 256 "pg.stmt": yes, 257 "pg.host": yes, 258 "pg.port": yes, 259 "pg.error": yes, 260 } 261 case CouchbaseSpanType: 262 return map[string]struct{}{ 263 "couchbase.bucket": yes, 264 "couchbase.hostname": yes, 265 "couchbase.type": yes, 266 "couchbase.sql": yes, 267 "couchbase.error": yes, 268 } 269 case MySQLSpanType: 270 return map[string]struct{}{ 271 "mysql.db": yes, 272 "mysql.user": yes, 273 "mysql.stmt": yes, 274 "mysql.host": yes, 275 "mysql.port": yes, 276 "mysql.error": yes, 277 } 278 case RedisSpanType: 279 return map[string]struct{}{ 280 "redis.connection": yes, 281 "redis.command": yes, 282 "redis.subCommands": yes, 283 "redis.error": yes, 284 } 285 case RabbitMQSpanType: 286 return map[string]struct{}{ 287 "rabbitmq.exchange": yes, 288 "rabbitmq.key": yes, 289 "rabbitmq.sort": yes, 290 "rabbitmq.address": yes, 291 "rabbitmq.error": yes, 292 } 293 case AzureFunctionType: 294 return map[string]struct{}{ 295 "azf.name": yes, 296 "azf.functionname": yes, 297 "azf.methodname": yes, 298 "azf.triggername": yes, 299 "azf.runtime": yes, 300 "azf.error": yes, 301 } 302 case GraphQLServerType, GraphQLClientType: 303 return map[string]struct{}{ 304 "graphql.operationName": yes, 305 "graphql.operationType": yes, 306 "graphql.fields": yes, 307 "graphql.args": yes, 308 "graphql.error": yes, 309 } 310 default: 311 return nil 312 } 313 } 314 315 // HTTPSpanData represents the `data` section of an HTTP span sent within an OT span document 316 type HTTPSpanData struct { 317 SpanData 318 Tags HTTPSpanTags `json:"http"` 319 320 clientSpan bool 321 } 322 323 // newHTTPSpanData initializes a new HTTP span data from tracer span 324 func newHTTPSpanData(span *spanS) HTTPSpanData { 325 data := HTTPSpanData{ 326 SpanData: NewSpanData(span, RegisteredSpanType(span.Operation)), 327 Tags: newHTTPSpanTags(span), 328 } 329 330 kindTag := span.Tags[string(ext.SpanKind)] 331 data.clientSpan = kindTag == ext.SpanKindRPCClientEnum || kindTag == string(ext.SpanKindRPCClientEnum) 332 333 return data 334 } 335 336 // Kind returns instana.EntrySpanKind for server spans and instana.ExitSpanKind otherwise 337 func (d HTTPSpanData) Kind() SpanKind { 338 if d.clientSpan { 339 return ExitSpanKind 340 } 341 342 return EntrySpanKind 343 } 344 345 // HTTPSpanTags contains fields within the `data.http` section of an OT span document 346 type HTTPSpanTags struct { 347 // Full request/response URL 348 URL string `json:"url,omitempty"` 349 // The HTTP status code returned with client/server response 350 Status int `json:"status,omitempty"` 351 // The HTTP method of the request 352 Method string `json:"method,omitempty"` 353 // Path is the path part of the request URL 354 Path string `json:"path,omitempty"` 355 // Params are the request query string parameters 356 Params string `json:"params,omitempty"` 357 // Headers are the captured request/response headers 358 Headers map[string]string `json:"header,omitempty"` 359 // PathTemplate is the raw template string used to route the request 360 PathTemplate string `json:"path_tpl,omitempty"` 361 // RouteID is an optional name/identifier for the matched route 362 RouteID string `json:"route_id,omitempty"` 363 // The name:port of the host to which the request had been sent 364 Host string `json:"host,omitempty"` 365 // The name of the protocol used for request ("http" or "https") 366 Protocol string `json:"protocol,omitempty"` 367 // The message describing an error occurred during the request handling 368 Error string `json:"error,omitempty"` 369 } 370 371 // newHTTPSpanTags extracts HTTP-specific span tags from a tracer span 372 func newHTTPSpanTags(span *spanS) HTTPSpanTags { 373 var tags HTTPSpanTags 374 for k, v := range span.Tags { 375 switch k { 376 case "http.url", string(ext.HTTPUrl): 377 readStringTag(&tags.URL, v) 378 case "http.status", "http.status_code": 379 readIntTag(&tags.Status, v) 380 case "http.method", string(ext.HTTPMethod): 381 readStringTag(&tags.Method, v) 382 case "http.path": 383 readStringTag(&tags.Path, v) 384 case "http.params": 385 readStringTag(&tags.Params, v) 386 case "http.header": 387 if m, ok := v.(map[string]string); ok { 388 tags.Headers = m 389 } 390 case "http.path_tpl": 391 readStringTag(&tags.PathTemplate, v) 392 case "http.route_id": 393 readStringTag(&tags.RouteID, v) 394 case "http.host": 395 readStringTag(&tags.Host, v) 396 case "http.protocol": 397 readStringTag(&tags.Protocol, v) 398 case "http.error": 399 readStringTag(&tags.Error, v) 400 } 401 } 402 403 return tags 404 } 405 406 // RPCSpanData represents the `data` section of an RPC span sent within an OT span document 407 type RPCSpanData struct { 408 SpanData 409 Tags RPCSpanTags `json:"rpc"` 410 411 clientSpan bool 412 } 413 414 // newRPCSpanData initializes a new RPC span data from tracer span 415 func newRPCSpanData(span *spanS) RPCSpanData { 416 data := RPCSpanData{ 417 SpanData: NewSpanData(span, RegisteredSpanType(span.Operation)), 418 Tags: newRPCSpanTags(span), 419 } 420 421 kindTag := span.Tags[string(ext.SpanKind)] 422 data.clientSpan = kindTag == ext.SpanKindRPCClientEnum || kindTag == (ext.SpanKindRPCClientEnum) 423 424 return data 425 } 426 427 // Kind returns instana.EntrySpanKind for server spans and instana.ExitSpanKind otherwise 428 func (d RPCSpanData) Kind() SpanKind { 429 if d.clientSpan { 430 return ExitSpanKind 431 } 432 433 return EntrySpanKind 434 } 435 436 // RPCSpanTags contains fields within the `data.rpc` section of an OT span document 437 type RPCSpanTags struct { 438 // The name of the remote host for an RPC call 439 Host string `json:"host,omitempty"` 440 // The port of the remote host for an RPC call 441 Port string `json:"port,omitempty"` 442 // The name of the remote method to invoke 443 Call string `json:"call,omitempty"` 444 // The type of an RPC call, e.g. either "unary" or "stream" for GRPC requests 445 CallType string `json:"call_type,omitempty"` 446 // The RPC flavor used for this call, e.g. "grpc" for GRPC requests 447 Flavor string `json:"flavor,omitempty"` 448 // The message describing an error occurred during the request handling 449 Error string `json:"error,omitempty"` 450 } 451 452 // newRPCSpanTags extracts RPC-specific span tags from a tracer span 453 func newRPCSpanTags(span *spanS) RPCSpanTags { 454 var tags RPCSpanTags 455 for k, v := range span.Tags { 456 switch k { 457 case "rpc.host": 458 readStringTag(&tags.Host, v) 459 case "rpc.port": 460 readStringTag(&tags.Port, v) 461 case "rpc.call": 462 readStringTag(&tags.Call, v) 463 case "rpc.call_type": 464 readStringTag(&tags.CallType, v) 465 case "rpc.flavor": 466 readStringTag(&tags.Flavor, v) 467 case "rpc.error": 468 readStringTag(&tags.Error, v) 469 } 470 } 471 472 return tags 473 } 474 475 // KafkaSpanData represents the `data` section of an Kafka span sent within an OT span document 476 type KafkaSpanData struct { 477 SpanData 478 Tags KafkaSpanTags `json:"kafka"` 479 480 producerSpan bool 481 } 482 483 // newKafkaSpanData initializes a new Kafka span data from tracer span 484 func newKafkaSpanData(span *spanS) KafkaSpanData { 485 data := KafkaSpanData{ 486 SpanData: NewSpanData(span, RegisteredSpanType(span.Operation)), 487 Tags: newKafkaSpanTags(span), 488 } 489 490 kindTag := span.Tags[string(ext.SpanKind)] 491 data.producerSpan = kindTag == ext.SpanKindProducerEnum || kindTag == string(ext.SpanKindProducerEnum) 492 493 return data 494 } 495 496 // Kind returns instana.ExitSpanKind for producer spans and instana.EntrySpanKind otherwise 497 func (d KafkaSpanData) Kind() SpanKind { 498 if d.producerSpan { 499 return ExitSpanKind 500 } 501 502 return EntrySpanKind 503 } 504 505 // KafkaSpanTags contains fields within the `data.kafka` section of an OT span document 506 type KafkaSpanTags struct { 507 // Kafka topic 508 Service string `json:"service"` 509 // The access mode:, either "send" for publisher or "consume" for consumer 510 Access string `json:"access"` 511 } 512 513 // newKafkaSpanTags extracts Kafka-specific span tags from a tracer span 514 func newKafkaSpanTags(span *spanS) KafkaSpanTags { 515 var tags KafkaSpanTags 516 for k, v := range span.Tags { 517 switch k { 518 case "kafka.service": 519 readStringTag(&tags.Service, v) 520 case "kafka.access": 521 readStringTag(&tags.Access, v) 522 } 523 } 524 525 return tags 526 } 527 528 // RabbitMQSpanData represents the `data` section of an RabbitMQ span 529 type RabbitMQSpanData struct { 530 SpanData 531 Tags RabbitMQSpanTags `json:"rabbitmq"` 532 533 producerSpan bool 534 } 535 536 // newRabbitMQSpanData initializes a new RabbitMQ span data from tracer span 537 func newRabbitMQSpanData(span *spanS) RabbitMQSpanData { 538 data := RabbitMQSpanData{ 539 SpanData: NewSpanData(span, RegisteredSpanType(span.Operation)), 540 Tags: newRabbitMQSpanTags(span), 541 } 542 543 kindTag := span.Tags[string(ext.SpanKind)] 544 data.producerSpan = kindTag == ext.SpanKindProducerEnum || kindTag == string(ext.SpanKindProducerEnum) 545 546 return data 547 } 548 549 // Kind returns instana.ExitSpanKind for producer spans and instana.EntrySpanKind otherwise 550 func (d RabbitMQSpanData) Kind() SpanKind { 551 if d.producerSpan { 552 return ExitSpanKind 553 } 554 555 return EntrySpanKind 556 } 557 558 // RabbitMQSpanTags contains fields within the `data.rabbitmq` section 559 type RabbitMQSpanTags struct { 560 // The RabbitMQ exchange name 561 Exchange string `json:"exchange"` 562 // The routing key 563 Key string `json:"key"` 564 // Indicates wether the message is being produced or consumed 565 Sort string `json:"sort"` 566 // The AMQP URI used to establish a connection to RabbitMQ 567 Address string `json:"address"` 568 // Error is the optional error that can be thrown by RabbitMQ when executing a command 569 Error string `json:"error,omitempty"` 570 } 571 572 // newRabbitMQSpanTags extracts RabbitMQ-specific span tags from a tracer span 573 func newRabbitMQSpanTags(span *spanS) RabbitMQSpanTags { 574 var tags RabbitMQSpanTags 575 for k, v := range span.Tags { 576 switch k { 577 case "rabbitmq.exchange": 578 readStringTag(&tags.Exchange, v) 579 case "rabbitmq.key": 580 readStringTag(&tags.Key, v) 581 case "rabbitmq.sort": 582 readStringTag(&tags.Sort, v) 583 case "rabbitmq.address": 584 readStringTag(&tags.Address, v) 585 case "rabbitmq.error": 586 readStringTag(&tags.Error, v) 587 } 588 } 589 590 return tags 591 } 592 593 // GCPStorageSpanData represents the `data` section of a Google Cloud Storage span sent within an OT span document 594 type GCPStorageSpanData struct { 595 SpanData 596 Tags GCPStorageSpanTags `json:"gcs"` 597 } 598 599 // newGCPStorageSpanData initializes a new Google Cloud Storage span data from tracer span 600 func newGCPStorageSpanData(span *spanS) GCPStorageSpanData { 601 data := GCPStorageSpanData{ 602 SpanData: NewSpanData(span, GCPStorageSpanType), 603 Tags: newGCPStorageSpanTags(span), 604 } 605 606 return data 607 } 608 609 // Kind returns the span kind for a Google Cloud Storage span 610 func (d GCPStorageSpanData) Kind() SpanKind { 611 return ExitSpanKind 612 } 613 614 // GCPStorageSpanTags contains fields within the `data.gcs` section of an OT span document 615 type GCPStorageSpanTags struct { 616 Operation string `json:"op,omitempty"` 617 Bucket string `json:"bucket,omitempty"` 618 Object string `json:"object,omitempty"` 619 Entity string `json:"entity,omitempty"` 620 Range string `json:"range,omitempty"` 621 SourceBucket string `json:"sourceBucket,omitempty"` 622 SourceObject string `json:"sourceObject,omitempty"` 623 DestinationBucket string `json:"destinationBucket,omitempty"` 624 DestinationObject string `json:"destinationObject,omitempty"` 625 NumberOfOperations string `json:"numberOfOperations,omitempty"` 626 ProjectID string `json:"projectId,omitempty"` 627 AccessID string `json:"accessId,omitempty"` 628 } 629 630 // newGCPStorageSpanTags extracts Google Cloud Storage span tags from a tracer span 631 func newGCPStorageSpanTags(span *spanS) GCPStorageSpanTags { 632 var tags GCPStorageSpanTags 633 for k, v := range span.Tags { 634 switch k { 635 case "gcs.op": 636 readStringTag(&tags.Operation, v) 637 case "gcs.bucket": 638 readStringTag(&tags.Bucket, v) 639 case "gcs.object": 640 readStringTag(&tags.Object, v) 641 case "gcs.entity": 642 readStringTag(&tags.Entity, v) 643 case "gcs.range": 644 readStringTag(&tags.Range, v) 645 case "gcs.sourceBucket": 646 readStringTag(&tags.SourceBucket, v) 647 case "gcs.sourceObject": 648 readStringTag(&tags.SourceObject, v) 649 case "gcs.destinationBucket": 650 readStringTag(&tags.DestinationBucket, v) 651 case "gcs.destinationObject": 652 readStringTag(&tags.DestinationObject, v) 653 case "gcs.numberOfOperations": 654 readStringTag(&tags.NumberOfOperations, v) 655 case "gcs.projectId": 656 readStringTag(&tags.ProjectID, v) 657 case "gcs.accessId": 658 readStringTag(&tags.AccessID, v) 659 } 660 } 661 662 return tags 663 } 664 665 // GCPPubSubSpanData represents the `data` section of a Google Cloud Pub/Sub span sent within an OT span document 666 type GCPPubSubSpanData struct { 667 SpanData 668 Tags GCPPubSubSpanTags `json:"gcps"` 669 } 670 671 // newGCPPubSubSpanData initializes a new Google Cloud Pub/Span span data from tracer span 672 func newGCPPubSubSpanData(span *spanS) GCPPubSubSpanData { 673 data := GCPPubSubSpanData{ 674 SpanData: NewSpanData(span, GCPPubSubSpanType), 675 Tags: newGCPPubSubSpanTags(span), 676 } 677 678 return data 679 } 680 681 // Kind returns the span kind for a Google Cloud Pub/Sub span 682 func (d GCPPubSubSpanData) Kind() SpanKind { 683 switch strings.ToLower(d.Tags.Operation) { 684 case "consume": 685 return EntrySpanKind 686 default: 687 return ExitSpanKind 688 } 689 } 690 691 // GCPPubSubSpanTags contains fields within the `data.gcps` section of an OT span document 692 type GCPPubSubSpanTags struct { 693 ProjectID string `json:"projid"` 694 Operation string `json:"op"` 695 Topic string `json:"top,omitempty"` 696 Subscription string `json:"sub,omitempty"` 697 MessageID string `json:"msgid,omitempty"` 698 } 699 700 // newGCPPubSubSpanTags extracts Google Cloud Pub/Sub span tags from a tracer span 701 func newGCPPubSubSpanTags(span *spanS) GCPPubSubSpanTags { 702 var tags GCPPubSubSpanTags 703 for k, v := range span.Tags { 704 switch k { 705 case "gcps.projid": 706 readStringTag(&tags.ProjectID, v) 707 case "gcps.op": 708 readStringTag(&tags.Operation, v) 709 case "gcps.top": 710 readStringTag(&tags.Topic, v) 711 case "gcps.sub": 712 readStringTag(&tags.Subscription, v) 713 case "gcps.msgid": 714 readStringTag(&tags.MessageID, v) 715 } 716 } 717 718 return tags 719 } 720 721 // AWSLambdaCloudWatchSpanTags contains fields within the `data.lambda.cw` section of an OT span document 722 type AWSLambdaCloudWatchSpanTags struct { 723 Events *AWSLambdaCloudWatchEventTags `json:"events,omitempty"` 724 Logs *AWSLambdaCloudWatchLogsTags `json:"logs,omitempty"` 725 } 726 727 // newAWSLambdaCloudWatchSpanTags extracts CloudWatch tags for an AWS Lambda entry span 728 func newAWSLambdaCloudWatchSpanTags(span *spanS) AWSLambdaCloudWatchSpanTags { 729 var tags AWSLambdaCloudWatchSpanTags 730 731 if events := newAWSLambdaCloudWatchEventTags(span); !events.IsZero() { 732 tags.Events = &events 733 } 734 735 if logs := newAWSLambdaCloudWatchLogsTags(span); !logs.IsZero() { 736 tags.Logs = &logs 737 } 738 739 return tags 740 } 741 742 // IsZero returns true if an AWSLambdaCloudWatchSpanTags struct was populated with event data 743 func (tags AWSLambdaCloudWatchSpanTags) IsZero() bool { 744 return (tags.Events == nil || tags.Events.IsZero()) && (tags.Logs == nil || tags.Logs.IsZero()) 745 } 746 747 // AWSLambdaCloudWatchEventTags contains fields within the `data.lambda.cw.events` section of an OT span document 748 type AWSLambdaCloudWatchEventTags struct { 749 // ID is the ID of the event 750 ID string `json:"id"` 751 // Resources contains the event resources 752 Resources []string `json:"resources"` 753 // More is set to true if the event resources list was truncated 754 More bool `json:"more,omitempty"` 755 } 756 757 // newAWSLambdaCloudWatchEventTags extracts CloudWatch event tags for an AWS Lambda entry span. It truncates 758 // the resources list to the first 3 items, populating the `data.lambda.cw.events.more` tag and limits each 759 // resource string to the first 200 characters to reduce the payload. 760 func newAWSLambdaCloudWatchEventTags(span *spanS) AWSLambdaCloudWatchEventTags { 761 var tags AWSLambdaCloudWatchEventTags 762 763 if v, ok := span.Tags["cloudwatch.events.id"]; ok { 764 readStringTag(&tags.ID, v) 765 } 766 767 if v, ok := span.Tags["cloudwatch.events.resources"]; ok { 768 switch v := v.(type) { 769 case []string: 770 if len(v) > 3 { 771 v = v[:3] 772 tags.More = true 773 } 774 775 tags.Resources = v 776 case string: 777 tags.Resources = []string{v} 778 case []byte: 779 tags.Resources = []string{string(v)} 780 } 781 } 782 783 // truncate resources 784 if len(tags.Resources) > 3 { 785 tags.Resources, tags.More = tags.Resources[:3], true 786 } 787 788 for i := range tags.Resources { 789 if len(tags.Resources[i]) > 200 { 790 tags.Resources[i] = tags.Resources[i][:200] 791 } 792 } 793 794 return tags 795 } 796 797 // IsZero returns true if an AWSCloudWatchEventTags struct was populated with event data 798 func (tags AWSLambdaCloudWatchEventTags) IsZero() bool { 799 return tags.ID == "" 800 } 801 802 // AWSLambdaCloudWatchLogsTags contains fields within the `data.lambda.cw.logs` section of an OT span document 803 type AWSLambdaCloudWatchLogsTags struct { 804 Group string `json:"group"` 805 Stream string `json:"stream"` 806 Events []string `json:"events"` 807 More bool `json:"more,omitempty"` 808 DecodingError string `json:"decodingError,omitempty"` 809 } 810 811 // newAWSLambdaCloudWatchLogsTags extracts CloudWatch Logs tags for an AWS Lambda entry span. It truncates 812 // the log events list to the first 3 items, populating the `data.lambda.cw.logs.more` tag and limits each 813 // log string to the first 200 characters to reduce the payload. 814 func newAWSLambdaCloudWatchLogsTags(span *spanS) AWSLambdaCloudWatchLogsTags { 815 var tags AWSLambdaCloudWatchLogsTags 816 817 if v, ok := span.Tags["cloudwatch.logs.group"]; ok { 818 readStringTag(&tags.Group, v) 819 } 820 821 if v, ok := span.Tags["cloudwatch.logs.stream"]; ok { 822 readStringTag(&tags.Stream, v) 823 } 824 825 if v, ok := span.Tags["cloudwatch.logs.decodingError"]; ok { 826 switch v := v.(type) { 827 case error: 828 tags.DecodingError = v.Error() 829 case string: 830 tags.DecodingError = v 831 } 832 } 833 834 if v, ok := span.Tags["cloudwatch.logs.events"]; ok { 835 switch v := v.(type) { 836 case []string: 837 if len(v) > 3 { 838 v = v[:3] 839 tags.More = true 840 } 841 842 tags.Events = v 843 case string: 844 tags.Events = []string{v} 845 case []byte: 846 tags.Events = []string{string(v)} 847 } 848 } 849 850 // truncate events 851 if len(tags.Events) > 3 { 852 tags.Events, tags.More = tags.Events[:3], true 853 } 854 855 for i := range tags.Events { 856 if len(tags.Events[i]) > 200 { 857 tags.Events[i] = tags.Events[i][:200] 858 } 859 } 860 861 return tags 862 } 863 864 // IsZero returns true if an AWSLambdaCloudWatchLogsTags struct was populated with logs data 865 func (tags AWSLambdaCloudWatchLogsTags) IsZero() bool { 866 return tags.Group == "" && tags.Stream == "" && tags.DecodingError == "" 867 } 868 869 // AWSS3EventTags represens metadata for an S3 event 870 type AWSS3EventTags struct { 871 Name string `json:"event"` 872 Bucket string `json:"bucket"` 873 Object string `json:"object,omitempty"` 874 } 875 876 // AWSLambdaS3SpanTags contains fields within the `data.lambda.s3` section of an OT span document 877 type AWSLambdaS3SpanTags struct { 878 Events []AWSS3EventTags `json:"events,omitempty"` 879 } 880 881 // newAWSLambdaS3SpanTags extracts S3 Event tags for an AWS Lambda entry span. It truncates 882 // the events list to the first 3 items and limits each object names to the first 200 characters to reduce the payload. 883 func newAWSLambdaS3SpanTags(span *spanS) AWSLambdaS3SpanTags { 884 var tags AWSLambdaS3SpanTags 885 886 if events, ok := span.Tags["s3.events"]; ok { 887 events, ok := events.([]AWSS3EventTags) 888 if ok { 889 tags.Events = events 890 } 891 } 892 893 if len(tags.Events) > 3 { 894 tags.Events = tags.Events[:3] 895 } 896 897 for i := range tags.Events { 898 if len(tags.Events[i].Object) > 200 { 899 tags.Events[i].Object = tags.Events[i].Object[:200] 900 } 901 } 902 903 return tags 904 } 905 906 // IsZero returns true if an AWSLambdaS3SpanTags struct was populated with events data 907 func (tags AWSLambdaS3SpanTags) IsZero() bool { 908 return len(tags.Events) == 0 909 } 910 911 // AWSSQSMessageTags represents span tags for an SQS message delivery 912 type AWSSQSMessageTags struct { 913 Queue string `json:"queue"` 914 } 915 916 // AWSLambdaSQSSpanTags contains fields within the `data.lambda.sqs` section of an OT span document 917 type AWSLambdaSQSSpanTags struct { 918 // Messages are message tags for an SQS event 919 Messages []AWSSQSMessageTags `json:"messages"` 920 } 921 922 // newAWSLambdaSQSSpanTags extracts SQS event tags for an AWS Lambda entry span. It truncates 923 // the events list to the first 3 items to reduce the payload. 924 func newAWSLambdaSQSSpanTags(span *spanS) AWSLambdaSQSSpanTags { 925 var tags AWSLambdaSQSSpanTags 926 927 if msgs, ok := span.Tags["sqs.messages"]; ok { 928 msgs, ok := msgs.([]AWSSQSMessageTags) 929 if ok { 930 tags.Messages = msgs 931 } 932 } 933 934 if len(tags.Messages) > 3 { 935 tags.Messages = tags.Messages[:3] 936 } 937 938 return tags 939 } 940 941 // IsZero returns true if an AWSLambdaSQSSpanTags struct was populated with messages data 942 func (tags AWSLambdaSQSSpanTags) IsZero() bool { 943 return len(tags.Messages) == 0 944 } 945 946 // AWSLambdaSpanTags contains fields within the `data.lambda` section of an OT span document 947 type AWSLambdaSpanTags struct { 948 // ARN is the ARN of invoked AWS Lambda function with the version attached 949 ARN string `json:"arn"` 950 // Runtime is an Instana constant for this AWS lambda runtime (always "go") 951 Runtime string `json:"runtime"` 952 // Name is the name of invoked function 953 Name string `json:"functionName,omitempty"` 954 // Version is either the numeric version or $LATEST 955 Version string `json:"functionVersion,omitempty"` 956 // Trigger is the trigger event type (if any) 957 Trigger string `json:"trigger,omitempty"` 958 // ColdStart is true if this is the first time current instance of the function was invoked 959 ColdStart bool `json:"coldStart,omitempty"` 960 // MillisecondsLeft is a number of milliseconds until timeout 961 MillisecondsLeft int `json:"msleft,omitempty"` 962 // Error is an AWS Lambda specific error 963 Error string `json:"error,omitempty"` 964 // CloudWatch holds the details of a CloudWatch event associated with this lambda 965 CloudWatch *AWSLambdaCloudWatchSpanTags `json:"cw,omitempty"` 966 // S3 holds the details of a S3 events associated with this lambda 967 S3 *AWSLambdaS3SpanTags 968 // SQS holds the details of a SQS events associated with this lambda 969 SQS *AWSLambdaSQSSpanTags 970 } 971 972 // newAWSLambdaSpanTags extracts AWS Lambda entry span tags from a tracer span 973 func newAWSLambdaSpanTags(span *spanS) AWSLambdaSpanTags { 974 tags := AWSLambdaSpanTags{Runtime: "go"} 975 976 if v, ok := span.Tags["lambda.arn"]; ok { 977 readStringTag(&tags.ARN, v) 978 } 979 980 if v, ok := span.Tags["lambda.name"]; ok { 981 readStringTag(&tags.Name, v) 982 } 983 984 if v, ok := span.Tags["lambda.version"]; ok { 985 readStringTag(&tags.Version, v) 986 } 987 988 if v, ok := span.Tags["lambda.trigger"]; ok { 989 readStringTag(&tags.Trigger, v) 990 } 991 992 if v, ok := span.Tags["lambda.coldStart"]; ok { 993 readBoolTag(&tags.ColdStart, v) 994 } 995 996 if v, ok := span.Tags["lambda.msleft"]; ok { 997 readIntTag(&tags.MillisecondsLeft, v) 998 } 999 1000 if v, ok := span.Tags["lambda.error"]; ok { 1001 readStringTag(&tags.Error, v) 1002 } 1003 1004 if cw := newAWSLambdaCloudWatchSpanTags(span); !cw.IsZero() { 1005 tags.CloudWatch = &cw 1006 } 1007 1008 if st := newAWSLambdaS3SpanTags(span); !st.IsZero() { 1009 tags.S3 = &st 1010 } 1011 1012 if sqs := newAWSLambdaSQSSpanTags(span); !sqs.IsZero() { 1013 tags.SQS = &sqs 1014 } 1015 1016 return tags 1017 } 1018 1019 // AWSLambdaSpanData is the base span data type for AWS Lambda entry spans 1020 type AWSLambdaSpanData struct { 1021 Snapshot AWSLambdaSpanTags `json:"lambda"` 1022 HTTP *HTTPSpanTags `json:"http,omitempty"` 1023 } 1024 1025 // newAWSLambdaSpanData initializes a new AWSLambdaSpanData from span 1026 func newAWSLambdaSpanData(span *spanS) AWSLambdaSpanData { 1027 d := AWSLambdaSpanData{ 1028 Snapshot: newAWSLambdaSpanTags(span), 1029 } 1030 1031 switch span.Tags["lambda.trigger"] { 1032 case "aws:api.gateway", "aws:application.load.balancer": 1033 tags := newHTTPSpanTags(span) 1034 d.HTTP = &tags 1035 } 1036 1037 return d 1038 } 1039 1040 // Type returns the span type for an AWS Lambda span 1041 func (d AWSLambdaSpanData) Type() RegisteredSpanType { 1042 return AWSLambdaEntrySpanType 1043 } 1044 1045 // Kind returns the span kind for an AWS Lambda span 1046 func (d AWSLambdaSpanData) Kind() SpanKind { 1047 return EntrySpanKind 1048 } 1049 1050 // AWSS3SpanData represents the `data` section of a AWS S3 span sent within an OT span document 1051 type AWSS3SpanData struct { 1052 SpanData 1053 Tags AWSS3SpanTags `json:"s3"` 1054 } 1055 1056 // newAWSS3SpanData initializes a new AWS S3 span data from tracer span 1057 func newAWSS3SpanData(span *spanS) AWSS3SpanData { 1058 data := AWSS3SpanData{ 1059 SpanData: NewSpanData(span, AWSS3SpanType), 1060 Tags: newAWSS3SpanTags(span), 1061 } 1062 1063 return data 1064 } 1065 1066 // Kind returns the span kind for a AWS S3 span 1067 func (d AWSS3SpanData) Kind() SpanKind { 1068 return ExitSpanKind 1069 } 1070 1071 // AWSS3SpanTags contains fields within the `data.s3` section of an OT span document 1072 type AWSS3SpanTags struct { 1073 // Region is the AWS region used to access S3 1074 Region string `json:"region,omitempty"` 1075 // Operation is the operation name, as defined by AWS S3 API 1076 Operation string `json:"op,omitempty"` 1077 // Bucket is the bucket name 1078 Bucket string `json:"bucket,omitempty"` 1079 // Key is the object key 1080 Key string `json:"key,omitempty"` 1081 // Error is an optional error returned by AWS API 1082 Error string `json:"error,omitempty"` 1083 } 1084 1085 // newAWSS3SpanTags extracts AWS S3 span tags from a tracer span 1086 func newAWSS3SpanTags(span *spanS) AWSS3SpanTags { 1087 var tags AWSS3SpanTags 1088 for k, v := range span.Tags { 1089 switch k { 1090 case "s3.region": 1091 readStringTag(&tags.Region, v) 1092 case "s3.op": 1093 readStringTag(&tags.Operation, v) 1094 case "s3.bucket": 1095 readStringTag(&tags.Bucket, v) 1096 case "s3.key": 1097 readStringTag(&tags.Key, v) 1098 case "s3.error": 1099 readStringTag(&tags.Error, v) 1100 } 1101 } 1102 1103 return tags 1104 } 1105 1106 // AWSSQSSpanData represents the `data` section of a AWS SQS span sent within an OT span document 1107 type AWSSQSSpanData struct { 1108 SpanData 1109 Tags AWSSQSSpanTags `json:"sqs"` 1110 } 1111 1112 // newAWSSQSSpanData initializes a new AWS SQS span data from tracer span 1113 func newAWSSQSSpanData(span *spanS) AWSSQSSpanData { 1114 data := AWSSQSSpanData{ 1115 SpanData: NewSpanData(span, AWSSQSSpanType), 1116 Tags: newAWSSQSSpanTags(span), 1117 } 1118 1119 return data 1120 } 1121 1122 // Kind returns the span kind for a AWS SQS span 1123 func (d AWSSQSSpanData) Kind() SpanKind { 1124 switch d.Tags.Sort { 1125 case "entry": 1126 return EntrySpanKind 1127 case "exit": 1128 return ExitSpanKind 1129 default: 1130 return IntermediateSpanKind 1131 } 1132 } 1133 1134 // AWSSQSSpanTags contains fields within the `data.sqs` section of an OT span document 1135 type AWSSQSSpanTags struct { 1136 // Sort is the direction of the call, wither "entry" or "exit" 1137 Sort string `json:"sort,omitempty"` 1138 // Queue is the queue name 1139 Queue string `json:"queue,omitempty"` 1140 // Type is the operation name 1141 Type string `json:"type,omitempty"` 1142 // MessageGroupID is the message group ID specified while sending messages 1143 MessageGroupID string `json:"group,omitempty"` 1144 // Size is the optional batch size 1145 Size int `json:"size,omitempty"` 1146 // Error is an optional error returned by AWS API 1147 Error string `json:"error,omitempty"` 1148 } 1149 1150 // newAWSSQSSpanTags extracts AWS SQS span tags from a tracer span 1151 func newAWSSQSSpanTags(span *spanS) AWSSQSSpanTags { 1152 var tags AWSSQSSpanTags 1153 for k, v := range span.Tags { 1154 switch k { 1155 case "sqs.sort": 1156 readStringTag(&tags.Sort, v) 1157 case "sqs.queue": 1158 readStringTag(&tags.Queue, v) 1159 case "sqs.type": 1160 readStringTag(&tags.Type, v) 1161 case "sqs.group": 1162 readStringTag(&tags.MessageGroupID, v) 1163 case "sqs.size": 1164 readIntTag(&tags.Size, v) 1165 case "sqs.error": 1166 readStringTag(&tags.Error, v) 1167 } 1168 } 1169 1170 return tags 1171 } 1172 1173 // AWSSNSSpanData represents the `data` section of a AWS SNS span sent within an OT span document 1174 type AWSSNSSpanData struct { 1175 SpanData 1176 Tags AWSSNSSpanTags `json:"sns"` 1177 } 1178 1179 // newAWSSNSSpanData initializes a new AWS SNS span data from tracer span 1180 func newAWSSNSSpanData(span *spanS) AWSSNSSpanData { 1181 data := AWSSNSSpanData{ 1182 SpanData: NewSpanData(span, AWSSNSSpanType), 1183 Tags: newAWSSNSSpanTags(span), 1184 } 1185 1186 return data 1187 } 1188 1189 // Kind returns the span kind for a AWS SNS span 1190 func (d AWSSNSSpanData) Kind() SpanKind { 1191 return ExitSpanKind 1192 } 1193 1194 // AWSSNSSpanTags contains fields within the `data.sns` section of an OT span document 1195 type AWSSNSSpanTags struct { 1196 // TopicARN is the topic ARN of an SNS message 1197 TopicARN string `json:"topic,omitempty"` 1198 // TargetARN is the target ARN of an SNS message 1199 TargetARN string `json:"target,omitempty"` 1200 // Phone is the phone no. of an SNS message 1201 Phone string `json:"phone,omitempty"` 1202 // Subject is the subject of an SNS message 1203 Subject string `json:"subject,omitempty"` 1204 // Error is an optional error returned by AWS API 1205 Error string `json:"error,omitempty"` 1206 } 1207 1208 // newAWSSNSSpanTags extracts AWS SNS span tags from a tracer span 1209 func newAWSSNSSpanTags(span *spanS) AWSSNSSpanTags { 1210 var tags AWSSNSSpanTags 1211 for k, v := range span.Tags { 1212 switch k { 1213 case "sns.topic": 1214 readStringTag(&tags.TopicARN, v) 1215 case "sns.target": 1216 readStringTag(&tags.TargetARN, v) 1217 case "sns.phone": 1218 readStringTag(&tags.Phone, v) 1219 case "sns.subject": 1220 readStringTag(&tags.Subject, v) 1221 case "sns.error": 1222 readStringTag(&tags.Error, v) 1223 } 1224 } 1225 1226 return tags 1227 } 1228 1229 // AWSDynamoDBSpanData represents the `data` section of a AWS DynamoDB span sent within an OT span document 1230 type AWSDynamoDBSpanData struct { 1231 SpanData 1232 Tags AWSDynamoDBSpanTags `json:"dynamodb"` 1233 } 1234 1235 // newAWSDynamoDBSpanData initializes a new AWS DynamoDB span data from tracer span 1236 func newAWSDynamoDBSpanData(span *spanS) AWSDynamoDBSpanData { 1237 data := AWSDynamoDBSpanData{ 1238 SpanData: NewSpanData(span, AWSDynamoDBSpanType), 1239 Tags: newAWSDynamoDBSpanTags(span), 1240 } 1241 1242 return data 1243 } 1244 1245 // Kind returns the span kind for a AWS DynamoDB span 1246 func (d AWSDynamoDBSpanData) Kind() SpanKind { 1247 return ExitSpanKind 1248 } 1249 1250 // AWSDynamoDBSpanTags contains fields within the `data.sns` section of an OT span document 1251 type AWSDynamoDBSpanTags struct { 1252 // Table is the name of DynamoDB table 1253 Table string `json:"table,omitempty"` 1254 // Operation is the operation name 1255 Operation string `json:"op,omitempty"` 1256 // Error is an optional name returned by AWS API 1257 Error string `json:"error,omitempty"` 1258 // Region is a region from the AWS session config 1259 Region string `json:"region,omitempty"` 1260 } 1261 1262 // newAWSDynamoDBSpanTags extracts AWS DynamoDB span tags from a tracer span 1263 func newAWSDynamoDBSpanTags(span *spanS) AWSDynamoDBSpanTags { 1264 var tags AWSDynamoDBSpanTags 1265 for k, v := range span.Tags { 1266 switch k { 1267 case "dynamodb.table": 1268 readStringTag(&tags.Table, v) 1269 case "dynamodb.op": 1270 readStringTag(&tags.Operation, v) 1271 case "dynamodb.error": 1272 readStringTag(&tags.Error, v) 1273 case "dynamodb.region": 1274 readStringTag(&tags.Region, v) 1275 } 1276 } 1277 1278 return tags 1279 } 1280 1281 // AWSInvokeSpanTags contains fields within the `aws.lambda.invoke` section of an OT span document 1282 type AWSInvokeSpanTags struct { 1283 // FunctionName is a name of the function which is invoked 1284 FunctionName string `json:"function"` 1285 // InvocationType if equal to `Event`, means it is an async invocation 1286 InvocationType string `json:"type"` 1287 // Error is an optional error returned by AWS API 1288 Error string `json:"error,omitempty"` 1289 } 1290 1291 func newAWSDInvokeSpanTags(span *spanS) AWSInvokeSpanTags { 1292 var tags AWSInvokeSpanTags 1293 for k, v := range span.Tags { 1294 switch k { 1295 case "function": 1296 readStringTag(&tags.FunctionName, v) 1297 case "type": 1298 readStringTag(&tags.InvocationType, v) 1299 case "error": 1300 readStringTag(&tags.Error, v) 1301 } 1302 } 1303 1304 return tags 1305 } 1306 1307 // AWSLambdaInvokeSpanData represents the `data` section of a AWS Invoke span sent within an OT span document 1308 type AWSLambdaInvokeSpanData struct { 1309 SpanData 1310 Tags AWSInvokeSpanTags `json:"aws.lambda.invoke"` 1311 } 1312 1313 // Kind returns the span kind for a AWS SDK Invoke span 1314 func (d AWSLambdaInvokeSpanData) Kind() SpanKind { 1315 return ExitSpanKind 1316 } 1317 1318 // Type returns the span type for an AWS SDK Invoke span 1319 func (d AWSLambdaInvokeSpanData) Type() RegisteredSpanType { 1320 return AWSLambdaInvokeSpanType 1321 } 1322 1323 // newAWSLambdaInvokeSpanData initializes a new AWS Invoke span data from tracer span 1324 func newAWSLambdaInvokeSpanData(span *spanS) AWSLambdaInvokeSpanData { 1325 data := AWSLambdaInvokeSpanData{ 1326 SpanData: NewSpanData(span, AWSLambdaInvokeSpanType), 1327 Tags: newAWSDInvokeSpanTags(span), 1328 } 1329 1330 return data 1331 } 1332 1333 // LogSpanData represents the `data` section of a logging span 1334 type LogSpanData struct { 1335 SpanData 1336 Tags LogSpanTags `json:"log"` 1337 } 1338 1339 // newLogSpanData initializes a new logging span data from tracer span 1340 func newLogSpanData(span *spanS) LogSpanData { 1341 return LogSpanData{ 1342 SpanData: NewSpanData(span, LogSpanType), 1343 Tags: newLogSpanTags(span), 1344 } 1345 } 1346 1347 // Kind returns the span kind for a logging span 1348 func (d LogSpanData) Kind() SpanKind { 1349 return ExitSpanKind 1350 } 1351 1352 // LogSpanTags contains fields within the `data.log` section of an OT span document 1353 type LogSpanTags struct { 1354 // Message is a string to log 1355 Message string `json:"message"` 1356 // Level is an optional log level for this record, e.g. INFO 1357 Level string `json:"level,omitempty"` 1358 // Logger is an optional logger name 1359 Logger string `json:"logger,omitempty"` 1360 // Error is an optional error string (if any) 1361 Error string `json:"parameters,omitempty"` 1362 } 1363 1364 func newLogSpanTags(span *spanS) LogSpanTags { 1365 var tags LogSpanTags 1366 for k, v := range span.Tags { 1367 switch k { 1368 case "log.message": 1369 readStringTag(&tags.Message, v) 1370 case "log.level": 1371 readStringTag(&tags.Level, v) 1372 case "log.parameters": 1373 readStringTag(&tags.Error, v) 1374 case "log.logger": 1375 readStringTag(&tags.Logger, v) 1376 } 1377 } 1378 1379 return tags 1380 } 1381 1382 // MongoDBSpanData represents the `data` section of a MongoDB client span 1383 type MongoDBSpanData struct { 1384 SpanData 1385 Tags MongoDBSpanTags `json:"mongo"` 1386 } 1387 1388 // newMongoDBSpanData initializes a new MongoDB clientspan data from tracer span 1389 func newMongoDBSpanData(span *spanS) MongoDBSpanData { 1390 return MongoDBSpanData{ 1391 SpanData: NewSpanData(span, MongoDBSpanType), 1392 Tags: newMongoDBSpanTags(span), 1393 } 1394 } 1395 1396 // RedisSpanData represents the `data` section of a Redis client span 1397 type RedisSpanData struct { 1398 SpanData 1399 Tags RedisSpanTags `json:"redis"` 1400 } 1401 1402 // newRedisSpanData initializes a new Redis clientspan data from tracer span 1403 func newRedisSpanData(span *spanS) RedisSpanData { 1404 return RedisSpanData{ 1405 SpanData: NewSpanData(span, RedisSpanType), 1406 Tags: newRedisSpanTags(span), 1407 } 1408 } 1409 1410 // Kind returns the span kind for a Redis client span 1411 func (d RedisSpanData) Kind() SpanKind { 1412 return ExitSpanKind 1413 } 1414 1415 // Kind returns the span kind for a MongoDB client span 1416 func (d MongoDBSpanData) Kind() SpanKind { 1417 return ExitSpanKind 1418 } 1419 1420 // MongoDBSpanTags contains fields within the `data.mongo` section of an OT span document 1421 type MongoDBSpanTags struct { 1422 // Service is the MongoDB server address in form of host:port 1423 Service string `json:"service"` 1424 // Namespace is the namespace name 1425 Namespace string `json:"namespace"` 1426 // Command is the name of the command initiated the span 1427 Command string `json:"command"` 1428 // Query is an optional query passed with command 1429 Query string `json:"query,omitempty"` 1430 // JSON is an optional JSON aggregation provided with command 1431 JSON string `json:"json,omitempty"` 1432 // Filter is an optional filter passed with command 1433 Filter string `json:"filter,omitempty"` 1434 // Error is an optional error message 1435 Error string `json:"error,omitempty"` 1436 } 1437 1438 func newMongoDBSpanTags(span *spanS) MongoDBSpanTags { 1439 var tags MongoDBSpanTags 1440 for k, v := range span.Tags { 1441 switch k { 1442 case "mongo.service": 1443 readStringTag(&tags.Service, v) 1444 case "mongo.namespace": 1445 readStringTag(&tags.Namespace, v) 1446 case "mongo.command": 1447 readStringTag(&tags.Command, v) 1448 case "mongo.query": 1449 readStringTag(&tags.Query, v) 1450 case "mongo.json": 1451 readStringTag(&tags.JSON, v) 1452 case "mongo.filter": 1453 readStringTag(&tags.Filter, v) 1454 case "mongo.error": 1455 readStringTag(&tags.Error, v) 1456 } 1457 } 1458 1459 return tags 1460 } 1461 1462 // PostgreSQLSpanData represents the `data` section of a PostgreSQL client span 1463 type PostgreSQLSpanData struct { 1464 SpanData 1465 Tags PostgreSQLSpanTags `json:"pg"` 1466 } 1467 1468 // newPostgreSQLSpanData initializes a new PostgreSQL client span data from tracer span 1469 func newPostgreSQLSpanData(span *spanS) PostgreSQLSpanData { 1470 return PostgreSQLSpanData{ 1471 SpanData: NewSpanData(span, PostgreSQLSpanType), 1472 Tags: newPostgreSQLSpanTags(span), 1473 } 1474 } 1475 1476 // Kind returns the span kind for a PostgreSQL client span 1477 func (d PostgreSQLSpanData) Kind() SpanKind { 1478 return ExitSpanKind 1479 } 1480 1481 // PostgreSQLSpanTags contains fields within the `data.pg` section of an OT span document 1482 type PostgreSQLSpanTags struct { 1483 Host string `json:"host"` 1484 Port string `json:"port"` 1485 DB string `json:"db"` 1486 User string `json:"user"` 1487 Stmt string `json:"stmt"` 1488 1489 Error string `json:"error,omitempty"` 1490 } 1491 1492 func newPostgreSQLSpanTags(span *spanS) PostgreSQLSpanTags { 1493 var tags PostgreSQLSpanTags 1494 for k, v := range span.Tags { 1495 switch k { 1496 case "pg.host": 1497 readStringTag(&tags.Host, v) 1498 case "pg.port": 1499 readStringTag(&tags.Port, v) 1500 case "pg.db": 1501 readStringTag(&tags.DB, v) 1502 case "pg.stmt": 1503 readStringTag(&tags.Stmt, v) 1504 case "pg.user": 1505 readStringTag(&tags.User, v) 1506 case "pg.error": 1507 readStringTag(&tags.Error, v) 1508 } 1509 } 1510 return tags 1511 } 1512 1513 // CouchbaseSpanData represents the `data` section of a Couchbase client span 1514 type CouchbaseSpanData struct { 1515 SpanData 1516 Tags CouchbaseSpanTags `json:"couchbase"` 1517 } 1518 1519 // newCouchbaseSpanData initializes a new Couchbase client span data from tracer span 1520 func newCouchbaseSpanData(span *spanS) CouchbaseSpanData { 1521 return CouchbaseSpanData{ 1522 SpanData: NewSpanData(span, CouchbaseSpanType), 1523 Tags: newCouchbaseSpanTags(span), 1524 } 1525 } 1526 1527 // Kind returns the span kind for a Couchbase client span 1528 func (c CouchbaseSpanData) Kind() SpanKind { 1529 return ExitSpanKind 1530 } 1531 1532 // CouchbaseSpanTags contains fields within the `data.couchbase` section of an OT span document 1533 type CouchbaseSpanTags struct { 1534 Bucket string `json:"bucket"` 1535 Host string `json:"hostname"` 1536 Type string `json:"type"` 1537 SQL string `json:"sql"` 1538 1539 Error string `json:"error,omitempty"` 1540 } 1541 1542 // CosmosSpanData represents the `data` section of a Cosmos client span 1543 type CosmosSpanData struct { 1544 SpanData 1545 Tags CosmosSpanTags `json:"cosmos"` 1546 } 1547 1548 // newCosmosSpanData initializes a new Cosmos client span data from tracer span 1549 func newCosmosSpanData(span *spanS) CosmosSpanData { 1550 return CosmosSpanData{ 1551 SpanData: NewSpanData(span, CosmosSpanType), 1552 Tags: newCosmosSpanTags(span), 1553 } 1554 } 1555 1556 // Kind returns the span kind for a Cosmos client span 1557 func (c CosmosSpanData) Kind() SpanKind { 1558 return ExitSpanKind 1559 } 1560 1561 // CosmosSpanTags contains fields within the `data.cosmos` section of an OT span document 1562 type CosmosSpanTags struct { 1563 ConnectionURL string `json:"con"` 1564 Database string `json:"db"` 1565 Type string `json:"type"` 1566 Sql string `json:"cmd"` 1567 Object string `json:"obj"` 1568 PartitionKey string `json:"pk"` 1569 ReturnCode string `json:"rt"` 1570 Error string `json:"error,omitempty"` 1571 } 1572 1573 func newCosmosSpanTags(span *spanS) CosmosSpanTags { 1574 var tags CosmosSpanTags 1575 for k, v := range span.Tags { 1576 switch k { 1577 case "cosmos.con": 1578 readStringTag(&tags.ConnectionURL, v) 1579 case "cosmos.db": 1580 readStringTag(&tags.Database, v) 1581 case "cosmos.type": 1582 readStringTag(&tags.Type, v) 1583 case "cosmos.rt": 1584 readStringTag(&tags.ReturnCode, v) 1585 case "cosmos.cmd": 1586 readStringTag(&tags.Sql, v) 1587 case "cosmos.obj": 1588 readStringTag(&tags.Object, v) 1589 case "cosmos.pk": 1590 readStringTag(&tags.PartitionKey, v) 1591 case "cosmos.error": 1592 readStringTag(&tags.Error, v) 1593 } 1594 } 1595 return tags 1596 } 1597 1598 func newCouchbaseSpanTags(span *spanS) CouchbaseSpanTags { 1599 var tags CouchbaseSpanTags 1600 for k, v := range span.Tags { 1601 switch k { 1602 case "couchbase.bucket": 1603 readStringTag(&tags.Bucket, v) 1604 case "couchbase.hostname": 1605 readStringTag(&tags.Host, v) 1606 case "couchbase.type": 1607 readStringTag(&tags.Type, v) 1608 case "couchbase.sql": 1609 readStringTag(&tags.SQL, v) 1610 case "couchbase.error": 1611 readStringTag(&tags.Error, v) 1612 } 1613 } 1614 return tags 1615 } 1616 1617 // MySQLSpanData represents the `data` section of a MySQL client span 1618 type MySQLSpanData struct { 1619 SpanData 1620 Tags MySQLSpanTags `json:"mysql"` 1621 } 1622 1623 // newMySQLSpanData initializes a new MySQL client span data from tracer span 1624 func newMySQLSpanData(span *spanS) MySQLSpanData { 1625 return MySQLSpanData{ 1626 SpanData: NewSpanData(span, MySQLSpanType), 1627 Tags: newMySQLSpanTags(span), 1628 } 1629 } 1630 1631 // Kind returns the span kind for a MySQL client span 1632 func (d MySQLSpanData) Kind() SpanKind { 1633 return ExitSpanKind 1634 } 1635 1636 // MySQLSpanTags contains fields within the `data.mysql` section of an OT span document 1637 type MySQLSpanTags struct { 1638 Host string `json:"host"` 1639 Port string `json:"port"` 1640 DB string `json:"db"` 1641 User string `json:"user"` 1642 Stmt string `json:"stmt"` 1643 1644 Error string `json:"error,omitempty"` 1645 } 1646 1647 func newMySQLSpanTags(span *spanS) MySQLSpanTags { 1648 var tags MySQLSpanTags 1649 for k, v := range span.Tags { 1650 switch k { 1651 case "mysql.host": 1652 readStringTag(&tags.Host, v) 1653 case "mysql.port": 1654 readStringTag(&tags.Port, v) 1655 case "mysql.db": 1656 readStringTag(&tags.DB, v) 1657 case "mysql.stmt": 1658 readStringTag(&tags.Stmt, v) 1659 case "mysql.user": 1660 readStringTag(&tags.User, v) 1661 case "mysql.error": 1662 readStringTag(&tags.Error, v) 1663 } 1664 } 1665 return tags 1666 } 1667 1668 // RedisSpanTags contains fields within the `data.redis` section of an OT span document 1669 type RedisSpanTags struct { 1670 // Connection is the host and port where the Redis server is running 1671 Connection string `json:"connection"` 1672 // Command is the Redis command being executed 1673 Command string `json:"command"` 1674 // Subcommands is the list of commands queued when a transaction starts, eg: by using the MULTI command 1675 Subcommands []string `json:"subCommands,omitempty"` 1676 // Error is the optional error that can be thrown by Redis when executing a command 1677 Error string `json:"error,omitempty"` 1678 } 1679 1680 func newRedisSpanTags(span *spanS) RedisSpanTags { 1681 var tags RedisSpanTags 1682 for k, v := range span.Tags { 1683 switch k { 1684 case "redis.connection": 1685 readStringTag(&tags.Connection, v) 1686 case "redis.command": 1687 readStringTag(&tags.Command, v) 1688 case "redis.subCommands": 1689 readArrayStringTag(&tags.Subcommands, v) 1690 case "redis.error": 1691 readStringTag(&tags.Error, v) 1692 } 1693 } 1694 1695 return tags 1696 } 1697 1698 type AZFSpanTags struct { 1699 Name string `json:"name,omitempty"` 1700 FunctionName string `json:"functionname,omitempty"` 1701 MethodName string `json:"methodname,omitempty"` 1702 Trigger string `json:"triggername,omitempty"` 1703 Runtime string `json:"runtime,omitempty"` 1704 Error string `json:"error,omitempty"` 1705 } 1706 1707 func newAZFSpanTags(span *spanS) AZFSpanTags { 1708 var tags AZFSpanTags 1709 for k, v := range span.Tags { 1710 switch k { 1711 case "azf.name": 1712 readStringTag(&tags.Name, v) 1713 case "azf.functionname": 1714 readStringTag(&tags.FunctionName, v) 1715 case "azf.methodname": 1716 readStringTag(&tags.MethodName, v) 1717 case "azf.triggername": 1718 readStringTag(&tags.Trigger, v) 1719 case "azf.runtime": 1720 readStringTag(&tags.Runtime, v) 1721 } 1722 } 1723 1724 return tags 1725 } 1726 1727 type AZFSpanData struct { 1728 SpanData 1729 Tags AZFSpanTags `json:"azf"` 1730 } 1731 1732 func newAZFSpanData(span *spanS) AZFSpanData { 1733 return AZFSpanData{ 1734 SpanData: NewSpanData(span, AzureFunctionType), 1735 Tags: newAZFSpanTags(span), 1736 } 1737 } 1738 1739 // Kind returns instana.EntrySpanKind for server spans and instana.ExitSpanKind otherwise 1740 func (d AZFSpanData) Kind() SpanKind { 1741 return EntrySpanKind 1742 } 1743 1744 // GraphQLSpanData represents the `data` section of a GraphQL span sent within an OT span document 1745 type GraphQLSpanData struct { 1746 SpanData 1747 Tags GraphQLSpanTags `json:"graphql"` 1748 1749 clientSpan bool 1750 } 1751 1752 // newGraphQLSpanData initializes a new GraphQL span data from tracer span 1753 func newGraphQLSpanData(span *spanS) GraphQLSpanData { 1754 data := GraphQLSpanData{ 1755 SpanData: NewSpanData(span, RegisteredSpanType(span.Operation)), 1756 Tags: newGraphQLSpanTags(span), 1757 } 1758 1759 kindTag := span.Tags[string(ext.SpanKind)] 1760 data.clientSpan = kindTag == ext.SpanKindRPCClientEnum || kindTag == string(ext.SpanKindRPCClientEnum) 1761 1762 return data 1763 } 1764 1765 // Kind returns instana.EntrySpanKind for server spans and instana.ExitSpanKind otherwise 1766 func (d GraphQLSpanData) Kind() SpanKind { 1767 if d.clientSpan { 1768 return ExitSpanKind 1769 } 1770 1771 return EntrySpanKind 1772 } 1773 1774 // GraphQLSpanTags contains fields within the `data.graphql` section of an OT span document 1775 type GraphQLSpanTags struct { 1776 OperationName string `json:"operationName,omitempty"` 1777 OperationType string `json:"operationType,omitempty"` 1778 Fields map[string][]string `json:"fields,omitempty"` 1779 Args map[string][]string `json:"args,omitempty"` 1780 Error string `json:"error,omitempty"` 1781 } 1782 1783 // newGraphQLSpanTags extracts GraphQL-specific span tags from a tracer span 1784 func newGraphQLSpanTags(span *spanS) GraphQLSpanTags { 1785 var tags GraphQLSpanTags 1786 for k, v := range span.Tags { 1787 switch k { 1788 case "graphql.operationName": 1789 readStringTag(&tags.OperationName, v) 1790 case "graphql.operationType": 1791 readStringTag(&tags.OperationType, v) 1792 case "graphql.fields": 1793 readMapOfStringSlicesTag(&tags.Fields, v) 1794 case "graphql.args": 1795 readMapOfStringSlicesTag(&tags.Args, v) 1796 case "graphql.error": 1797 readStringTag(&tags.Error, v) 1798 } 1799 } 1800 1801 return tags 1802 }