Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding semantic-convention attributes for trace #868

Merged
merged 12 commits into from
Jul 30, 2021
189 changes: 189 additions & 0 deletions api/include/opentelemetry/trace/semantic_conventions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "opentelemetry/common/string_util.h"
#include "opentelemetry/version.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace trace
{

#define OTEL_CPP_GET_ATTR(name) attr(OTEL_CPP_CONST_HASHCODE(name))

/**
* Stores the Constants for semantic kAttribute names outlined by the OpenTelemetry specifications.
* <see
* href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/README.md"/>.
*/
static const struct
{
uint32_t attribute_id;
const char *attribute_key;
} attribute_ids[] = {
// The set of constants matches the specification as of this commit.
// https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/trace/semantic_conventions
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/exceptions.md

// General network connection attributes
{OTEL_CPP_CONST_HASHCODE(AttrNetTransport), "net.transport"},
{OTEL_CPP_CONST_HASHCODE(AttrNetPeerIp), "net.peer.ip"},
{OTEL_CPP_CONST_HASHCODE(AttrNetPeerPort), "net.peer.port"},
{OTEL_CPP_CONST_HASHCODE(AttrNetPeerName), "net.peer.name"},
{OTEL_CPP_CONST_HASHCODE(AttrNetHostIp), "net.host.ip"},
{OTEL_CPP_CONST_HASHCODE(AttrNetHostPort), "net.host.port"},
{OTEL_CPP_CONST_HASHCODE(AttrNetHostName), "net.host.name"},

// General identity attributes
{OTEL_CPP_CONST_HASHCODE(AttrEnduserId), "enduser.id"},
{OTEL_CPP_CONST_HASHCODE(AttrEnduserRole), "enduser.role"},
{OTEL_CPP_CONST_HASHCODE(AttrEnduserScope), "enduser.scope"},

// General remote service attributes
{OTEL_CPP_CONST_HASHCODE(AttrPeerService), "peer.service"},

// General thread attributes
{OTEL_CPP_CONST_HASHCODE(AttrThreadId), "thread.id"},
{OTEL_CPP_CONST_HASHCODE(AttrThreadName), "thread.name"},

// Source Code Attributes
{OTEL_CPP_CONST_HASHCODE(AttrCodeFunction), "code.function"},
{OTEL_CPP_CONST_HASHCODE(AttrCodeNamespace), "code.namespace"},
{OTEL_CPP_CONST_HASHCODE(AttrCodeFilepath), "code.filepath"},
{OTEL_CPP_CONST_HASHCODE(AttrCodeLineno), "code.lineno"},

// Http Span Common Attributes
{OTEL_CPP_CONST_HASHCODE(AttrHttpMethod), "http.method"},
{OTEL_CPP_CONST_HASHCODE(AttrHttpUrl), "http.url"},
{OTEL_CPP_CONST_HASHCODE(AttrHttpTarget), "http.target"},
{OTEL_CPP_CONST_HASHCODE(AttrHttpHost), "http.host"},
{OTEL_CPP_CONST_HASHCODE(AttrHttpScheme), "http.scheme"},
{OTEL_CPP_CONST_HASHCODE(AttrHttpStatusCode), "http.status_code"},
{OTEL_CPP_CONST_HASHCODE(AttrHttpFlavor), "http.flavor"},
{OTEL_CPP_CONST_HASHCODE(AttrHttpUserAgent), "http.user_agent"},
{OTEL_CPP_CONST_HASHCODE(AttrHttpRequestContentLength), "http.request_content_length"},
{OTEL_CPP_CONST_HASHCODE(AttrHttpRequestContentLengthUncompressed),
"http.request_content_length_uncompressed"},
{OTEL_CPP_CONST_HASHCODE(AttrHttpResponseContentLength), "http.response_content_length"},
{OTEL_CPP_CONST_HASHCODE(AttrHttpResponseContentLengthUncompressed),
"http.response_content_length_uncompressed"},

// HTTP Span Client Attributes
// One of the following combinations:
// - http.url
// - http.scheme, http.host, http.target
// - http.scheme, net.peer.name, net.peer.port, http.target
// - http.scheme, net.peer.ip, net.peer.port, http.target

// HTTP Span Server Attributes
// One of the following combinations:
// -http.scheme, http.host, http.target
// -http.scheme, http.server_name, net.host.port, http.target
// -http.scheme, net.host.name, net.host.port, http.target
// -http.url
{OTEL_CPP_CONST_HASHCODE(AttrHttpServerName), "http.server_name"},
{OTEL_CPP_CONST_HASHCODE(AttrHttpRoute), "http.route"},
{OTEL_CPP_CONST_HASHCODE(AttrHttpClientIp), "http.client_ip"},

// DB: Connection-level attributes
{OTEL_CPP_CONST_HASHCODE(AttrDbSystem), "db.system"}, // other_sql, mssql, mysql...
{OTEL_CPP_CONST_HASHCODE(AttrDbConnectionString), "db.connection_string"},
{OTEL_CPP_CONST_HASHCODE(AttrDbUser), "db.user"},
// DB: Connection-level attributes for specific technologies
{OTEL_CPP_CONST_HASHCODE(AttrDbMssqlInstanceName), "db.mssql.instance_name"},
{OTEL_CPP_CONST_HASHCODE(AttrDbJdbcDriverClassname), "db.jdbc.driver_classname"},
// DB: Call-level attributes
{OTEL_CPP_CONST_HASHCODE(AttrDbName), "db.name"},
{OTEL_CPP_CONST_HASHCODE(AttrDbStatement), "db.statement"},
{OTEL_CPP_CONST_HASHCODE(AttrDbOperation), "db.operation"},
// DB: Call-level attributes for specific technologies
{OTEL_CPP_CONST_HASHCODE(AttrDbHbaseNamespace), "db.hbase.namespace"},
{OTEL_CPP_CONST_HASHCODE(AttrDbRedisDatabaseIndex), "db.redis.database_index"},
{OTEL_CPP_CONST_HASHCODE(AttrDbMongodbCollection), "db.mongodb.collection"},

// // DB: Call-level attributes for Cassandra for clarity
{OTEL_CPP_CONST_HASHCODE(AttrDbCassandraKeyspace), "db.cassandra.keyspace"},
{OTEL_CPP_CONST_HASHCODE(AttrDbCassandraPageSize), "db.cassandra.page_size"},
{OTEL_CPP_CONST_HASHCODE(AttrDbCassandraConsistencyLevel), "db.cassandra.consistency_level"},
{OTEL_CPP_CONST_HASHCODE(AttrDbCassandraTable), "db.cassandra.table"},
{OTEL_CPP_CONST_HASHCODE(AttrDbCassandraIdempotence), "db.cassandra.idempotence"},
{OTEL_CPP_CONST_HASHCODE(AttrDbCassandraSpeculativeExecutionCount),
"db.cassandra.speculative_execution_count"},
{OTEL_CPP_CONST_HASHCODE(AttrDbCassandraCoordinatorId), "db.cassandra.coordinator.id"},
{OTEL_CPP_CONST_HASHCODE(AttrDbCassandraCoordinatorDC), "db.cassandra.coordinator.dc"},

// Common RPC attributes
{OTEL_CPP_CONST_HASHCODE(AttrRpcSystem), "rpc.system"},
{OTEL_CPP_CONST_HASHCODE(AttrRpcService), "rpc.service"},
{OTEL_CPP_CONST_HASHCODE(AttrRpcMethod), "rpc.method"},
// gRPC attributes
{OTEL_CPP_CONST_HASHCODE(AttrRpcGrpcStatusCode), "rpc.grpc.status_code"},
// JSON-RPC attributes
{OTEL_CPP_CONST_HASHCODE(AttrRpcJsonrpcVersion), "rpc.jsonrpc.version"},
{OTEL_CPP_CONST_HASHCODE(AttrRpcJsonrpcRequestId), "rpc.jsonrpc.request_id"},
{OTEL_CPP_CONST_HASHCODE(AttrRpcJsonrpcErrorCode), "rpc.jsonrpc.error_code"},
{OTEL_CPP_CONST_HASHCODE(AttrRpcJsonrpcErrorMessage), "rpc.jsonrpc.error_message"},

// faas: General Attributes
{OTEL_CPP_CONST_HASHCODE(AttrFaasTrigger), "faas.trigger"},
{OTEL_CPP_CONST_HASHCODE(AttrFaasExecution), "faas.execution"},
// faas: incoming invocations
{OTEL_CPP_CONST_HASHCODE(AttrFaasColdStart), "faas.coldstart"},
// faas: outgoing invocations
{OTEL_CPP_CONST_HASHCODE(AttrFaasInvokedName), "faas.invoked_name"},
{OTEL_CPP_CONST_HASHCODE(AttrFaasInvokedProvider), "faas.invoked_provider"},
{OTEL_CPP_CONST_HASHCODE(AttrFaasInvokedRegion), "faas.invoked_region"},
// faas: datastore trigger
{OTEL_CPP_CONST_HASHCODE(AttrFaasDocumentCollection), "faas.document.collection"},
{OTEL_CPP_CONST_HASHCODE(AttrFaasDocumentOperation), "faas.document.operation"},
{OTEL_CPP_CONST_HASHCODE(AttrFaasDocumentTime), "faas.document.time"},
{OTEL_CPP_CONST_HASHCODE(AttrFaasDocumentName), "faas.document.name"},
// faas: timer trigger
{OTEL_CPP_CONST_HASHCODE(AttrFaasTime), "faas.time"},
{OTEL_CPP_CONST_HASHCODE(AttrFaasCron), "faas.cron"},

// messaging attributes
{OTEL_CPP_CONST_HASHCODE(AttrMessagingSystem), "messaging.system"},
{OTEL_CPP_CONST_HASHCODE(AttrMessagingDestination), "messaging.destination"},
{OTEL_CPP_CONST_HASHCODE(AttrMessagingDestinationKind), "messaging.destination_kind"},
{OTEL_CPP_CONST_HASHCODE(AttrMessagingTempDestination), "messaging.temp_destination"},
{OTEL_CPP_CONST_HASHCODE(AttrMessagingProtocol), "messaging.protocol"},
{OTEL_CPP_CONST_HASHCODE(AttrMessagingProtocolVersion), "messaging.protocol_version"},
{OTEL_CPP_CONST_HASHCODE(AttrMessagingUrl), "messaging.url"},
{OTEL_CPP_CONST_HASHCODE(AttrMessagingMessageId), "messaging.message_id"},
{OTEL_CPP_CONST_HASHCODE(AttrMessagingConversationId), "messaging.conversation_id"},
{OTEL_CPP_CONST_HASHCODE(AttrMessagingPayloadSize), "messaging.message_payload_size_bytes"},
{OTEL_CPP_CONST_HASHCODE(AttrMessagingPayloadCompressedSize),
"messaging.message_payload_compressed_size_bytes"},
{OTEL_CPP_CONST_HASHCODE(AttrMessagingOperation), "messaging.operation"},
// messaging attributes specific to messaging systems
{OTEL_CPP_CONST_HASHCODE(AttrMessagingRabbitMQRoutingKey), "messaging.rabbitmq.routing_key"},
{OTEL_CPP_CONST_HASHCODE(AttrMessagingKafkaMessageKey), "messaging.kafka.message_key"},
{OTEL_CPP_CONST_HASHCODE(AttrMessagingKafkaConsumerGroup), "messaging.kafka.consumer_group"},
{OTEL_CPP_CONST_HASHCODE(AttrMessagingKafkaClientId), "messaging.kafka.client_id"},
{OTEL_CPP_CONST_HASHCODE(AttrMessagingKafkaPartition), "messaging.kafka.partition"},
{OTEL_CPP_CONST_HASHCODE(AttrMessagingKafkaTombstone), "messaging.kafka.tombstone"},

// Exceptions attributes
{OTEL_CPP_CONST_HASHCODE(AttrExceptionType), "exception.type"},
{OTEL_CPP_CONST_HASHCODE(AttrExceptionMessage), "exception.message"},
{OTEL_CPP_CONST_HASHCODE(AttrExceptionStacktrace), "exception.stacktrace"},
{OTEL_CPP_CONST_HASHCODE(AttrExceptionEscapted), "exception.escaped"},
};
// function to generate hash code for semantic conventions attributes.

#define OTEL_CPP_TRACE_ATTRIBUTES_MAX (sizeof(attribute_ids) / sizeof(attribute_ids[0]))

inline const char *attr(uint32_t attr)
{
for (int i = 0; i < OTEL_CPP_TRACE_ATTRIBUTES_MAX; i++)
{
if (attribute_ids[i].attribute_id == attr)
return attribute_ids[i].attribute_key;
}
return "";
}

} // namespace trace
OPENTELEMETRY_END_NAMESPACE
16 changes: 9 additions & 7 deletions examples/grpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "messages.grpc.pb.h"
#endif

#include "opentelemetry/trace/semantic_conventions.h"
#include "tracer_common.h"
#include <iostream>
#include <memory>
Expand All @@ -26,6 +27,7 @@ using grpc_example::GreetResponse;
namespace
{

using namespace opentelemetry::trace;
class GreeterClient
{
public:
Expand All @@ -44,11 +46,11 @@ class GreeterClient

std::string span_name = "GreeterClient/Greet";
auto span = get_tracer("grpc")->StartSpan(span_name,
{{"rpc.system", "grpc"},
{"rpc.service", "grpc-example.GreetService"},
{"rpc.method", "Greet"},
{"net.peer.ip", ip},
{"net.peer.port", port}},
{{OTEL_CPP_GET_ATTR(AttrRpcSystem), "grpc"},
{OTEL_CPP_GET_ATTR(AttrRpcService), "grpc-example.GreetService"},
{OTEL_CPP_GET_ATTR(AttrRpcMethod), "Greet"},
{OTEL_CPP_GET_ATTR(AttrNetPeerIp), ip},
{OTEL_CPP_GET_ATTR(AttrNetPeerPort), port}},
options);

auto scope = get_tracer("grpc-client")->WithActiveSpan(span);
Expand All @@ -64,7 +66,7 @@ class GreeterClient
if (status.ok())
{
span->SetStatus(opentelemetry::trace::StatusCode::kOk);
span->SetAttribute("rpc.grpc.status_code", status.error_code());
span->SetAttribute(OTEL_CPP_GET_ATTR(AttrRpcGrpcStatusCode), status.error_code());
// Make sure to end your spans!
span->End();
return response.response();
Expand All @@ -73,7 +75,7 @@ class GreeterClient
{
std::cout << status.error_code() << ": " << status.error_message() << std::endl;
span->SetStatus(opentelemetry::trace::StatusCode::kError);
span->SetAttribute("rpc.grpc.status_code", status.error_code());
span->SetAttribute(OTEL_CPP_GET_ATTR(AttrRpcGrpcStatusCode), status.error_code());
// Make sure to end your spans!
span->End();
return "RPC failed";
Expand Down
10 changes: 6 additions & 4 deletions examples/grpc/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#endif
#include "tracer_common.h"
#include "opentelemetry/trace/span_context_kv_iterable_view.h"
#include "opentelemetry/trace/semantic_conventions.h"

#include <grpcpp/grpcpp.h>
#include <grpcpp/server.h>
Expand All @@ -30,6 +31,7 @@ using grpc_example::GreetResponse;

using Span = opentelemetry::trace::Span;
using SpanContext = opentelemetry::trace::SpanContext;
using namespace opentelemetry::trace;

namespace
{
Expand Down Expand Up @@ -59,10 +61,10 @@ class GreeterServer final : public Greeter::Service
std::string span_name = "GreeterService/Greet";
auto span = get_tracer("grpc")
->StartSpan(span_name,
{{"rpc.system", "grpc"},
{"rpc.service", "GreeterService"},
{"rpc.method", "Greet"},
{"rpc.grpc.status_code", 0}},
{{OTEL_CPP_GET_ATTR(AttrRpcSystem), "grpc"},
{OTEL_CPP_GET_ATTR(AttrRpcService), "GreeterService"},
{OTEL_CPP_GET_ATTR(AttrRpcMethod), "Greet"},
{OTEL_CPP_GET_ATTR(AttrRpcGrpcStatusCode), 0}},
options);
auto scope = get_tracer("grpc")->WithActiveSpan(span);

Expand Down
11 changes: 7 additions & 4 deletions examples/http/client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@

#include "opentelemetry/ext/http/client/http_client_factory.h"
#include "opentelemetry/ext/http/common/url_parser.h"
#include "opentelemetry/trace/semantic_conventions.h"
#include "tracer_common.h"

namespace
{

using namespace opentelemetry::trace;

void sendRequest(const std::string &url)
{
auto http_client = opentelemetry::ext::http::client::HttpClientFactory::CreateSync();
Expand All @@ -20,9 +23,9 @@ void sendRequest(const std::string &url)
std::string span_name = url_parser.path_;
auto span = get_tracer("http-client")
->StartSpan(span_name,
{{"http.url", url_parser.url_},
{"http.scheme", url_parser.scheme_},
{"http.method", "GET"}},
{{OTEL_CPP_GET_ATTR(AttrHttpUrl), url_parser.url_},
{OTEL_CPP_GET_ATTR(AttrHttpScheme), url_parser.scheme_},
{OTEL_CPP_GET_ATTR(AttrHttpMethod), "GET"}},
options);
auto scope = get_tracer("http-client")->WithActiveSpan(span);

Expand All @@ -38,7 +41,7 @@ void sendRequest(const std::string &url)
{
// set span attributes
auto status_code = result.GetResponse().GetStatusCode();
span->SetAttribute("http.status_code", status_code);
span->SetAttribute(OTEL_CPP_GET_ATTR(AttrHttpStatusCode), status_code);
result.GetResponse().ForEachHeader([&span](opentelemetry::nostd::string_view header_name,
opentelemetry::nostd::string_view header_value) {
span->SetAttribute("http.header." + std::string(header_name.data()), header_value);
Expand Down
25 changes: 14 additions & 11 deletions examples/http/server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@
// SPDX-License-Identifier: Apache-2.0

#include "server.h"
#include "opentelemetry/trace/semantic_conventions.h"
#include "tracer_common.h"

#include <iostream>
#include <thread>

namespace
{

using namespace opentelemetry::trace;
;
uint16_t server_port = 8800;
constexpr const char *server_name = "localhost";

Expand All @@ -31,17 +35,16 @@ class RequestHandler : public HTTP_SERVER_NS::HttpRequestCallback
options.parent = opentelemetry::trace::propagation::GetSpan(new_context)->GetContext();

// start span with parent context extracted from http header
auto span =
get_tracer("http-server")
->StartSpan(
span_name,
{{"http.server_name", server_name},
{"net.host.port", server_port},
{"http.method", request.method},
{"http.scheme", "http"},
{"http.request_content_length", static_cast<uint64_t>(request.content.length())},
{"http.client_ip", request.client}},
options);
auto span = get_tracer("http-server")
->StartSpan(span_name,
{{OTEL_CPP_GET_ATTR(AttrHttpServerName), server_name},
{OTEL_CPP_GET_ATTR(AttrNetHostPort), server_port},
{OTEL_CPP_GET_ATTR(AttrHttpMethod), request.method},
{OTEL_CPP_GET_ATTR(AttrHttpScheme), "http"},
{OTEL_CPP_GET_ATTR(AttrHttpRequestContentLength),
static_cast<uint64_t>(request.content.length())},
{OTEL_CPP_GET_ATTR(AttrHttpClientIp), request.client}},
options);

auto scope = get_tracer("http_server")->WithActiveSpan(span);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#pragma once

#include <stdint.h>
#include <iostream>
#include <type_traits>
#include <unordered_map>

Expand All @@ -20,7 +18,7 @@ static const std::unordered_map<uint32_t, const char *> attribute_ids = {
{OTEL_CPP_CONST_HASHCODE(AttrServiceName), "service.name"},
{OTEL_CPP_CONST_HASHCODE(AttrServiceNamespace), "service.namespace"},
{OTEL_CPP_CONST_HASHCODE(AttrServiceInstance), "service.instance.id"},
{OTEL_CPP_CONST_HASHCODE(AttrServiceVersion), "service.version "},
{OTEL_CPP_CONST_HASHCODE(AttrServiceVersion), "service.version"},

// telemetry attributes
{OTEL_CPP_CONST_HASHCODE(AttrTelemetrySdkName), "telemetry.sdk.name"},
Expand Down Expand Up @@ -123,7 +121,7 @@ static const std::unordered_map<uint32_t, const char *> attribute_ids = {
{OTEL_CPP_CONST_HASHCODE(AttrCronjobUid), "k8s.cronjob.id"},
{OTEL_CPP_CONST_HASHCODE(AttrCronjobName), "k8s.cronjob.name"}};

// macro and function to generate hash code for semantic conventions attributes.
// function to generate hash code for semantic conventions attributes.
inline const char *attr(uint32_t attr)
{
return (attribute_ids.find(attr) != attribute_ids.end()) ? attribute_ids.at(attr) : "";
Expand Down
Loading