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

Add OTLP/HTTP+JSON Protocol exporter #810

Merged
merged 7 commits into from
Jun 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ Increment the:

## [Unreleased]

* [EXPORTER] Add OTLP/HTTP+JSON Protocol exporter ([#810](https://github.com/open-telemetry/opentelemetry-cpp/pull/810))
* [EXPORTER] Rename `OtlpExporter` to `OtlpGrpcExporter`, rename `otlp_exporter.h` to `otlp_grpc_exporter.h` ([#810](https://github.com/open-telemetry/opentelemetry-cpp/pull/810))

## [1.0.0-rc1] 2021-06-04

* [BUILD] Enable Jaeger exporter build in Windows ([#815](https://github.com/open-telemetry/opentelemetry-cpp/pull/815))
Expand Down
13 changes: 11 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ if(WITH_OTLP)
find_package(Protobuf REQUIRED)
endif()
if(NOT gRPC_FOUND)
find_package(gRPC REQUIRED)
find_package(gRPC)
endif()
if(WIN32)
# Always use x64 protoc.exe
Expand All @@ -221,6 +221,15 @@ if(WITH_OTLP)
message("PROTOBUF_PROTOC_EXECUTABLE=${PROTOBUF_PROTOC_EXECUTABLE}")

include(cmake/opentelemetry-proto.cmake)
include(CMakeDependentOption)
find_package(CURL)
find_package(nlohmann_json)
cmake_dependent_option(
WITH_OTLP_GRPC "Whether to include the OTLP gRPC exporter in the SDK" ON
"gRPC_FOUND" OFF)
cmake_dependent_option(
WITH_OTLP_HTTP "Whether to include the OTLP http exporter in the SDK" ON
"CURL_FOUND;nlohmann_json_FOUND" OFF)
lalitb marked this conversation as resolved.
Show resolved Hide resolved
endif()

list(APPEND CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}")
Expand Down Expand Up @@ -268,11 +277,11 @@ if(NOT WITH_API_ONLY)
include_directories(ext/include)

add_subdirectory(sdk)
add_subdirectory(ext)
add_subdirectory(exporters)
if(WITH_EXAMPLES)
add_subdirectory(examples)
endif()
add_subdirectory(ext)
endif()

# Add nlohmann/json submodule to include directories
Expand Down
4 changes: 2 additions & 2 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps")

grpc_extra_deps()

load("@upb//bazel:repository_defs.bzl", "bazel_version_repository")
load("@upb//bazel:workspace_deps.bzl", "upb_deps")

bazel_version_repository(name = "upb_bazel_version")
upb_deps()

# Load prometheus C++ dependencies.
load("@com_github_jupp0r_prometheus_cpp//bazel:repositories.bzl", "prometheus_cpp_repositories")
Expand Down
16 changes: 13 additions & 3 deletions bazel/repository.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,23 @@ def opentelemetry_cpp_deps():
)

# Load gRPC dependency
maybe(
http_archive,
name = "com_github_grpc_grpc_legacy",
sha256 = "2060769f2d4b0d3535ba594b2ab614d7f68a492f786ab94b4318788d45e3278a",
strip_prefix = "grpc-1.33.2",
urls = [
"https://github.com/grpc/grpc/archive/v1.33.2.tar.gz",
],
)

maybe(
http_archive,
name = "com_github_grpc_grpc",
sha256 = "d6277f77e0bb922d3f6f56c0f93292bb4cfabfc3c92b31ee5ccea0e100303612",
strip_prefix = "grpc-1.28.0",
sha256 = "2060769f2d4b0d3535ba594b2ab614d7f68a492f786ab94b4318788d45e3278a",
strip_prefix = "grpc-1.33.2",
urls = [
"https://github.com/grpc/grpc/archive/v1.28.0.tar.gz",
"https://github.com/grpc/grpc/archive/v1.33.2.tar.gz",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why upgrade this to 1.33? I think 1.34 is used in our CI.

git clone --depth=1 -b v1.34.0 https://github.com/grpc/grpc

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think 1.33 is the only version support both bazel 4+ and legacy gcc 4.8.
setup_grpc.sh is only used when using cmake, not bazel.
I found grpc 1.34 upgrade abseil-cpp to 2020923.2 and it uses something gcc 4.8 do not support.
I submit another PR #666 and try to upgrade gRPC but failed on legacy toolchain. Maybe some one can help to switch the
grpc to old version or just disable OTLP Exporters when using bazel?I'm not familar with bazel.

Copy link
Contributor

@maxgolov maxgolov Jun 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume for Windows, while eventually getting to prebuilt DLL / SDK, we can most likely use whatever recent version of gRPC from vcpkg? Mine right now is 1.37.0

C:\work\opentelemetry-cpp\tools\vcpkg>vcpkg list grpc
grpc:x64-windows                                   1.37.0#2         An RPC library and framework

I hope that one works with Visual Studio 2015 Update 2 and above.

Copy link
Member Author

@owent owent Jun 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested several toolchains with different versions of gRPC, and here is the result:

Right now, we have legacy gcc 4.8 in CI matrix, so I just update gRPC in bazel to 1.33 for compatiability. Maybe it can be upgraded to newer version in the future and in another PR.

],
)

Expand Down
2 changes: 1 addition & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
if(WITH_OTLP)
if(WITH_OTLP_GRPC OR WITH_OTLP_HTTP)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need that level of granularity, can one flag build both?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is rare for one build to have both, so 2 flags make sense. Or we could introduce a third flag WITH_OTLP to include both but then it seems over complicated.

Copy link
Member Author

@owent owent Jun 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometimes we want only either WITH_OTLP_GRPC or WITH_OTLP_HTTP .
Set WITH_OTLP=ON will try to turn WITH_OTLP_GRPC on when grpc is found and turn WITH_OTLP_HTTP on when both libcurl and nlohmann_json are found in this PR.
The WITH_OTLP option is just for backward compatibility, and the actually options take effect is WITH_OTLP_GRPC and WITH_OTLP_HTTP now.

add_subdirectory(otlp)
add_subdirectory(grpc)
endif()
Expand Down
19 changes: 16 additions & 3 deletions examples/otlp/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,27 @@ cc_library(
)

cc_binary(
name = "example_otlp",
name = "example_otlp_grpc",
srcs = [
"main.cc",
"grpc_main.cc",
],
deps = [
":foo_library",
"//api",
"//exporters/otlp:otlp_exporter",
"//exporters/otlp:otlp_grpc_exporter",
"//sdk/src/trace",
],
)

cc_binary(
name = "example_otlp_http",
srcs = [
"http_main.cc",
],
deps = [
":foo_library",
"//api",
"//exporters/otlp:otlp_http_exporter",
"//sdk/src/trace",
],
)
27 changes: 18 additions & 9 deletions examples/otlp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,21 @@ add_library(otlp_foo_library foo_library/foo_library.cc)
target_link_libraries(otlp_foo_library ${CMAKE_THREAD_LIBS_INIT}
${CORE_RUNTIME_LIBS} opentelemetry_api)

add_executable(example_otlp main.cc)
target_link_libraries(
example_otlp
${CMAKE_THREAD_LIBS_INIT}
otlp_foo_library
opentelemetry_trace
${CORE_RUNTIME_LIBS}
opentelemetry_exporter_otprotocol
gRPC::grpc++)
if(WITH_OTLP_GRPC)
add_executable(example_otlp_grpc grpc_main.cc)
target_link_libraries(
example_otlp_grpc
${CMAKE_THREAD_LIBS_INIT}
otlp_foo_library
opentelemetry_trace
${CORE_RUNTIME_LIBS}
opentelemetry_exporter_otlp_grpc
gRPC::grpc++)
endif()

if(WITH_OTLP_HTTP)
add_executable(example_otlp_http http_main.cc)
target_link_libraries(
example_otlp_http ${CMAKE_THREAD_LIBS_INIT} otlp_foo_library
opentelemetry_trace ${CORE_RUNTIME_LIBS} opentelemetry_exporter_otlp_http)
endif()
14 changes: 8 additions & 6 deletions examples/otlp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ This is an example of how to use the [OpenTelemetry
Protocol](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/README.md)
(OTLP) exporter.

The application in `main.cc` initializes an `OtlpExporter` instance and uses it
to register a tracer provider from the [OpenTelemetry
The application in `grpc_main.cc` initializes an `OtlpGrpcExporter` instance and
the application in `http_main.cc` initializes an `OtlpHttpExporter` instance
and they register a tracer provider from the [OpenTelemetry
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
this certificate via OtlpGrpcExporterOptions. 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.

Expand All @@ -31,18 +32,19 @@ 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
docker run --rm -it -p 4317:4317 -p 55681:55681 -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
docker run --rm -it -p 4317:4317 -p 55681:55681 -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
default. This can be changed with first argument from command-line, for example:
`./example_otlp gateway.docker.internal:4317`.
`./example_otlp_grpc gateway.docker.internal:4317` and
`./example_otlp_http gateway.docker.internal:55681/v1/traces`.

Once you have the Collector running, see
[CONTRIBUTING.md](../../CONTRIBUTING.md) for instructions on building and
Expand Down
6 changes: 3 additions & 3 deletions examples/otlp/main.cc → examples/otlp/grpc_main.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#include "opentelemetry/exporters/otlp/otlp_exporter.h"
#include "opentelemetry/exporters/otlp/otlp_grpc_exporter.h"
#include "opentelemetry/sdk/trace/simple_processor.h"
#include "opentelemetry/sdk/trace/tracer_provider.h"
#include "opentelemetry/trace/provider.h"
Expand All @@ -15,11 +15,11 @@ namespace otlp = opentelemetry::exporter::otlp;

namespace
{
opentelemetry::exporter::otlp::OtlpExporterOptions opts;
opentelemetry::exporter::otlp::OtlpGrpcExporterOptions opts;
void InitTracer()
{
// Create OTLP exporter instance
auto exporter = std::unique_ptr<sdktrace::SpanExporter>(new otlp::OtlpExporter(opts));
auto exporter = std::unique_ptr<sdktrace::SpanExporter>(new otlp::OtlpGrpcExporter(opts));
auto processor = std::unique_ptr<sdktrace::SpanProcessor>(
new sdktrace::SimpleSpanProcessor(std::move(exporter)));
auto provider =
Expand Down
58 changes: 58 additions & 0 deletions examples/otlp/http_main.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#include "opentelemetry/exporters/otlp/otlp_http_exporter.h"
#include "opentelemetry/sdk/trace/simple_processor.h"
#include "opentelemetry/sdk/trace/tracer_provider.h"
#include "opentelemetry/trace/provider.h"

#include <string>

#include "foo_library/foo_library.h"

namespace trace = opentelemetry::trace;
namespace nostd = opentelemetry::nostd;
namespace sdktrace = opentelemetry::sdk::trace;
namespace otlp = opentelemetry::exporter::otlp;

namespace
{
opentelemetry::exporter::otlp::OtlpHttpExporterOptions opts;
void InitTracer()
{
// Create OTLP exporter instance
auto exporter = std::unique_ptr<sdktrace::SpanExporter>(new otlp::OtlpHttpExporter(opts));
auto processor = std::unique_ptr<sdktrace::SpanProcessor>(
new sdktrace::SimpleSpanProcessor(std::move(exporter)));
auto provider =
nostd::shared_ptr<trace::TracerProvider>(new sdktrace::TracerProvider(std::move(processor)));
// Set the global trace provider
trace::Provider::SetTracerProvider(provider);
}
} // namespace

int main(int argc, char *argv[])
{
if (argc > 1)
{
opts.url = argv[1];
if (argc > 2)
{
std::string debug = argv[2];
opts.console_debug = debug != "" && debug != "0" && debug != "no";
}

if (argc > 3)
{
std::string binary_mode = argv[3];
if (binary_mode.size() >= 3 && binary_mode.substr(0, 3) == "bin")
{
opts.content_type = opentelemetry::exporter::otlp::HttpRequestContentType::kBinary;
}
}
}
// Removing this line will leave the default noop TracerProvider in place.
InitTracer();

foo_library();
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ receivers:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: "0.0.0.0:55681"
cors_allowed_origins:
- '*'
service:
pipelines:
traces:
Expand Down
58 changes: 49 additions & 9 deletions exporters/otlp/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ cc_library(
)

cc_library(
name = "otlp_exporter",
name = "otlp_grpc_exporter",
srcs = [
"src/otlp_exporter.cc",
"src/otlp_grpc_exporter.cc",
],
hdrs = [
"include/opentelemetry/exporters/otlp/otlp_exporter.h",
"include/opentelemetry/exporters/otlp/otlp_grpc_exporter.h",
"include/opentelemetry/exporters/otlp/protobuf_include_prefix.h",
"include/opentelemetry/exporters/otlp/protobuf_include_suffix.h",
],
Expand All @@ -55,6 +55,36 @@ cc_library(
],
)

cc_library(
name = "otlp_http_exporter",
srcs = [
"src/otlp_http_exporter.cc",
],
hdrs = [
"include/opentelemetry/exporters/otlp/otlp_http_exporter.h",
"include/opentelemetry/exporters/otlp/protobuf_include_prefix.h",
"include/opentelemetry/exporters/otlp/protobuf_include_suffix.h",
],
copts = [
"-DCURL_STATICLIB",
],
linkopts = select({
"//bazel:windows": [
"-DEFAULTLIB:advapi32.lib",
"-DEFAULTLIB:crypt32.lib",
],
"//conditions:default": [],
}),
strip_include_prefix = "include",
deps = [
":otlp_recordable",
"//ext/src/http/client/curl:http_client_curl",
"//sdk/src/trace",
"@com_github_opentelemetry_proto//:trace_service_proto_cc",
"@github_nlohmann_json//:json",
],
)

cc_test(
name = "otlp_recordable_test",
srcs = ["test/otlp_recordable_test.cc"],
Expand All @@ -65,19 +95,29 @@ cc_test(
)

cc_test(
name = "otlp_exporter_test",
srcs = ["test/otlp_exporter_test.cc"],
name = "otlp_grpc_exporter_test",
srcs = ["test/otlp_grpc_exporter_test.cc"],
deps = [
":otlp_grpc_exporter",
"//api",
"@com_google_googletest//:gtest_main",
],
)

cc_test(
name = "otlp_http_exporter_test",
srcs = ["test/otlp_http_exporter_test.cc"],
deps = [
":otlp_exporter",
":otlp_http_exporter",
"//api",
"@com_google_googletest//:gtest_main",
],
)

otel_cc_benchmark(
name = "otlp_exporter_benchmark",
srcs = ["test/otlp_exporter_benchmark.cc"],
name = "otlp_grpc_exporter_benchmark",
srcs = ["test/otlp_grpc_exporter_benchmark.cc"],
deps = [
":otlp_exporter",
":otlp_grpc_exporter",
],
)
Loading