Skip to content

Commit

Permalink
[CurrencyService] Add C++ Metrics (#759)
Browse files Browse the repository at this point in the history
* Add cpp metrics

* Add IntCounter to CurrencyService

* changelog

* changelog

* Fix indentantion

* Add line break

* Remove unnecessary comma

* Remove unnecessary includes

* Apply suggestions
  • Loading branch information
julianocosta89 authored Mar 1, 2023
1 parent 5a3f298 commit a60ca4f
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ tls_certificate_check and bump to OTP-25
([#756](https://github.com/open-telemetry/opentelemetry-demo/pull/756))
* Bump up OTEL Java Agent version to 1.23.0
([#757](https://github.com/open-telemetry/opentelemetry-demo/pull/757))
* Add counter metric to currency service (C++)
([#759](https://github.com/open-telemetry/opentelemetry-demo/issues/759))
* Use browserDetector to populate browser info to frontend-web telemetry
([#760](https://github.com/open-telemetry/opentelemetry-demo/pull/760))

Expand Down
2 changes: 2 additions & 0 deletions src/currencyservice/.dockerignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
client.js
node_modules/
build/
out/
12 changes: 8 additions & 4 deletions src/currencyservice/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
cmake_minimum_required(VERSION 3.1)
project(currency-service)

find_package(Protobuf)
find_package(gRPC)
find_package(Protobuf REQUIRED)
find_package(gRPC CONFIG REQUIRED)
find_package(opentelemetry-cpp CONFIG REQUIRED)

set(PROTO_PATH "${CMAKE_CURRENT_SOURCE_DIR}/proto")
set(GENERATED_PROTOBUF_PATH "${CMAKE_BINARY_DIR}/generated/proto")
Expand Down Expand Up @@ -56,12 +57,15 @@ add_library(demo-proto ${DEMO_PB_H_FILE}
${HEALTH_GRPC_PB_H_FILE})

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

add_executable(currencyservice src/server.cpp)
add_dependencies(currencyservice demo-proto)
target_link_libraries(
currencyservice demo-proto protobuf::libprotobuf
opentelemetry_trace opentelemetry_common opentelemetry_exporter_otlp_grpc opentelemetry_exporter_otlp_grpc_client opentelemetry_proto opentelemetry_otlp_recordable opentelemetry_resources gRPC::grpc++)
${OPENTELEMETRY_CPP_LIBRARIES} opentelemetry_trace opentelemetry_common
opentelemetry_exporter_otlp_grpc opentelemetry_exporter_otlp_grpc_client
opentelemetry_proto opentelemetry_otlp_recordable opentelemetry_resources
opentelemetry_metrics opentelemetry_exporter_otlp_grpc_metrics gRPC::grpc++)

install(TARGETS currencyservice DESTINATION bin)
4 changes: 2 additions & 2 deletions src/currencyservice/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ FROM alpine as builder
RUN apk update
RUN apk add git cmake make g++ grpc-dev re2-dev protobuf-dev c-ares-dev

ARG OPENTELEMETRY_CPP_VERSION=1.8.1
ARG OPENTELEMETRY_CPP_VERSION=1.8.2

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

COPY . /currencyservice
Expand Down
64 changes: 64 additions & 0 deletions src/currencyservice/src/meter_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright The 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.

#include "opentelemetry/exporters/otlp/otlp_grpc_metric_exporter_factory.h"
#include "opentelemetry/metrics/provider.h"
#include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader.h"
#include "opentelemetry/sdk/metrics/meter.h"
#include "opentelemetry/sdk/metrics/meter_provider.h"

// namespaces
namespace common = opentelemetry::common;
namespace metrics_api = opentelemetry::metrics;
namespace metric_sdk = opentelemetry::sdk::metrics;
namespace nostd = opentelemetry::nostd;
namespace otlp_exporter = opentelemetry::exporter::otlp;

namespace
{
std::string version{ "1.3.0" };
std::string name{ "app_currency" };
std::string schema{ "https://opentelemetry.io/schemas/1.2.0" };

void initMeter()
{
// Build MetricExporter
otlp_exporter::OtlpGrpcMetricExporterOptions otlpOptions;

// Configuration via environment variable not supported yet
otlpOptions.endpoint = "otelcol:4317";
otlpOptions.aggregation_temporality = metric_sdk::AggregationTemporality::kDelta;
auto exporter = otlp_exporter::OtlpGrpcMetricExporterFactory::Create(otlpOptions);

// Build MeterProvider and Reader
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());
auto p = std::static_pointer_cast<metric_sdk::MeterProvider>(provider);
p->AddMetricReader(std::move(reader));
metrics_api::Provider::SetMeterProvider(provider);
}

nostd::unique_ptr<metrics_api::Counter<uint64_t>> initIntCounter()
{
std::string counter_name = name + "_counter";
auto provider = metrics_api::Provider::GetMeterProvider();
nostd::shared_ptr<metrics_api::Meter> meter = provider->GetMeter(name, version);
auto int_counter = meter->CreateUInt64Counter(counter_name);
return int_counter;
}
}
24 changes: 21 additions & 3 deletions src/currencyservice/src/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "opentelemetry/trace/span_context_kv_iterable_view.h"
#include "opentelemetry/baggage/baggage.h"
#include "opentelemetry/nostd/string_view.h"
#include "meter_common.h"
#include "tracer_common.h"

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

namespace metrics_api = opentelemetry::metrics;
namespace nostd = opentelemetry::nostd;

namespace
{
std::unordered_map<std::string, double> currency_conversion{
std::unordered_map<std::string, double> currency_conversion
{
{"EUR", 1.0},
{"USD", 1.1305},
{"JPY", 126.40},
Expand Down Expand Up @@ -84,7 +89,9 @@ namespace
{"SGD", 1.5349},
{"THB", 36.012},
{"ZAR", 16.0583},
};
};

nostd::unique_ptr<metrics_api::Counter<uint64_t>> currency_counter;

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

CurrencyCounter(to_code);

// End the span
span->AddEvent("Conversion successful, response sent back");
span->SetStatus(StatusCode::kOk);
Expand All @@ -218,6 +227,13 @@ class CurrencyService final : public oteldemo::CurrencyService::Service
}
return Status::OK;
}

void CurrencyCounter(const std::string& currency_code)
{
std::map<std::string, std::string> labels = { {"currency_code", currency_code} };
auto labelkv = common::KeyValueIterableView<decltype(labels)>{ labels };
currency_counter->Add(1, labelkv);
}
};

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

initTracer();
initMeter();
currency_counter = initIntCounter();
RunServer(port);

return 0;
}
}

0 comments on commit a60ca4f

Please sign in to comment.