This project is a library wrapper around the official opentelemetry-cpp library. Understanding OpenTelemetry specification is a prerequisite.
- opentelemetry-c
The OpenTelemetry opentelemetry-cpp project can be used to trace C++ microservices. However, if you want to trace C microservices, you should consider a high-level C binding, like this one. It's worth noting that this wrapper does not support all the features of the C++ official project.
This project is provided as-is, without any warranty or support. Use at your own risk.
You can use this project as a sub repo subdirectory in your project or install library and header files.
We recommend using it as a sub-repo because it avoids the struggle of reinstalling the library every time we change the wrapper.
Whatever option you chose, you need :
- A supported platform: Windows, macOS or Linux if you're not planning to use the LTTngExporter. Otherwise Linux.
- A compatible C++ compiler supporting at least C++11.
- Git for fetching the project source code from the repository.
- CMake for building the project.
- opentelemetry-cpp v1.8.1. The library needs to be installed with
WITH_OTLP
andWITH_OTLP_GRPC
options set. Refer to the project documentation for the installation. - LTTng v2.13 if you plan to use the LTTngExporter. Refer to the project documentation for the installation.
All these tools are installed by default in the lttng-otelcpp image and pushed to GitHub Container Registry (see lttng-otelcpp-deploy CI job). To access the image use :
docker pull ghcr.io/dorsal-lab/lttng-otelcpp:main
First, add this project as a sub-repo in a folder like third-party/
.
$ cd path/to/the/root/of/your/git/project
$ git submodule add https://github.com/dorsal-lab/opentelemetry-c.git third-party/opentelemetry-c/
Then, in your project CMakeLists.txt
:
-
Set project options
Some of the available CMake build variables we can use during CMake configuration:
-
LTTNG_EXPORTER_ENABLED
: Whether to use LTTng exporter or not. If set to off, OTLP GRPC default exporter will be used. All telemetry data generated byopentelemetry-cpp
library are described using protocol buffers. Those protocol buffers are serialized and exported in binary format to LTTng. LTTng logs all these binary data to CTF files. The otel-replayer project can be used to read the CTF files and export them to various observability backends (e.g. Jaeger, Prometheus).Type of
telemetry dataDescription LTTng tracepoint Status traces
(spans)A Span represents a unit of work or operation.
It tracks specific operations that a request makes,
painting a picture of what happened during the time in which that operation was executed.opentelemetry:resource_spans
See Ressources spans proto and OTLP ExportTraceServiceRequestImplemented logs A log is a timestamped message emitted by services or other components opentelemetry:resource_logs
See Ressources logs proto and OTLP ExportLogsServiceRequestWork in progress metrics Metrics are aggregations over a period of time of numeric data about your infrastructure or application opentelemetry:resource_metrics
See Ressources metrics proto and OTLP ExportMetricsServiceRequestInt64 UpDown counter and Int64 Observable UpDown implemented When not using
LTTNG_EXPORTER_ENABLED
variable, all telemetry data are exported to an OpenTelemetry collector using the OTLP protocol. Also, you can also configure the collector GRPC server using the following environment variables:OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE
,OTEL_EXPORTER_OTLP_METRICS_COMPRESSION
,OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
,OTEL_EXPORTER_OTLP_METRICS_HEADERS
,OTEL_EXPORTER_OTLP_METRICS_INSECURE
,OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE
,OTEL_EXPORTER_OTLP_METRICS_TIMEOUT
,OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE
,OTEL_EXPORTER_OTLP_TRACES_COMPRESSION
,OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
,OTEL_EXPORTER_OTLP_TRACES_HEADERS
,OTEL_EXPORTER_OTLP_TRACES_INSECURE
,OTEL_EXPORTER_OTLP_TRACES_TIMEOUT
, Description of these environment variables are available here. -
BATCH_SPAN_PROCESSOR_ENABLED
: Whether to use Batching Span Processor or Simple Span Processor. Read more about Span Processors here. -
BUILD_EXAMPLES
: Whether to build examples provided in opentelemetry-c project.
Here is how to setup these variables :
# CMakeLists.txt option(LTTNG_EXPORTER_ENABLED "Whether to use LTTng exporter or not. If set to off, OTLP GRPC default exporter will be used" ON) option(BATCH_SPAN_PROCESSOR_ENABLED "Whether to use Batching Span Processor or Simple Span Processor" ON) option(BUILD_EXAMPLES "Whether to build examples or not" OFF)
-
-
Add
opentelemetry-c
folder :# CMakeLists.txt add_subdirectory(third-party/opentelemetry-c)
The opentelemetry-c-performance is an example of a CMake project using the wrapper as a sub-repo. This project extract benchmark from various wrapper use cases.
-
Getting the opentelemetry-c source code:
# Change to the directory where you want to create the code repository $ git clone https://github.com/dorsal-lab/opentelemetry-c.git
-
Navigate to the repository cloned above, and create the CMake build configuration.
$ cd opentelemetry-c $ mkdir -p build && cd build $ cmake -DBATCH_SPAN_PROCESSOR_ENABLED=ON \ -DLTTNG_EXPORTER_ENABLED=ON \ -DBUILD_EXAMPLES=OFF \ -DBUILD_SHARED_LIBS=ON \ -DCMAKE_INSTALL_PREFIX=/usr/local/ \ ..
CMake build variables are the same ones described in the previous section. The
-DBUILD_SHARED_LIBS=ON
is used to build a shared library.-DCMAKE_INSTALL_PREFIX
set the directory in which the library will be installed. -
Install the header files for the API, and generated targets at the specified install location.
$ make -j <number of cores> $ make install
The
$ make install
command may require root access since we are installing the library in/usr/local
folder.
To use the library from a CMake project, you can locate it directly with find_package
and use the imported targets from generated package configurations.
# CMakeLists.txt
find_library(opentelemetry-c opentelemetry-c REQUIRED)
...
# In your targets
target_include_directories(<my_target> PRIVATE ${OPENTELEMETRY_C_INCLUDE_DIRS})
target_link_libraries(<my_target> PRIVATE ${OPENTELEMETRY_C_LIBRARIES})
The opentelemetry-c-demo is an example of a CMake project using the installed version of the wrapper as the tracer. It's a Simple ZeroMQ client, proxy and server application.
The following functions can be used for initializing and using tracers in applications. These tracers are used for creating spans that help in understanding the application flow.
/**
* @brief Initialize the tracer provider and context propagator
*
* Read more on :
* https://opentelemetry.io/docs/reference/specification/trace/api/#tracerprovider
* and
* https://opentelemetry.io/docs/reference/specification/context/api-propagators/#textmap-propagator
*
* @param service_name The name of the service we are tracing
* @param service_version The version of the service
* @param service_namespace The service namespace
* @param service_instance_id The host instance id
*/
void otelc_init_tracer_provider(const char *service_name, const char *service_version,
const char *service_namespace,
const char *service_instance_id);
/**
* @brief Get the tracer object
* The tracer object help in the future to create spans
*
* Read more on :
* https://opentelemetry.io/docs/reference/specification/trace/api/#tracer
*
* @return void*
*/
void *otelc_get_tracer();
/**
* @brief Deallocate all resources used by the tracer
*
* @param tracer The tracer we want to destroy
*/
void otelc_destroy_tracer(void *tracer);
Here is an example of usage of these functions :
#include <opentelemetry_c/opentelemetry_c.h>
int main() {
otelc_init_tracer_provider(
"service_name",
"1.0.0",
"service_namespace",
"host_instance_id");
void *tracer = otelc_get_tracer();
// Use the tracer to create spans
// ...
otelc_destroy_tracer(tracer);
return 0;
}
The following functions are available to create, modify, and destroy an attribute map:
void *otelc_create_attr_map();
/**
* @brief Create a map of attribute (std::map<std::string,
* opentelemetry::common::AttributeValue>).
*
* See https://opentelemetry.io/docs/reference/specification/common/#attribute
*/
void otelc_set_bool_attr(void *attr_map, const char *key, int boolean_value);
/**
* See https://opentelemetry.io/docs/reference/specification/common/#attribute
*/
void otelc_set_int32_t_attr(void *attr_map, const char *key, int32_t value);
/**
* See https://opentelemetry.io/docs/reference/specification/common/#attribute
*/
void otelc_set_int64_t_attr(void *attr_map, const char *key, int64_t value);
/**
* See https://opentelemetry.io/docs/reference/specification/common/#attribute
*/
void otelc_set_uint64_t_attr(void *attr_map, const char *key, uint64_t value);
/**
* See https://opentelemetry.io/docs/reference/specification/common/#attribute
*/
void otelc_set_double_attr(void *attr_map, const char *key, double value);
/**
* See https://opentelemetry.io/docs/reference/specification/common/#attribute
*/
void otelc_set_str_attr(void *attr_map, const char *key, const char *value);
/**
* @brief Deallocate map memory
*/
void otelc_destroy_attr_map(void *attr_map);
Here is an example of usage of these functions :
#include <opentelemetry_c/opentelemetry_c.h>
int main() {
map = otelc_create_attr_map();
otelc_set_str_attr(map, "message", "Work started");
otelc_add_span_event(span, "work_start", map);
otelc_destroy_attr_map(map);
return 0;
}
The following functions and types are available for creating, managing and ending spans in the OpenTelemetry tracing system.
/**
* @brief Define the SpanKind
*
* See https://opentelemetry.io/docs/reference/specification/trace/api/#spankind
*/
typedef enum { // NOLINTBEGIN
OTELC_SPAN_KIND_INTERNAL,
OTELC_SPAN_KIND_SERVER,
OTELC_SPAN_KIND_CLIENT,
OTELC_SPAN_KIND_PRODUCER,
OTELC_SPAN_KIND_CONSUMER
} otelc_span_kind_t; // NOLINTEND
/**
* @brief Create a new span
*
* Read more on :
* https://opentelemetry.io/docs/reference/specification/trace/api/#span-creation
*
* @param tracer The tracer
* @param span_name The name of the span we are creating
* @param span_kind The SpanKind
* @param remote_context The remote context serialized. This argument is
* optional when creating nested spans in the same thread
* @return void* The span
*/
void *otelc_start_span(void *tracer, const char *span_name, otelc_span_kind_t span_kind,
const char *remote_context);
/**
* @brief Extract the context from the current active span
*
* Use this method to get the context to pass around requests
*
* The function allocates memory for the return value. This memory must be freed
* later.
*
* For now the context is a string. In future, it could be in a
* binary format (See
* https://github.com/open-telemetry/opentelemetry-specification/issues/437)
*
* @param span The span
* @return char* The context serialized
*/
char *otelc_extract_context_from_current_span(void *span);
/**
* @brief Define a span status
*
* See
* https://opentelemetry.io/docs/reference/specification/trace/api/#set-status
*/
typedef enum { // NOLINTBEGIN
OTELC_SPAN_STATUS_CODE_UNSET,
OTELC_SPAN_STATUS_CODE_OK,
OTELC_SPAN_STATUS_CODE_ERROR
} otelc_span_status_code_t; // NOLINTEND
/**
* @brief Set the status of an span
*
* Read more on :
* https://opentelemetry.io/docs/reference/specification/trace/api/#span-operations
*
* @param span The span
* @param code The status code
* @param description A description. The description matters only for the error
* status code
*/
void otelc_set_span_status(void *span, otelc_span_status_code_t code,
const char *description);
/**
* @brief Set the span attributes
*
* Read more on :
* https://opentelemetry.io/docs/reference/specification/trace/api/#span-operations
*
* @param span The span
* @param attr_map The map with all attributes
*/
void otelc_set_span_attrs(void *span, void *attr_map);
/**
* @brief Add a span event
*
* Read more on :
* https://opentelemetry.io/docs/reference/specification/trace/api/#span-operations
*
* @param span The span
* @param event_name The event name
* @param attr_map The map with all event attributes
*/
void otelc_add_span_event(void *span, const char *event_name, void *attr_map);
/**
* @brief Ends a deallocated memory relating to a span
*
* @param span The span we want to end
*/
void otelc_end_span(void *span);
Example 1 : Create a span
#include <opentelemetry_c/opentelemetry_c.h>
int main(void) {
otelc_init_tracer_provider("example", "0.0.1", "",
"machine-0.0.1");
void *tracer = otelc_get_tracer();
void *span = otelc_start_span(tracer, "get-hello", OTELC_SPAN_KIND_CLIENT, "");
// Do something
// ...
otelc_end_span(span);
otelc_destroy_tracer(tracer);
return 0;
}
Example 2 : Create a span from and extract the context. This context can be sent to another host for cross host tracing.
#include <opentelemetry_c/opentelemetry_c.h>
#include <stdlib.h>
int main(void) {
otelc_init_tracer_provider("example", "0.0.1", "",
"machine-0.0.1");
// Get remote context from
void *tracer = otelc_get_tracer();
void *span = otelc_start_span(tracer, "get-hello", OTELC_SPAN_KIND_CLIENT, "");
char *span_contexnt = otelc_extract_context_from_current_span(span);
// Send the context by network and do something
// ...
free(span_contexnt);
otelc_end_span(span);
otelc_destroy_tracer(tracer);
return 0;
}
Example 3 : Create a span from a remote context.
#include <opentelemetry_c/opentelemetry_c.h>
#include <stdlib.h>
int main(void) {
otelc_init_tracer_provider("example", "0.0.1", "",
"machine-0.0.1");
// Get remote context from
void *tracer = otelc_get_tracer();
// Receive a remote context
char *remote_contexnt = "The context received";
// Start a span with the context received
void *span = otelc_start_span(tracer, "get-hello", OTELC_SPAN_KIND_SERVER, remote_context);
// So something
// ...
otelc_end_span(span);
free(remote_contexnt);
otelc_destroy_tracer(tracer);
return 0;
}
The following functions are available for initializing and creating various types of metrics objects, such as counters. These metrics objects can be used to collect data on the performance of a service.
/**
* @brief Initialize the Meter Provider and Meter reader
*
* Read more on
* https://opentelemetry.io/docs/reference/specification/metrics/sdk/#meterprovider
* and
* https://opentelemetry.io/docs/reference/specification/metrics/sdk/#metricreader
*
* @param service_name The name of the service we are tracing
* @param service_version The version of the service
* @param service_namespace The service namespace
* @param service_instance_id The host instance id
* @param export_interval_millis The time interval in milliseconds between two
* consecutive exports
* @param export_timeout_millis How long the export can run before it is
* cancelled
*/
void otelc_init_metrics_provider(const char *service_name,
const char *service_version,
const char *service_namespace,
const char *service_instance_id,
int64_t export_interval_millis,
int64_t export_timeout_millis);
/**
* @brief Create a int64 up down counter
*
* Read more on :
* https://opentelemetry.io/docs/reference/specification/metrics/api/#updowncounter
*
* @param name Counter name
* @param description A description of what the counter does
* @return void* The counter
*/
void *otelc_create_int64_up_down_counter(const char *name, const char *description);
/**
* @brief Increment or decrement the UpDownCounter by a fixed amount
*
* https://opentelemetry.io/docs/reference/specification/metrics/api/#add-1
*
* @param counter The counter
* @param value The increment or decrement
*/
void otelc_int64_up_down_counter_add(void *counter, int64_t value);
/**
* @brief Deallocate all resources used by the counter
*
* @param counter The counter
*/
void otelc_destroy_up_down_counter(void *counter);
/**
* @brief Create a int64 asynchronous up down counter
*
* Read more on :
* https://opentelemetry.io/docs/reference/specification/metrics/api/#asynchronous-updowncounter
*
* @param name Counter name
* @param description A description of what the counter does
* @return void* The counter
*/
void *otelc_create_int64_observable_up_down_counter(const char *name,
const char *description);
/**
* @brief Register an asynchronous up down counter callback
*
* Read more on :
* https://opentelemetry.io/docs/reference/specification/metrics/api/#asynchronous-updowncounter-operations
*
* @param counter The counter
* @param callback The callback is a function returning the increment to apply
* to the counter
* @return void* The callback registration that should be use to cancel it
*/
void *otelc_int64_observable_up_down_counter_register_callback(void *counter,
int64_t (*callback)());
/**
* @brief Cancel an asynchronous up down counter callback registration
*
* Read more on :
* https://opentelemetry.io/docs/reference/specification/metrics/api/#asynchronous-updowncounter-operations
*
* @param counter The counter
* @param registration The callback registration
*/
void otelc_int64_observable_up_down_counter_cancel_registration(void *counter,
void *registration);
/**
* @brief Deallocate all resources used by the counter
*
* @param counter The counter
*/
void otelc_destroy_observable_up_down_counter(void *counter);
Example 1 : Asynchronous counter
// TODO
#include <opentelemetry_c/opentelemetry_c.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/**
* @brief Function called periodically by the counter to get the difference
* between the current observation and the last sent
*/
int64_t counter_callback() {
static int64_t last_n_active_requests = 0;
int64_t current_n_active_requests = rand() % 100;
int64_t delta = current_n_active_requests - last_n_active_requests;
last_n_active_requests = current_n_active_requests;
printf("n_active_requests=%ld\n", current_n_active_requests);
printf("delta=%ld\n", delta);
return delta;
}
int main() {
printf("Observable Up Down Counter Basic example starts ...!\n");
srand(0); // NOLINT
otelc_init_metrics_provider("test_service", "0.0.1", "com.test",
"fake-instance-id-123456789", 1000, 500);
void *counter = otelc_create_int64_observable_up_down_counter(
"n_active_requests", "Simple counter to keep track of the number of "
"active requests in the system");
void *registration = otelc_int64_observable_up_down_counter_register_callback(
counter, &counter_callback);
sleep(60); // Give time to counter to call callback few times
otelc_int64_observable_up_down_counter_cancel_registration(counter,
registration);
otelc_destroy_observable_up_down_counter(counter);
printf("Observable Up Down Counter Basic example ends ...!\n");
return 0;
}
Example 2 : Synchronous counter
#include <opentelemetry_c/opentelemetry_c.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
printf("Up Down Counter Basic example starts ...!\n");
srand(0); // NOLINT
otelc_init_metrics_provider("test_service", "0.0.1", "com.test",
"fake-instance-id-123456789", 1000, 500);
void *counter = otelc_create_int64_up_down_counter(
"n_active_requests", "Simple counter to keep track of the number of "
"active requests in the system");
int64_t n_active_requests = 0;
otelc_int64_up_down_counter_add(counter, 0);
for (int i = 0; i < 60; i++) {
// Randomly generate a number for active requests
int64_t n_active_requests_new = rand() % 100; // NOLINT
int64_t delta = n_active_requests_new - n_active_requests;
printf("n_active_requests=%ld\n", n_active_requests_new);
printf("delta=%ld\n", delta);
otelc_int64_up_down_counter_add(counter, delta);
n_active_requests = n_active_requests_new;
// The work : Sleep between 0 and 1 second
usleep(1000000.0F / RAND_MAX * rand()); // NOLINT
}
sleep(2); // Give time to process the last metric
otelc_destroy_up_down_counter(counter);
printf("Up Down Counter Basic example ends ...!\n");
return 0;
}
The following functions and types are available for emitting log records in the OpenTelemetry tracing system.
/**
* @brief Get the logger
*
* Read more on
* https://opentelemetry.io/docs/specs/otel/logs/bridge-api/#get-a-logger
*
* @param service_name The name of the service we are tracing
* @param service_version The version of the service
* @param service_namespace The service namespace
* @param service_instance_id The host instance id
*/
void otelc_init_logger_provider(const char *service_name,
const char *service_version,
const char *service_namespace,
const char *service_instance_id);
/**
* @brief Get the logger object
* The logger object is used to emit log records
*
* Read more on :
* https://opentelemetry.io/docs/specs/otel/logs/bridge-api/#emit-a-logrecord
*
* @return void*
*/
void *otelc_get_logger();
/**
* @brief Deallocate all resources used by the logger
* @param logger
*/
void otelc_destroy_logger(void *logger);
/**
* @brief Define the log severity
*
* Read more on : https://opentelemetry.io/docs/specs/otel/logs/data-model/#displaying-severity
*/
typedef enum { // NOLINTBEGIN
OTEL_C_LOG_SEVERITY_KINVALID,
OTEL_C_LOG_SEVERITY_KTRACE,
OTEL_C_LOG_SEVERITY_KTRACE2,
OTEL_C_LOG_SEVERITY_KTRACE3,
OTEL_C_LOG_SEVERITY_KTRACE4,
OTEL_C_LOG_SEVERITY_KDEBUG,
OTEL_C_LOG_SEVERITY_KDEBUG2,
OTEL_C_LOG_SEVERITY_KDEBUG3,
OTEL_C_LOG_SEVERITY_KDEBUG4,
OTEL_C_LOG_SEVERITY_KINFO,
OTEL_C_LOG_SEVERITY_KINFO2,
OTEL_C_LOG_SEVERITY_KINFO3,
OTEL_C_LOG_SEVERITY_KINFO4,
OTEL_C_LOG_SEVERITY_KWARN,
OTEL_C_LOG_SEVERITY_KWARN2,
OTEL_C_LOG_SEVERITY_KWARN3,
OTEL_C_LOG_SEVERITY_KWARN4,
OTEL_C_LOG_SEVERITY_KERROR,
OTEL_C_LOG_SEVERITY_KERROR2,
OTEL_C_LOG_SEVERITY_KERROR3,
OTEL_C_LOG_SEVERITY_KERROR4,
OTEL_C_LOG_SEVERITY_KFATAL,
OTEL_C_LOG_SEVERITY_KFATAL2,
OTEL_C_LOG_SEVERITY_KFATAL3,
OTEL_C_LOG_SEVERITY_KFATAL4
} otelc_log_severity_t; // NOLINTEND
/**
* @brief Emit a log record
*
* Read more : https://opentelemetry.io/docs/specs/otel/logs/bridge-api/#emit-a-logrecord
*
* @param severity
* @param body
*/
void otelc_log(void *logger, otelc_log_severity_t severity, const char *body);
Example:
#include <opentelemetry_c/opentelemetry_c.h>
int main() {
otelc_init_logger_provider("test_service", "0.0.1", "com.test",
"fake-instance-id-123456789");
void *logger = otelc_get_logger();
otelc_log(logger, OTEL_C_LOG_SEVERITY_KINFO, "Hello");
return 0;
}
Some examples of wrapper usage can be found in the examples folder. To execute an example :
$ ./run.sh <example>
example is either basic
, up-down-counter
, observable-up-down-counter
or client-server-socket
.
Refer to each example README.md to understand each of them.
Instead of installing all dependencies before running examples, you can run examples directly in Docker.
$ docker build -t opentelemetry-c .
Sending build context to Docker daemon 803.8kB
Step 1/6 : FROM ghcr.io/dorsal-lab/lttng-otelcpp:main
...
Step 6/6 : CMD ./run.sh basic && ./run.sh up-down-counter && ./run.sh observable-up-down-counter && ./run.sh client-server-socket
---> Running in d1eeb864e1b1
Removing intermediate container d1eeb864e1b1
---> 45e569393564
Successfully built 45e569393564
Successfully tagged opentelemetry-c:latest
$ docker run opentelemetry-c ./run.sh basic
Building basic-example target ...
-- The C compiler identification is GNU 10.4.0
-- The CXX compiler identification is GNU 10.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/gcc-10 - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/g++-10 - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found nlohmann_json: /usr/local/lib/cmake/nlohmann_json/nlohmann_jsonConfig.cmake (found version "3.10.5")
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- Found opentelemetry-cpp: /usr/local/include (Required is at least version "1.8.1")
-- Found LTTngUST: /usr/local/lib/liblttng-ust.so;dl (found version "2.3.5")
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/opentelemetry-c-build
[ 11%] Building CXX object CMakeFiles/opentelemetry-c.dir/src/opentelemetry_c.cpp.o
...
[100%] Built target basic-example
Starting a LTTng session ...
Spawning a session daemon
Session auto-20230326-230750 created.
Traces will be output to /tmp/opentelemetry-c/ctf-traces/basic
ust event opentelemetry:* created in channel channel0
ust context vtid added to all channels
Tracing started for session auto-20230326-230750
Starting basic example ...
Basic example starts ...!
Basic example ends ...!
Stop LTTng session ...
Waiting for data availability.
Tracing stopped for session auto-20230326-230750
View traces ...
[23:07:52.009282402] (+?.?????????) 32cb5db20ee3 opentelemetry:resource_spans: { cpu_id = 1 }, { vtid = 180 }, { _resource_spans_length = 481, resource_spans = [ [0] = 10, [1] = 252, [2] = 1, [3] = 10, [4] = 32, [5] = 10, [6] = 21, [7] = 116, [8] = 101, [9] = 108, [10] = 101, [11] = 109, [12] = 101, [13] = 116, [14] = 114, [15] = 121, [16] = 46, [17] = 115, [18] = 100, [19] = 107, [20] = 46, [21] ...
[23:07:52.404522461] (+0.395240059) 32cb5db20ee3 opentelemetry:resource_spans: { cpu_id = 1 }, { vtid = 180 }, { _resource_spans_length = 481, resource_spans = [ [0] = 10, [1] = 252, [2] = 1, [3] = 10, [4] = 32, [5] = 10, [6] = 21, [7] = 116, [8] = 101, [9] = 108, [10] = 101, [11] = 109, [12] = 101, [13] = 116, [14] = 114, [15] = 121, [16] = 46, [17] = 115, [18] = 100, [19] = 107, [20] = 46, [21] ...
[23:07:53.188366671] (+0.783844210) 32cb5db20ee3 opentelemetry:resource_spans: { cpu_id = 1 }, { vtid = 180 }, { _resource_spans_length = 481, resource_spans = [ [0] = 10, [1] = 252, [2] = 1, [3] = 10, [4] = 32, [5] = 10, [6] = 21, [7] = 116, [8] = 101, [9] = 108, [10] = 101, [11] = 109, [12] = 101, [13] = 116, [14] = 114, [15] = 121, [16] = 46, [17] = 115, [18] = 100, [19] = 107, [20] = 46, [21] ...
[23:07:53.188595441] (+0.000228770) 32cb5db20ee3 opentelemetry:resource_spans: { cpu_id = 1 }, { vtid = 180 }, { _resource_spans_length = 349, resource_spans = [ [0] = 10, [1] = 252, [2] = 1, [3] = 10, [4] = 32, [5] = 10, [6] = 21, [7] = 116, [8] = 101, [9] = 108, [10] = 101, [11] = 109, [12] = 101, [13] = 116, [14] = 114, [15] = 121, [16] = 46, [17] = 115, [18] = 100, [19] = 107, [20] = 46, [21] ...
Destroying LTTng session ...
Destroying session auto-20230326-230750..
Session auto-20230326-230750 destroyed
Done!