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 Jaeger exporter #534

Merged
merged 41 commits into from
May 11, 2021
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
7cd462f
Initial commit of Jaeger exporter
ThomsonTan Jan 21, 2021
62746e5
Export spans to thrift
ThomsonTan Jan 26, 2021
9fd15a4
Add thrift generated files to repo
ThomsonTan Jan 26, 2021
2081396
Fix CMake script
ThomsonTan Jan 27, 2021
fcb82b7
Add WITH_JAEGER as CMake option
ThomsonTan Jan 28, 2021
eacbe0b
Merge branch 'main' into JaegerExporter
ThomsonTan Jan 28, 2021
5c09997
Merge branch 'main' into JaegerExporter
ThomsonTan Feb 11, 2021
02b3bbd
Merge branch 'main' into JaegerExporter
ThomsonTan Feb 17, 2021
a3a08ad
Merge branch 'main' into JaegerExporter
ThomsonTan Feb 22, 2021
5d8140b
Fix build
ThomsonTan Feb 24, 2021
ca66fed
Format changed files
ThomsonTan Feb 24, 2021
8a7fa9f
Merge branch 'main' into JaegerExporter
ThomsonTan Apr 1, 2021
f7f6d79
Merge branch 'main' into JaegerExporter
ThomsonTan Apr 2, 2021
64672ba
Tmp change
ThomsonTan Apr 5, 2021
dbed4aa
Merge branch 'main' into JaegerExporter
ThomsonTan Apr 5, 2021
4bde77a
Add TUDPTransport
ThomsonTan Apr 8, 2021
0a64e80
Add max UDP packet size check
ThomsonTan Apr 8, 2021
6cbffcf
Move exception handling close to emitBatch in AgentClient
ThomsonTan Apr 8, 2021
d09aa9b
Merge remote-tracking branch 'origin' into JaegerExporter
ThomsonTan Apr 8, 2021
fd3d26f
Add example_jaeger
ThomsonTan Apr 8, 2021
04581ee
Initialize winsock
ThomsonTan Apr 8, 2021
0d74fac
Remove Jaeger IDL from submodule list which is no longer necessary
ThomsonTan Apr 8, 2021
f337341
Add CleanSocket call
ThomsonTan Apr 8, 2021
e58b00b
Add mutex to avoid race condition in Jaeger exporter
ThomsonTan Apr 9, 2021
843e2c6
Update readme.txt
ThomsonTan Apr 9, 2021
accce34
Fix format
ThomsonTan Apr 9, 2021
05a7f42
Disable build Jaeger exporter/example in bazel build
ThomsonTan Apr 9, 2021
adb49c4
Remove boost dependence
ThomsonTan Apr 13, 2021
b443819
Merge branch 'main' into JaegerExporter
ThomsonTan Apr 20, 2021
8e6c3a1
Address feedback and rebase to latest main
ThomsonTan Apr 20, 2021
9a980ad
Merge branch 'main' into JaegerExporter
ThomsonTan Apr 23, 2021
aeadf81
Add README.md for Jaeger exporter
ThomsonTan Apr 23, 2021
e1b93df
Merge branch 'main' into JaegerExporter
ThomsonTan May 5, 2021
3d9597d
Add resource and instrumentation library to jaeger exporter
ThomsonTan May 5, 2021
d7c3498
Populate resource to Jaeger service name
ThomsonTan May 5, 2021
2027eb9
Format markdown README
ThomsonTan May 5, 2021
ec6ee47
Clang-format
ThomsonTan May 5, 2021
6d09836
Flush batch and remove lock on Jaeger exporter sender.
ThomsonTan May 5, 2021
c962561
Fix Linux build
ThomsonTan May 6, 2021
3f2ef72
Merge branch 'main' into JaegerExporter
lalitb May 10, 2021
e38dec6
Merge branch 'main' into JaegerExporter
lalitb May 11, 2021
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
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ option(WITH_PROMETHEUS "Whether to include the Prometheus Client in the SDK"
option(WITH_ELASTICSEARCH
"Whether to include the Elasticsearch Client in the SDK" OFF)

option(WITH_JAEGER "Whether to include the Jaeger exporter" OFF)

option(BUILD_TESTING "Whether to enable tests" ON)
if(WIN32)
option(WITH_ETW "Whether to include the ETW Exporter in the SDK" ON)
Expand Down
3 changes: 3 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
if(WITH_OTLP)
add_subdirectory(otlp)
endif()
if(WITH_JAEGER)
add_subdirectory(jaeger)
endif()
add_subdirectory(plugin)
add_subdirectory(simple)
add_subdirectory(batch)
Expand Down
26 changes: 26 additions & 0 deletions examples/jaeger/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
cc_library(
name = "foo_library",
srcs = [
"foo_library/foo_library.cc",
],
hdrs = [
"foo_library/foo_library.h",
],
deps = [
"//api",
],
)

# TODO: enable bazel build
# cc_binary(
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: anything I can do to help get this working?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks @jsuereth I will send out another PR with bazel build script then will need your help to make sure it is installing thrift dependence in the right way.

# name = "example_jaeger",
# srcs = [
# "main.cc",
# ],
# deps = [
# ":foo_library",
# "//api",
# "//exporters/jaeger:jaeger_exporter",
# "//sdk/src/trace",
# ],
# )
10 changes: 10 additions & 0 deletions examples/jaeger/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
include_directories(${CMAKE_SOURCE_DIR}/exporters/jaeger/include)

add_library(jaeger_foo_library foo_library/foo_library.cc)
target_link_libraries(jaeger_foo_library ${CMAKE_THREAD_LIBS_INIT}
${CORE_RUNTIME_LIBS} opentelemetry_api)

add_executable(example_jaeger main.cc)
target_link_libraries(
example_jaeger ${CMAKE_THREAD_LIBS_INIT} jaeger_foo_library
opentelemetry_trace ${CORE_RUNTIME_LIBS} jaeger_trace_exporter)
18 changes: 18 additions & 0 deletions examples/jaeger/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Jaeger Exporter Example

This is an example of how to use the Jaeger exporter.

The application in `main.cc` initializes an `JaegerExporter` instance and uses it
to 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).

Resulting spans are exported to the Jaeger agent using the Jaeger exporter.

Note that the Jaeger exporter connects to the agent at `localhost:6831` by
default.

Once you have the Collector running, see
[CONTRIBUTING.md](../../CONTRIBUTING.md) for instructions on building and
running the example.
33 changes: 33 additions & 0 deletions examples/jaeger/foo_library/foo_library.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "opentelemetry/trace/provider.h"

namespace trace = opentelemetry::trace;
namespace nostd = opentelemetry::nostd;

namespace
{
nostd::shared_ptr<trace::Tracer> get_tracer()
{
auto provider = trace::Provider::GetTracerProvider();
return provider->GetTracer("foo_library");
}

void f1()
{
auto scoped_span = trace::Scope(get_tracer()->StartSpan("f1"));
}

void f2()
{
auto scoped_span = trace::Scope(get_tracer()->StartSpan("f2"));

f1();
f1();
}
} // namespace

void foo_library()
{
auto scoped_span = trace::Scope(get_tracer()->StartSpan("library"));

f2();
}
3 changes: 3 additions & 0 deletions examples/jaeger/foo_library/foo_library.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

void foo_library();
38 changes: 38 additions & 0 deletions examples/jaeger/main.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "opentelemetry/exporters/jaeger/jaeger_exporter.h"
#include "opentelemetry/sdk/trace/simple_processor.h"
#include "opentelemetry/sdk/trace/tracer_provider.h"
#include "opentelemetry/trace/provider.h"

#include "foo_library/foo_library.h"

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

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

int main(int argc, char *argv[])
{
if (argc == 2)
{
opts.server_addr = argv[1];
}
// Removing this line will leave the default noop TracerProvider in place.
InitTracer();

foo_library();
}
4 changes: 4 additions & 0 deletions exporters/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ endif()
if(WITH_ETW)
add_subdirectory(etw)
endif()

if(WITH_JAEGER)
add_subdirectory(jaeger)
endif()
32 changes: 32 additions & 0 deletions exporters/jaeger/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
include_directories(include)
include_directories(thrift-gen)

find_package(Boost REQUIRED)
ThomsonTan marked this conversation as resolved.
Show resolved Hide resolved
find_package(thrift REQUIRED)

if(MSVC)
add_definitions(-DNOMINMAX)
endif()

set(JAEGER_THRIFT_GENCPP_SOURCES
thrift-gen/Agent.cpp thrift-gen/jaeger_types.cpp thrift-gen/Collector.cpp
thrift-gen/zipkincore_types.cpp)

set(JAEGER_EXPORTER_SOURCES
src/jaeger_exporter.cc src/thrift_sender.cc src/udp_transport.cc
src/recordable.cc src/TUDPTransport.cc)

add_library(jaeger_trace_exporter ${JAEGER_EXPORTER_SOURCES}
${JAEGER_THRIFT_GENCPP_SOURCES})
target_link_libraries(jaeger_trace_exporter PRIVATE thrift::thrift)

if(BUILD_TESTING)
add_executable(jaeger_recordable_test test/jaeger_recordable_test.cc)
target_link_libraries(jaeger_recordable_test ${GTEST_BOTH_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT} jaeger_trace_exporter)

gtest_add_tests(
TARGET jaeger_recordable_test
TEST_PREFIX exporter.
TEST_LIST jaeger_recordable_test)
endif() # BUILD_TESTING
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright 2021, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <opentelemetry/sdk/trace/exporter.h>

OPENTELEMETRY_BEGIN_NAMESPACE
namespace exporter
{
namespace jaeger
{
enum class TransportFormat
{
kThriftUdp,
kThriftUdpCompact,
kThriftHttp,
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps only the currently supported transports should be listed here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that works too. But as this list is expected to be stable, I just leave it there to make the header file stable (later extension should not need to update the header file, just update the .cc file). But let me know if removing the unimplemented formats is preferred.

kProtobufGrpc,
};

class ThriftSender;

/**
* Struct to hold Jaeger exporter options.
*/
struct JaegerExporterOptions
{
// The endpoint to export to.
std::string server_addr = "localhost";
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps future proofing, but ff Thrift over HTTP is supported, perhaps rename it to endpoint and parse host, port from it? With HTTP it will be necessary to specify the full endpoint, e.g. localhost:1234/api/traces.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I suggest we refactor the option in later PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

+1

uint16_t server_port = 6831;
TransportFormat transport_format = TransportFormat::kThriftUdpCompact;
};

namespace trace_sdk = opentelemetry::sdk::trace;

class JaegerExporter final : public trace_sdk::SpanExporter
{
public:
/**
* Create a JaegerExporter using all default options.
*/
JaegerExporter();

/**
* Create a JaegerExporter using the given options.
*/
explicit JaegerExporter(const JaegerExporterOptions &options);

/**
* Create a span recordable.
* @return a new initialized Recordable object.
*/
std::unique_ptr<trace_sdk::Recordable> MakeRecordable() noexcept override;

/**
* Export a batch of spans.
* @param spans a span of unique pointers to span recordables.
*/
trace_sdk::ExportResult Export(
const nostd::span<std::unique_ptr<trace_sdk::Recordable>> &spans) noexcept override;

/**
* Shutdown the exporter.
* @param timeout an option timeout, default to max.
*/
bool Shutdown(
std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override
{
return true;
}

private:
void InitializeEndpoint();

private:
// The configuration options associated with this exporter.
bool is_shutdown_ = false;
JaegerExporterOptions options_;
std::unique_ptr<ThriftSender> sender_;
};

} // namespace jaeger
} // namespace exporter
OPENTELEMETRY_END_NAMESPACE
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2020, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <jaeger_types.h>
#include <opentelemetry/sdk/trace/recordable.h>
#include <opentelemetry/version.h>

OPENTELEMETRY_BEGIN_NAMESPACE
namespace exporter
{
namespace jaeger
{

using namespace jaegertracing;

class Recordable final : public sdk::trace::Recordable
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Not something which needs immediate attention, but probably we should have recordable names after transport types - eg TUDPRecordable. This is an issue with Zipkin exporter too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree. I logged the same comment for ETW exporter. I think we could create a task for the cleanup for all the exporters? I'll try the renaming anyway.

Copy link
Contributor

Choose a reason for hiding this comment

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

+1

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Created issue #735 for this.

{
public:
Recordable();

thrift::Span *Span() noexcept { return span_.release(); }
std::vector<thrift::Tag> Tags() noexcept { return std::move(tags_); }

void SetIds(trace::TraceId trace_id,
trace::SpanId span_id,
trace::SpanId parent_span_id) noexcept override;

void SetAttribute(nostd::string_view key,
const opentelemetry::common::AttributeValue &value) noexcept override;

void AddEvent(nostd::string_view key,
core::SystemTimestamp timestamp,
const common::KeyValueIterable &attributes) noexcept override;

void AddLink(const opentelemetry::trace::SpanContext &span_context,
const common::KeyValueIterable &attributes) noexcept override;

void SetStatus(trace::StatusCode code, nostd::string_view description) noexcept override;

void SetName(nostd::string_view name) noexcept override;

void SetStartTime(opentelemetry::core::SystemTimestamp start_time) noexcept override;

void SetSpanKind(opentelemetry::trace::SpanKind span_kind) noexcept override;

void SetDuration(std::chrono::nanoseconds duration) noexcept override;

private:
void AddTag(const std::string &key, const std::string &value);
void AddTag(const std::string &key, bool value);
void AddTag(const std::string &key, int64_t value);
void AddTag(const std::string &key, double value);

void PopulateAttribute(nostd::string_view key,
const opentelemetry::common::AttributeValue &value);

private:
std::unique_ptr<thrift::Span> span_;
std::vector<thrift::Tag> tags_;
};

} // namespace jaeger
} // namespace exporter
OPENTELEMETRY_END_NAMESPACE
Loading