-
Notifications
You must be signed in to change notification settings - Fork 417
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
ostream metrics example #1312
ostream metrics example #1312
Changes from 8 commits
8d1bf2c
8c6ea1d
04afa7f
dcb1c5d
e51b14b
55aa2d9
7aa6a14
7b89ff9
f9e42c6
35cb208
34e8b8e
454a2c9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
#include <memory> | ||
#ifndef ENABLE_METRICS_PREVIEW | ||
# include <chrono> | ||
# include <thread> | ||
# include "opentelemetry/exporters/ostream/metric_exporter.h" | ||
# include "opentelemetry/metrics/provider.h" | ||
# include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h" | ||
# include "opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h" | ||
# include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader.h" | ||
# include "opentelemetry/sdk/metrics/meter.h" | ||
# include "opentelemetry/sdk/metrics/meter_provider.h" | ||
|
||
# include <iostream> | ||
|
||
namespace metric_sdk = opentelemetry::sdk::metrics; | ||
namespace nostd = opentelemetry::nostd; | ||
namespace common = opentelemetry::common; | ||
namespace exportermetrics = opentelemetry::exporter::metrics; | ||
namespace metrics_api = opentelemetry::metrics; | ||
|
||
void sync_sum() | ||
{ | ||
std::unique_ptr<metric_sdk::MetricExporter> exporter{new exportermetrics::OStreamMetricExporter}; | ||
std::vector<std::unique_ptr<metric_sdk::MetricExporter>> exporters; | ||
|
||
std::string name{"ostream_metric_example"}; | ||
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 options; | ||
options.export_interval_millis = std::chrono::milliseconds(1000); | ||
options.export_timeout_millis = std::chrono::milliseconds(500); | ||
std::unique_ptr<metric_sdk::MetricReader> reader{ | ||
new metric_sdk::PeriodicExportingMetricReader(std::move(exporter), options)}; | ||
auto provider = std::shared_ptr<metrics_api::MeterProvider>( | ||
new metric_sdk::MeterProvider(std::move(exporters))); | ||
auto p = std::static_pointer_cast<metric_sdk::MeterProvider>(provider); | ||
p->AddMetricReader(std::move(reader)); | ||
std::unique_ptr<metric_sdk::InstrumentSelector> instrument_selector{ | ||
new metric_sdk::InstrumentSelector(metric_sdk::InstrumentType::kCounter, name)}; | ||
std::unique_ptr<metric_sdk::MeterSelector> meter_selector{ | ||
new metric_sdk::MeterSelector(name, version, schema)}; | ||
std::unique_ptr<metric_sdk::View> view{ | ||
new metric_sdk::View{name, "description", metric_sdk::AggregationType::kSum}}; | ||
p->AddView(std::move(instrument_selector), std::move(meter_selector), std::move(view)); | ||
metrics_api::Provider::SetMeterProvider(provider); | ||
|
||
// Get the Meter from the MeterProvider | ||
nostd::shared_ptr<metrics_api::Meter> meter = provider->GetMeter(name, "1.2.0"); | ||
auto double_counter = meter->CreateDoubleCounter(name); | ||
double_counter->Add(28.5); | ||
std::this_thread::sleep_for(std::chrono::milliseconds(500)); | ||
double_counter->Add(3.14); | ||
std::this_thread::sleep_for(std::chrono::milliseconds(500)); | ||
double_counter->Add(23.5); | ||
std::this_thread::sleep_for(std::chrono::milliseconds(5000)); | ||
p->ForceFlush(); | ||
} | ||
|
||
int main() | ||
{ | ||
sync_sum(); | ||
} | ||
#else | ||
int main() {} | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,68 +1,95 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
#include <chrono> | ||
#ifndef ENABLE_METRICS_PREVIEW | ||
# include "opentelemetry/exporters/ostream/metric_exporter.h" | ||
# include <algorithm> | ||
# include "opentelemetry/exporters/ostream/metric_exporter.h" | ||
# include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h" | ||
# include "opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h" | ||
# include "opentelemetry/sdk_config.h" | ||
|
||
namespace | ||
{ | ||
std::string timeToString(opentelemetry::common::SystemTimestamp time_stamp) | ||
{ | ||
auto duration = time_stamp.time_since_epoch().count(); | ||
|
||
std::chrono::nanoseconds dur(duration); | ||
std::chrono::time_point<std::chrono::system_clock> dt(dur); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit - need to check, but I think this can be directly obtained by calling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I try to print time in human readable format here. I didn't find any function similar. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if something wrong with GitHub. I pasted a comment here, it was displayed multiple times and then when I removed one occurrence all of them removed :) But it was not that important, was thinking something to avoid couple of lines of code (so can be ignored): std::string timeToString(opentelemetry::common::SystemTimestamp time_stamp)
{
std::time_t epoch_time = std::chrono::system_clock::to_time_t(time_stamp());
return std::ctime(&epoch_time);
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks, added your version. |
||
std::time_t epoch_time = std::chrono::system_clock::to_time_t(dt); | ||
|
||
return std::ctime(&epoch_time); | ||
} | ||
} // namespace | ||
|
||
OPENTELEMETRY_BEGIN_NAMESPACE | ||
namespace exporter | ||
{ | ||
namespace metrics | ||
{ | ||
|
||
template <typename Container> | ||
inline void printVec(std::ostream &os, Container &vec) | ||
{ | ||
using T = typename std::decay<decltype(*vec.begin())>::type; | ||
os << '['; | ||
if (vec.size() > 1) | ||
{ | ||
std::copy(vec.begin(), vec.end(), std::ostream_iterator<T>(os, ", ")); | ||
} | ||
os << ']'; | ||
} | ||
|
||
OStreamMetricExporter::OStreamMetricExporter(std::ostream &sout) noexcept : sout_(sout) {} | ||
|
||
sdk::common::ExportResult OStreamMetricExporter::Export( | ||
const nostd::span<std::unique_ptr<opentelemetry::sdk::metrics::MetricData>> &records) noexcept | ||
const sdk::metrics::ResourceMetrics &data) noexcept | ||
{ | ||
if (isShutdown()) | ||
{ | ||
OTEL_INTERNAL_LOG_ERROR("[OStream Metric] Exporting " | ||
<< records.size() << " records(s) failed, exporter is shutdown"); | ||
<< data.instrumentation_info_metric_data_.size() | ||
<< " records(s) failed, exporter is shutdown"); | ||
return sdk::common::ExportResult::kFailure; | ||
} | ||
|
||
for (auto &record : records) | ||
for (auto &record : data.instrumentation_info_metric_data_) | ||
{ | ||
sout_ << "{" | ||
<< "\n name : " << record->instrumentation_library_->GetName() | ||
<< "\n version : " << record->instrumentation_library_->GetVersion(); | ||
printPointData(record->point_data_); | ||
sout_ << "\n}\n"; | ||
printInstrumentationInfoMetricData(record); | ||
} | ||
return sdk::common::ExportResult::kSuccess; | ||
} | ||
|
||
template <typename T> | ||
inline void printVec(std::ostream &os, std::vector<T> &vec) | ||
void OStreamMetricExporter::printInstrumentationInfoMetricData( | ||
const sdk::metrics::InstrumentationInfoMetrics &info_metric) | ||
{ | ||
os << '['; | ||
if (vec.size() > 1) | ||
{ | ||
std::copy(vec.begin(), vec.end() - 1, std::ostream_iterator<T>(os, ", ")); | ||
} | ||
if (!vec.empty()) | ||
sout_ << "{"; | ||
sout_ << "\n name\t\t: " << info_metric.instrumentation_library_->GetName() | ||
<< "\n schema url\t: " << info_metric.instrumentation_library_->GetSchemaURL() | ||
<< "\n version\t: " << info_metric.instrumentation_library_->GetVersion(); | ||
for (const auto &record : info_metric.metric_data_) | ||
{ | ||
os << vec.back(); | ||
sout_ << "\n start time\t: " << timeToString(record.start_ts) | ||
<< " end time\t: " << timeToString(record.end_ts) | ||
<< " description\t: " << record.instrument_descriptor.description_ | ||
<< "\n unit\t\t: " << record.instrument_descriptor.unit_; | ||
|
||
for (const auto &pd : record.point_data_attr_) | ||
{ | ||
printPointData(pd.point_data); | ||
} | ||
} | ||
os << ']'; | ||
sout_ << "\n}\n"; | ||
} | ||
|
||
void OStreamMetricExporter::printPointData(opentelemetry::sdk::metrics::PointType &point_data) | ||
void OStreamMetricExporter::printPointData(const opentelemetry::sdk::metrics::PointType &point_data) | ||
{ | ||
if (nostd::holds_alternative<sdk::metrics::SumPointData>(point_data)) | ||
{ | ||
auto sum_point_data = nostd::get<sdk::metrics::SumPointData>(point_data); | ||
sout_ << "\n type : SumPointData"; | ||
sout_ << "\n start timestamp : " | ||
<< std::to_string(sum_point_data.start_epoch_nanos_.time_since_epoch().count()); | ||
sout_ << "\n end timestamp : " | ||
<< std::to_string(sum_point_data.end_epoch_nanos_.time_since_epoch().count()); | ||
sout_ << "\n value : "; | ||
sout_ << "\n type\t\t: SumPointData"; | ||
sout_ << "\n value\t\t: "; | ||
if (nostd::holds_alternative<double>(sum_point_data.value_)) | ||
{ | ||
sout_ << nostd::get<double>(sum_point_data.value_); | ||
|
@@ -76,8 +103,6 @@ void OStreamMetricExporter::printPointData(opentelemetry::sdk::metrics::PointTyp | |
{ | ||
auto histogram_point_data = nostd::get<sdk::metrics::HistogramPointData>(point_data); | ||
sout_ << "\n type : HistogramPointData"; | ||
sout_ << "\n timestamp : " | ||
<< std::to_string(histogram_point_data.epoch_nanos_.time_since_epoch().count()); | ||
sout_ << "\n count : " << histogram_point_data.count_; | ||
sout_ << "\n sum : "; | ||
if (nostd::holds_alternative<double>(histogram_point_data.sum_)) | ||
|
@@ -90,14 +115,14 @@ void OStreamMetricExporter::printPointData(opentelemetry::sdk::metrics::PointTyp | |
} | ||
|
||
sout_ << "\n buckets : "; | ||
if (nostd::holds_alternative<std::vector<double>>(histogram_point_data.boundaries_)) | ||
if (nostd::holds_alternative<std::list<double>>(histogram_point_data.boundaries_)) | ||
{ | ||
auto &double_boundaries = nostd::get<std::vector<double>>(histogram_point_data.boundaries_); | ||
auto &double_boundaries = nostd::get<std::list<double>>(histogram_point_data.boundaries_); | ||
printVec(sout_, double_boundaries); | ||
} | ||
else if (nostd::holds_alternative<std::vector<long>>(histogram_point_data.boundaries_)) | ||
else if (nostd::holds_alternative<std::list<long>>(histogram_point_data.boundaries_)) | ||
{ | ||
auto &long_boundaries = nostd::get<std::vector<long>>(histogram_point_data.boundaries_); | ||
auto &long_boundaries = nostd::get<std::list<long>>(histogram_point_data.boundaries_); | ||
printVec(sout_, long_boundaries); | ||
} | ||
|
||
|
@@ -109,8 +134,8 @@ void OStreamMetricExporter::printPointData(opentelemetry::sdk::metrics::PointTyp | |
auto last_point_data = nostd::get<sdk::metrics::LastValuePointData>(point_data); | ||
sout_ << "\n type : LastValuePointData"; | ||
sout_ << "\n timestamp : " | ||
<< std::to_string(last_point_data.epoch_nanos_.time_since_epoch().count()) | ||
<< std::boolalpha << "\n valid : " << last_point_data.is_lastvalue_valid_; | ||
<< std::to_string(last_point_data.sample_ts_.time_since_epoch().count()) << std::boolalpha | ||
<< "\n valid : " << last_point_data.is_lastvalue_valid_; | ||
sout_ << "\n value : "; | ||
if (nostd::holds_alternative<double>(last_point_data.value_)) | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit - should we add small metrics instrumentation under (example/common) similar to how we do for traces and logs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, added.