diff --git a/.markdownlintignore b/.markdownlintignore index c3dbab2a0e..f0cec48dba 100644 --- a/.markdownlintignore +++ b/.markdownlintignore @@ -1,2 +1,3 @@ third_party/** tools/** +examples/otlp/README.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 532c08eafe..a45feac7c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ Increment the: ## [Unreleased] +* [EXPORTER] Populate resource to OTLP proto data ([#758](https://github.com/open-telemetry/opentelemetry-cpp/pull/758)) + ## [0.6.0] 2021-05-11 * [EXPORTER] Add Jaeger exporter ([#534](https://github.com/open-telemetry/opentelemetry-cpp/pull/534)) diff --git a/examples/otlp/README.md b/examples/otlp/README.md index 1f246053f4..e4750ef875 100644 --- a/examples/otlp/README.md +++ b/examples/otlp/README.md @@ -10,36 +10,34 @@ SDK](https://github.com/open-telemetry/opentelemetry-cpp). The application then calls a `foo_library` which has been instrumented using the [OpenTelemetry API](https://github.com/open-telemetry/opentelemetry-cpp/tree/main/api). -To enable TLS authentication for OTLP grpc exporter, SslCredentials can be used by -specifying the path to client certificate pem file, or the string containing this certificate via OtlpExporterOptions. The path to such a -.pem file can be provided as a command-line argument alongwith the collector endpoint -to the main binary invocation above. +To enable TLS authentication for OTLP grpc exporter, SslCredentials can be used +by specifying the path to client certificate pem file, or the string containing +this certificate via OtlpExporterOptions. The path to such a .pem file can be +provided as a command-line argument alongwith the collector endpoint to the main +binary invocation above. Resulting spans are exported to the **OpenTelemetry Collector** using the OTLP exporter. The OpenTelemetry Collector can be configured to export to other backends (see list of [supported backends](https://github.com/open-telemetry/opentelemetry-collector/blob/main/exporter/README.md)). -For instructions on downloading and running the OpenTelemetry Collector, see -[Getting Started](https://opentelemetry.io/docs/collector/about/). - -Here is an example of a Collector `config.yaml` file that can be used to export -to [Zipkin](https://zipkin.io/) via the Collector using the OTLP exporter: - -```yml -receivers: - otlp: - protocols: - grpc: - endpoint: localhost:4317 -exporters: - zipkin: - endpoint: "http://localhost:9411/api/v2/spans" -service: - pipelines: - traces: - receivers: [otlp] - exporters: [zipkin] +Follow below command to run the **OpenTelemetry Collector** with OTLP receiver +in docker which dumps the received data into console. See [Getting +Started](https://opentelemetry.io/docs/collector/about/) for more information. + +Open a terminal window at the root directory of this repo and launch the +OpenTelemetry Collector with an OTLP receiver by running: + +- On Unix based systems use: + +```console +docker run --rm -it -p 4317:4317 -v $(pwd)/examples/otlp:/cfg otel/opentelemetry-collector:0.19.0 --config=/cfg/opentelemetry-collector-config/config.dev.yaml +``` + +- On Windows use: + +```console +docker run --rm -it -p 4317:4317 -v "%cd%/examples/otlp":/cfg otel/opentelemetry-collector:0.19.0 --config=/cfg/opentelemetry-collector-config/config.dev.yaml ``` Note that the OTLP exporter connects to the Collector at `localhost:4317` by diff --git a/examples/otlp/opentelemetry-collector-config/config.dev.yaml b/examples/otlp/opentelemetry-collector-config/config.dev.yaml new file mode 100644 index 0000000000..6807000f01 --- /dev/null +++ b/examples/otlp/opentelemetry-collector-config/config.dev.yaml @@ -0,0 +1,15 @@ +exporters: + logging: + loglevel: DEBUG +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 +service: + pipelines: + traces: + receivers: + - otlp + exporters: + - logging diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/recordable.h b/exporters/otlp/include/opentelemetry/exporters/otlp/recordable.h index 53fc5f4d55..6ebe0511aa 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/recordable.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/recordable.h @@ -53,7 +53,7 @@ class Recordable final : public sdk::trace::Recordable private: proto::trace::v1::Span span_; - const opentelemetry::sdk::resource::Resource *resource_; + const opentelemetry::sdk::resource::Resource *resource_ = nullptr; }; } // namespace otlp } // namespace exporter diff --git a/exporters/otlp/src/otlp_exporter.cc b/exporters/otlp/src/otlp_exporter.cc index 74e1a71bd4..7a1a56c26c 100644 --- a/exporters/otlp/src/otlp_exporter.cc +++ b/exporters/otlp/src/otlp_exporter.cc @@ -28,8 +28,13 @@ void PopulateRequest(const nostd::span> for (auto &recordable : spans) { auto rec = std::unique_ptr(static_cast(recordable.release())); - // TODO - Handle Resource *instrumentation_lib->add_spans() = std::move(rec->span()); + + if (!has_resource) + { + *resource_span->mutable_resource() = rec->ProtoResource(); + has_resource = true; + } } } diff --git a/exporters/otlp/src/recordable.cc b/exporters/otlp/src/recordable.cc index a973bad994..666a370574 100644 --- a/exporters/otlp/src/recordable.cc +++ b/exporters/otlp/src/recordable.cc @@ -226,6 +226,7 @@ proto::resource::v1::Resource Recordable::ProtoResource() const noexcept PopulateAttribute(proto.add_attributes(), kv.first, kv.second); } } + return proto; } diff --git a/exporters/otlp/test/recordable_test.cc b/exporters/otlp/test/recordable_test.cc index 5ea4e03031..b4ceef03e8 100644 --- a/exporters/otlp/test/recordable_test.cc +++ b/exporters/otlp/test/recordable_test.cc @@ -150,6 +150,28 @@ TEST(Recordable, AddLink) } } +TEST(Recordable, SetResource) +{ + Recordable rec; + const std::string service_name_key = "service.name"; + std::string service_name = "test-otlp"; + auto resource = + opentelemetry::sdk::resource::Resource::Create({{service_name_key, service_name}}); + rec.SetResource(resource); + + auto proto_resource = rec.ProtoResource(); + bool found_service_name = false; + for (size_t i = 0; i < proto_resource.attributes_size(); i++) + { + auto attr = proto_resource.attributes(static_cast(i)); + if (attr.key() == service_name_key && attr.value().string_value() == service_name) + { + found_service_name = true; + } + } + EXPECT_TRUE(found_service_name); +} + // Test non-int single types. Int single types are tested using templates (see IntAttributeTest) TEST(Recordable, SetSingleAtrribute) {