Skip to content

Commit a60ca4f

Browse files
[CurrencyService] Add C++ Metrics (#759)
* Add cpp metrics * Add IntCounter to CurrencyService * changelog * changelog * Fix indentantion * Add line break * Remove unnecessary comma * Remove unnecessary includes * Apply suggestions
1 parent 5a3f298 commit a60ca4f

File tree

6 files changed

+99
-9
lines changed

6 files changed

+99
-9
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ tls_certificate_check and bump to OTP-25
1818
([#756](https://github.com/open-telemetry/opentelemetry-demo/pull/756))
1919
* Bump up OTEL Java Agent version to 1.23.0
2020
([#757](https://github.com/open-telemetry/opentelemetry-demo/pull/757))
21+
* Add counter metric to currency service (C++)
22+
([#759](https://github.com/open-telemetry/opentelemetry-demo/issues/759))
2123
* Use browserDetector to populate browser info to frontend-web telemetry
2224
([#760](https://github.com/open-telemetry/opentelemetry-demo/pull/760))
2325

src/currencyservice/.dockerignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
client.js
22
node_modules/
3+
build/
4+
out/

src/currencyservice/CMakeLists.txt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
cmake_minimum_required(VERSION 3.1)
22
project(currency-service)
33

4-
find_package(Protobuf)
5-
find_package(gRPC)
4+
find_package(Protobuf REQUIRED)
5+
find_package(gRPC CONFIG REQUIRED)
6+
find_package(opentelemetry-cpp CONFIG REQUIRED)
67

78
set(PROTO_PATH "${CMAKE_CURRENT_SOURCE_DIR}/proto")
89
set(GENERATED_PROTOBUF_PATH "${CMAKE_BINARY_DIR}/generated/proto")
@@ -56,12 +57,15 @@ add_library(demo-proto ${DEMO_PB_H_FILE}
5657
${HEALTH_GRPC_PB_H_FILE})
5758

5859
target_link_libraries(demo-proto gRPC::grpc++ protobuf::libprotobuf)
59-
include_directories("${GENERATED_PROTOBUF_PATH}")
60+
include_directories("${GENERATED_PROTOBUF_PATH}" "${OPENTELEMETRY_CPP_INCLUDE_DIRS}")
6061

6162
add_executable(currencyservice src/server.cpp)
6263
add_dependencies(currencyservice demo-proto)
6364
target_link_libraries(
6465
currencyservice demo-proto protobuf::libprotobuf
65-
opentelemetry_trace opentelemetry_common opentelemetry_exporter_otlp_grpc opentelemetry_exporter_otlp_grpc_client opentelemetry_proto opentelemetry_otlp_recordable opentelemetry_resources gRPC::grpc++)
66+
${OPENTELEMETRY_CPP_LIBRARIES} opentelemetry_trace opentelemetry_common
67+
opentelemetry_exporter_otlp_grpc opentelemetry_exporter_otlp_grpc_client
68+
opentelemetry_proto opentelemetry_otlp_recordable opentelemetry_resources
69+
opentelemetry_metrics opentelemetry_exporter_otlp_grpc_metrics gRPC::grpc++)
6670

6771
install(TARGETS currencyservice DESTINATION bin)

src/currencyservice/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ FROM alpine as builder
1717
RUN apk update
1818
RUN apk add git cmake make g++ grpc-dev re2-dev protobuf-dev c-ares-dev
1919

20-
ARG OPENTELEMETRY_CPP_VERSION=1.8.1
20+
ARG OPENTELEMETRY_CPP_VERSION=1.8.2
2121

2222
RUN git clone https://github.com/open-telemetry/opentelemetry-cpp \
2323
&& cd opentelemetry-cpp/ \
2424
&& git checkout tags/v${OPENTELEMETRY_CPP_VERSION} -b v${OPENTELEMETRY_CPP_VERSION} \
2525
&& mkdir build \
2626
&& cd build \
27-
&& cmake .. -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DWITH_EXAMPLES=OFF -DWITH_OTLP=ON \
27+
&& cmake .. -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DWITH_EXAMPLES=OFF -DWITH_OTLP=ON -DWITH_OTLP_GRPC=ON \
2828
&& make -j$(nproc || sysctl -n hw.ncpu || echo 1) install && cd ../.. && rm -rf opentelemetry-cpp
2929

3030
COPY . /currencyservice
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "opentelemetry/exporters/otlp/otlp_grpc_metric_exporter_factory.h"
16+
#include "opentelemetry/metrics/provider.h"
17+
#include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader.h"
18+
#include "opentelemetry/sdk/metrics/meter.h"
19+
#include "opentelemetry/sdk/metrics/meter_provider.h"
20+
21+
// namespaces
22+
namespace common = opentelemetry::common;
23+
namespace metrics_api = opentelemetry::metrics;
24+
namespace metric_sdk = opentelemetry::sdk::metrics;
25+
namespace nostd = opentelemetry::nostd;
26+
namespace otlp_exporter = opentelemetry::exporter::otlp;
27+
28+
namespace
29+
{
30+
std::string version{ "1.3.0" };
31+
std::string name{ "app_currency" };
32+
std::string schema{ "https://opentelemetry.io/schemas/1.2.0" };
33+
34+
void initMeter()
35+
{
36+
// Build MetricExporter
37+
otlp_exporter::OtlpGrpcMetricExporterOptions otlpOptions;
38+
39+
// Configuration via environment variable not supported yet
40+
otlpOptions.endpoint = "otelcol:4317";
41+
otlpOptions.aggregation_temporality = metric_sdk::AggregationTemporality::kDelta;
42+
auto exporter = otlp_exporter::OtlpGrpcMetricExporterFactory::Create(otlpOptions);
43+
44+
// Build MeterProvider and Reader
45+
metric_sdk::PeriodicExportingMetricReaderOptions options;
46+
options.export_interval_millis = std::chrono::milliseconds(1000);
47+
options.export_timeout_millis = std::chrono::milliseconds(500);
48+
std::unique_ptr<metric_sdk::MetricReader> reader{
49+
new metric_sdk::PeriodicExportingMetricReader(std::move(exporter), options) };
50+
auto provider = std::shared_ptr<metrics_api::MeterProvider>(new metric_sdk::MeterProvider());
51+
auto p = std::static_pointer_cast<metric_sdk::MeterProvider>(provider);
52+
p->AddMetricReader(std::move(reader));
53+
metrics_api::Provider::SetMeterProvider(provider);
54+
}
55+
56+
nostd::unique_ptr<metrics_api::Counter<uint64_t>> initIntCounter()
57+
{
58+
std::string counter_name = name + "_counter";
59+
auto provider = metrics_api::Provider::GetMeterProvider();
60+
nostd::shared_ptr<metrics_api::Meter> meter = provider->GetMeter(name, version);
61+
auto int_counter = meter->CreateUInt64Counter(counter_name);
62+
return int_counter;
63+
}
64+
}

src/currencyservice/src/server.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "opentelemetry/trace/span_context_kv_iterable_view.h"
2323
#include "opentelemetry/baggage/baggage.h"
2424
#include "opentelemetry/nostd/string_view.h"
25+
#include "meter_common.h"
2526
#include "tracer_common.h"
2627

2728
#include <grpcpp/grpcpp.h>
@@ -48,9 +49,13 @@ using namespace opentelemetry::trace;
4849
using namespace opentelemetry::baggage;
4950
namespace context = opentelemetry::context;
5051

52+
namespace metrics_api = opentelemetry::metrics;
53+
namespace nostd = opentelemetry::nostd;
54+
5155
namespace
5256
{
53-
std::unordered_map<std::string, double> currency_conversion{
57+
std::unordered_map<std::string, double> currency_conversion
58+
{
5459
{"EUR", 1.0},
5560
{"USD", 1.1305},
5661
{"JPY", 126.40},
@@ -84,7 +89,9 @@ namespace
8489
{"SGD", 1.5349},
8590
{"THB", 36.012},
8691
{"ZAR", 16.0583},
87-
};
92+
};
93+
94+
nostd::unique_ptr<metrics_api::Counter<uint64_t>> currency_counter;
8895

8996
class HealthServer final : public grpc::health::v1::Health::Service
9097
{
@@ -202,6 +209,8 @@ class CurrencyService final : public oteldemo::CurrencyService::Service
202209
span->SetAttribute("app.currency.conversion.from", from_code);
203210
span->SetAttribute("app.currency.conversion.to", to_code);
204211

212+
CurrencyCounter(to_code);
213+
205214
// End the span
206215
span->AddEvent("Conversion successful, response sent back");
207216
span->SetStatus(StatusCode::kOk);
@@ -218,6 +227,13 @@ class CurrencyService final : public oteldemo::CurrencyService::Service
218227
}
219228
return Status::OK;
220229
}
230+
231+
void CurrencyCounter(const std::string& currency_code)
232+
{
233+
std::map<std::string, std::string> labels = { {"currency_code", currency_code} };
234+
auto labelkv = common::KeyValueIterableView<decltype(labels)>{ labels };
235+
currency_counter->Add(1, labelkv);
236+
}
221237
};
222238

223239
void RunServer(uint16_t port)
@@ -250,7 +266,9 @@ int main(int argc, char **argv) {
250266
std::cout << "Port: " << port << "\n";
251267

252268
initTracer();
269+
initMeter();
270+
currency_counter = initIntCounter();
253271
RunServer(port);
254272

255273
return 0;
256-
}
274+
}

0 commit comments

Comments
 (0)