diff --git a/examples/otlp/BUILD b/examples/otlp/BUILD index e8a8be791c..6b2086d783 100644 --- a/examples/otlp/BUILD +++ b/examples/otlp/BUILD @@ -41,6 +41,24 @@ cc_binary( ]), ) +cc_binary( + name = "example_otlp_file", + srcs = [ + "file_main.cc", + ], + tags = [ + "examples", + "otlp", + "otlp_file", + ], + deps = [ + "//api", + "//examples/common/foo_library:common_foo_library", + "//exporters/otlp:otlp_file_exporter", + "//sdk/src/trace", + ], +) + cc_binary( name = "example_otlp_http_log", srcs = [ @@ -79,6 +97,25 @@ cc_binary( ]), ) +cc_binary( + name = "example_otlp_file_log", + srcs = [ + "file_log_main.cc", + ], + tags = [ + "examples", + "otlp", + "otlp_file_log", + ], + deps = [ + "//api", + "//examples/common/logs_foo_library:common_logs_foo_library", + "//exporters/otlp:otlp_file_exporter", + "//exporters/otlp:otlp_file_log_record_exporter", + "//sdk/src/trace", + ], +) + cc_binary( name = "example_otlp_grpc_metric", srcs = [ @@ -116,3 +153,22 @@ cc_binary( "//sdk/src/metrics", ]), ) + +cc_binary( + name = "example_otlp_file_metric", + srcs = [ + "file_metric_main.cc", + ], + tags = [ + "examples", + "metrics", + "otlp", + ], + deps = [ + "//api", + "//examples/common/metrics_foo_library:common_metrics_foo_library", + "//exporters/otlp:otlp_file_exporter", + "//exporters/otlp:otlp_file_metric_exporter", + "//sdk/src/metrics", + ], +) diff --git a/examples/otlp/CMakeLists.txt b/examples/otlp/CMakeLists.txt index 5d051a52cc..145fafca87 100644 --- a/examples/otlp/CMakeLists.txt +++ b/examples/otlp/CMakeLists.txt @@ -100,3 +100,47 @@ if(WITH_OTLP_HTTP) endif() endif() + +if(WITH_OTLP_FILE) + # TRACE + + add_executable(example_otlp_file file_main.cc) + + target_link_libraries(example_otlp_file ${CMAKE_THREAD_LIBS_INIT} + common_foo_library) + + if(DEFINED OPENTELEMETRY_BUILD_DLL) + target_link_libraries(example_otlp_file opentelemetry_cpp) + else() + target_link_libraries(example_otlp_file opentelemetry_trace + opentelemetry_exporter_otlp_file) + endif() + + # METRIC + + add_executable(example_otlp_file_metric file_metric_main.cc) + + target_link_libraries(example_otlp_file_metric ${CMAKE_THREAD_LIBS_INIT} + common_metrics_foo_library) + + if(DEFINED OPENTELEMETRY_BUILD_DLL) + target_link_libraries(example_otlp_file_metric opentelemetry_cpp) + else() + target_link_libraries(example_otlp_file_metric opentelemetry_metrics + opentelemetry_exporter_otlp_file_metric) + endif() + + # LOG + + add_executable(example_otlp_file_log file_log_main.cc) + + target_link_libraries(example_otlp_file_log ${CMAKE_THREAD_LIBS_INIT} + common_logs_foo_library) + if(DEFINED OPENTELEMETRY_BUILD_DLL) + target_link_libraries(example_otlp_file_log opentelemetry_cpp) + else() + target_link_libraries( + example_otlp_file_log opentelemetry_trace opentelemetry_logs + opentelemetry_exporter_otlp_file opentelemetry_exporter_otlp_file_log) + endif() +endif() diff --git a/examples/otlp/file_log_main.cc b/examples/otlp/file_log_main.cc new file mode 100644 index 0000000000..f903449c56 --- /dev/null +++ b/examples/otlp/file_log_main.cc @@ -0,0 +1,124 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/otlp/otlp_file_client_options.h" +#include "opentelemetry/exporters/otlp/otlp_file_exporter_factory.h" +#include "opentelemetry/exporters/otlp/otlp_file_exporter_options.h" +#include "opentelemetry/exporters/otlp/otlp_file_log_record_exporter_factory.h" +#include "opentelemetry/exporters/otlp/otlp_file_log_record_exporter_options.h" +#include "opentelemetry/logs/provider.h" +#include "opentelemetry/sdk/logs/exporter.h" +#include "opentelemetry/sdk/logs/logger_provider_factory.h" +#include "opentelemetry/sdk/logs/processor.h" +#include "opentelemetry/sdk/logs/simple_log_record_processor_factory.h" +#include "opentelemetry/sdk/trace/exporter.h" +#include "opentelemetry/sdk/trace/processor.h" +#include "opentelemetry/sdk/trace/simple_processor_factory.h" +#include "opentelemetry/sdk/trace/tracer_provider_factory.h" +#include "opentelemetry/trace/provider.h" + +// sdk::TracerProvider and sdk::LoggerProvider is just used to call ForceFlush and prevent to cancel +// running exportings when destroy and shutdown exporters.It's optional to users. +#include "opentelemetry/sdk/logs/logger_provider.h" +#include "opentelemetry/sdk/trace/tracer_provider.h" + +#include +#include +#include + +#ifdef BAZEL_BUILD +# include "examples/common/logs_foo_library/foo_library.h" +#else +# include "logs_foo_library/foo_library.h" +#endif + +namespace trace = opentelemetry::trace; +namespace nostd = opentelemetry::nostd; +namespace otlp = opentelemetry::exporter::otlp; +namespace logs_sdk = opentelemetry::sdk::logs; +namespace logs = opentelemetry::logs; +namespace trace_sdk = opentelemetry::sdk::trace; + +namespace +{ +opentelemetry::exporter::otlp::OtlpFileExporterOptions opts; +opentelemetry::exporter::otlp::OtlpFileLogRecordExporterOptions log_opts; +void InitTracer() +{ + // Create OTLP exporter instance + auto exporter = otlp::OtlpFileExporterFactory::Create(opts); + auto processor = trace_sdk::SimpleSpanProcessorFactory::Create(std::move(exporter)); + std::shared_ptr provider = + trace_sdk::TracerProviderFactory::Create(std::move(processor)); + // Set the global trace provider + trace::Provider::SetTracerProvider(provider); +} + +void CleanupTracer() +{ + // We call ForceFlush to prevent to cancel running exportings, It's optional. + opentelemetry::nostd::shared_ptr provider = + trace::Provider::GetTracerProvider(); + if (provider) + { + static_cast(provider.get())->ForceFlush(); + } + + std::shared_ptr none; + trace::Provider::SetTracerProvider(none); +} + +void InitLogger() +{ + // Create OTLP exporter instance + auto exporter = otlp::OtlpFileLogRecordExporterFactory::Create(log_opts); + auto processor = logs_sdk::SimpleLogRecordProcessorFactory::Create(std::move(exporter)); + nostd::shared_ptr provider( + logs_sdk::LoggerProviderFactory::Create(std::move(processor))); + + opentelemetry::logs::Provider::SetLoggerProvider(provider); +} + +void CleanupLogger() +{ + // We call ForceFlush to prevent to cancel running exportings, It's optional. + opentelemetry::nostd::shared_ptr provider = + logs::Provider::GetLoggerProvider(); + if (provider) + { + static_cast(provider.get())->ForceFlush(); + } + + nostd::shared_ptr none; + opentelemetry::logs::Provider::SetLoggerProvider(none); +} +} // namespace + +int main(int argc, char *argv[]) +{ + if (argc > 1) + { + opentelemetry::exporter::otlp::OtlpFileClientFileSystemOptions fs_backend; + fs_backend.file_pattern = argv[1]; + opts.backend_options = fs_backend; + if (argc > 2) + { + opentelemetry::exporter::otlp::OtlpFileClientFileSystemOptions logs_fs_backend; + logs_fs_backend.file_pattern = argv[2]; + log_opts.backend_options = logs_fs_backend; + } + else + { + log_opts.backend_options = std::ref(std::cout); + } + } + else + { + opts.backend_options = std::ref(std::cout); + } + InitLogger(); + InitTracer(); + foo_library(); + CleanupTracer(); + CleanupLogger(); +} diff --git a/examples/otlp/file_main.cc b/examples/otlp/file_main.cc new file mode 100644 index 0000000000..e0a1264fb6 --- /dev/null +++ b/examples/otlp/file_main.cc @@ -0,0 +1,71 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/otlp/otlp_file_exporter_factory.h" +#include "opentelemetry/sdk/trace/processor.h" +#include "opentelemetry/sdk/trace/simple_processor_factory.h" +#include "opentelemetry/sdk/trace/tracer_provider_factory.h" +#include "opentelemetry/trace/provider.h" + +// sdk::TracerProvider is just used to call ForceFlush and prevent to cancel running exportings when +// destroy and shutdown exporters.It's optional to users. +#include "opentelemetry/sdk/trace/tracer_provider.h" + +#include +#include +#include + +#ifdef BAZEL_BUILD +# include "examples/common/foo_library/foo_library.h" +#else +# include "foo_library/foo_library.h" +#endif + +namespace trace = opentelemetry::trace; +namespace trace_sdk = opentelemetry::sdk::trace; +namespace otlp = opentelemetry::exporter::otlp; + +namespace +{ +opentelemetry::exporter::otlp::OtlpFileExporterOptions opts; +void InitTracer() +{ + // Create OTLP exporter instance + auto exporter = otlp::OtlpFileExporterFactory::Create(opts); + auto processor = trace_sdk::SimpleSpanProcessorFactory::Create(std::move(exporter)); + std::shared_ptr provider = + trace_sdk::TracerProviderFactory::Create(std::move(processor)); + // Set the global trace provider + trace::Provider::SetTracerProvider(provider); +} + +void CleanupTracer() +{ + // We call ForceFlush to prevent to cancel running exportings, It's optional. + opentelemetry::nostd::shared_ptr provider = + trace::Provider::GetTracerProvider(); + if (provider) + { + static_cast(provider.get())->ForceFlush(); + } + + std::shared_ptr none; + trace::Provider::SetTracerProvider(none); +} +} // namespace + +int main(int argc, char *argv[]) +{ + if (argc > 1) + { + opentelemetry::exporter::otlp::OtlpFileClientFileSystemOptions fs_backend; + fs_backend.file_pattern = argv[1]; + opts.backend_options = fs_backend; + } + // Removing this line will leave the default noop TracerProvider in place. + InitTracer(); + + foo_library(); + + CleanupTracer(); +} diff --git a/examples/otlp/file_metric_main.cc b/examples/otlp/file_metric_main.cc new file mode 100644 index 0000000000..b99d77a609 --- /dev/null +++ b/examples/otlp/file_metric_main.cc @@ -0,0 +1,108 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/otlp/otlp_file_metric_exporter_factory.h" +#include "opentelemetry/metrics/provider.h" +#include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h" +#include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader.h" +#include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_factory.h" +#include "opentelemetry/sdk/metrics/meter.h" +#include "opentelemetry/sdk/metrics/meter_context_factory.h" +#include "opentelemetry/sdk/metrics/meter_provider.h" +#include "opentelemetry/sdk/metrics/meter_provider_factory.h" + +#include +#include +#include +#include +#include + +#ifdef BAZEL_BUILD +# include "examples/common/metrics_foo_library/foo_library.h" +#else +# include "metrics_foo_library/foo_library.h" +#endif + +namespace metric_sdk = opentelemetry::sdk::metrics; +namespace common = opentelemetry::common; +namespace metrics_api = opentelemetry::metrics; +namespace otlp_exporter = opentelemetry::exporter::otlp; + +namespace +{ + +otlp_exporter::OtlpFileMetricExporterOptions exporter_options; + +void InitMetrics() +{ + auto exporter = otlp_exporter::OtlpFileMetricExporterFactory::Create(exporter_options); + + std::string version{"1.2.0"}; + std::string schema{"https://opentelemetry.io/schemas/1.2.0"}; + + // Initialize and set the global MeterProvider + metric_sdk::PeriodicExportingMetricReaderOptions reader_options; + reader_options.export_interval_millis = std::chrono::milliseconds(1000); + reader_options.export_timeout_millis = std::chrono::milliseconds(500); + + auto reader = + metric_sdk::PeriodicExportingMetricReaderFactory::Create(std::move(exporter), reader_options); + + auto context = metric_sdk::MeterContextFactory::Create(); + context->AddMetricReader(std::move(reader)); + + auto u_provider = metric_sdk::MeterProviderFactory::Create(std::move(context)); + std::shared_ptr provider(std::move(u_provider)); + + metrics_api::Provider::SetMeterProvider(provider); +} + +void CleanupMetrics() +{ + std::shared_ptr none; + metrics_api::Provider::SetMeterProvider(none); +} +} // namespace + +int main(int argc, char *argv[]) +{ + std::string example_type; + if (argc > 1) + { + opentelemetry::exporter::otlp::OtlpFileClientFileSystemOptions fs_backend; + fs_backend.file_pattern = argv[1]; + exporter_options.backend_options = fs_backend; + if (argc > 2) + { + example_type = argv[2]; + } + } + // Removing this line will leave the default noop MetricProvider in place. + InitMetrics(); + std::string name{"otlp_file_metric_example"}; + + if (example_type == "counter") + { + foo_library::counter_example(name); + } + else if (example_type == "observable_counter") + { + foo_library::observable_counter_example(name); + } + else if (example_type == "histogram") + { + foo_library::histogram_example(name); + } + else + { + std::thread counter_example{&foo_library::counter_example, name}; + std::thread observable_counter_example{&foo_library::observable_counter_example, name}; + std::thread histogram_example{&foo_library::histogram_example, name}; + + counter_example.join(); + observable_counter_example.join(); + histogram_example.join(); + } + + CleanupMetrics(); +} diff --git a/exporters/otlp/README.md b/exporters/otlp/README.md index 812bb8e3c2..21b5f002ed 100644 --- a/exporters/otlp/README.md +++ b/exporters/otlp/README.md @@ -42,6 +42,22 @@ options.url = "localhost:12345"; auto exporter = std::unique_ptr(new otlp::OtlpHttpExporter(options)); ``` +The OTLP File exporter offers some configuration options. To configure the exporter, +create an `OtlpFileExporterOptions` struct (defined in +[otlp_file_exporter_options.h](https://github.com/open-telemetry/opentelemetry-cpp/blob/main/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_file_exporter_options.h) +and +[otlp_file_client_options.h](https://github.com/open-telemetry/opentelemetry-cpp/blob/main/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_file_client_options.h)), +set the options inside, and pass the struct to the `OtlpFileExporter` constructor, +like so: + +```cpp +OtlpFileExporterOptions options; +OtlpFileClientFileSystemOptions fs_backend; +fs_backend.file_pattern = "trace.%N.log"; +options.backend_options = fs_backend; +auto exporter = std::unique_ptr(new otlp::OtlpFileExporter(options)); +``` + ### Configuration options ( OTLP GRPC Exporter ) | Option | Env Variable | Default | Description | @@ -73,6 +89,48 @@ auto exporter = std::unique_ptr(new otlp::OtlpHttpExport |`http_headers` |`OTEL_EXPORTER_OTLP_HEADERS` | | http headers | | |`OTEL_EXPORTER_OTLP_TRACES_HEADERS` | | | +### Configuration options ( OTLP File Exporter ) + +| Option | Env Variable | Default | Description | +|--------------------|------------------------------------|---------------------------------|-------------------------------------------------------------------| +|`backend_options` | n/a |`OtlpFileClientFileSystemOptions`| The OTLP FILE backend | + +The backend for OTLP File Exporter can be `OtlpFileClientFileSystemOptions` (which +support basic log rotate and alias), and reference to `std::ostream` or custom `OtlpFileAppender`. + +#### Configuration options ( File System Backend for OTLP File Exporter ) + +| Option | Env Variable | Default | Description | +|--------------------|------------------------------------|---------------------------------|-------------------------------------------------------------------| +|`file_pattern` | n/a |`trace-%N.jsonl` | The file pattern to use | +| | |`metrics-%N.jsonl` | | +| | |`logs-%N.jsonl` | | +|`alias_pattern` | n/a | `trace-latest.jsonl` | The file which always point to the latest file | +| | | `metrics-latest.jsonl` | | +| | | `logs-latest.jsonl` | | +|`flush_interval` | n/a | `30s` | Interval to force flush ostream | +|`flush_count` | n/a | `256` | Force flush ostream every `flush_count` records | +|`file_size` | n/a | `20MB` | File size to rotate log files | +|`rotate_size` | n/a | | Rotate count | + +Some special placeholders are available for `file_pattern` and `alias_pattern`: + ++ `%Y`: Writes year as a 4 digit decimal number ++ `%y`: Writes last 2 digits of year as a decimal number (range [00,99]) ++ `%m`: Writes month as a decimal number (range [01,12]) ++ `%j`: Writes day of the year as a decimal number (range [001,366]) ++ `%d`: Writes day of the month as a decimal number (range [01,31]) ++ `%w`: Writes weekday as a decimal number, where Sunday is 0 (range [0-6]) ++ `%H`: Writes hour as a decimal number, 24 hour clock (range [00-23]) ++ `%I`: Writes hour as a decimal number, 12 hour clock (range [01,12]) ++ `%M`: Writes minute as a decimal number (range [00,59]) ++ `%S`: Writes second as a decimal number (range [00,60]) ++ `%F`: Equivalent to "%Y-%m-%d" (the ISO 8601 date format) ++ `%T`: Equivalent to "%H:%M:%S" (the ISO 8601 time format) ++ `%R`: Equivalent to "%H:%M" ++ `%N`: Rotate index, start from 0 ++ `%n`: Rotate index, start from 1 + ## Example For a complete example demonstrating how to use the OTLP exporter, see