After installing bazel, we’ll need to make two files in the same working directory as the metrics.cc
that is:

WORKSPACE

BUILD

WORKSPACE

Please add the content below to a file WORKSPACE:

http_archive(name="io_opencensus_cpp",
strip_prefix="opencensus-cpp-master",
urls=["https://github.com/census-instrumentation/opencensus-cpp/archive/master.zip"],
)# OpenCensus depends on Abseil so we have to explicitly to pull it in.
# This is how diamond dependencies are prevented.
http_archive(name="com_google_absl",
strip_prefix="abseil-cpp-master",
urls=["https://github.com/abseil/abseil-cpp/archive/master.zip"])

http_archive tells bazel to configure an “external repository” by downloading an archive via http, unpacking it, and removing the top-level directory as per “strip_prefix”

deps is a list of libraries that our binary depends on. Alongside linking these libraries, bazel will also
make their headers available to the compiler.

@io_opencensus_cpp refers to an external subrepository

//opencensus/stats is a directory path within that subdirectory

:metrics is the name of a “cc_library” target in that directory

From the compiler’s point of view, all of the sources and dependencies’ headers are merged into a single hierarchy i.e.

metrics.cc
absl/...
opencensus/...

Measures

We’ll collect some metrics by using OpenCensus’ measures:

Latency of every call

Length of each line

Number of lines

For each of the measurement that we make against each measure, we’ll tag them with the respective methods that processed them.

To enable that, we’ll create the measures:

#include"absl/strings/string_view.h"#include"opencensus/stats/stats.h"ABSL_CONST_INITconstabsl::string_viewkLatencyMeasureName="repl/latency";ABSL_CONST_INITconstabsl::string_viewkLineLengthsMeasureName="repl/line_lengths";// Treat Measures and TagKeys as singletons and initialize on
// demand in order to avoid initialization order issues.
opencensus::stats::MeasureDoubleLatencyMsMeasure(){staticconstautomeasure=opencensus::stats::MeasureDouble::Register(kLatencyMeasureName,"The latency in milliseconds","ms");returnmeasure;}opencensus::stats::MeasureInt64LineLengthsMeasure(){staticconstautomeasure=opencensus::stats::MeasureInt64::Register(kLineLengthsMeasureName,"The distributions of line lengths","By");returnmeasure;}

Record latencies against tags

which collectively then makes our helper functions getLine and processLine look like this:

std::stringgetLine(){absl::Timestart=absl::Now();std::stringinput;// Get the line
std::getline(std::cin,input);absl::Timeend=absl::Now();doublelatency_ms=absl::ToDoubleMilliseconds(end-start);// Record both measures at once.
opencensus::stats::Record({{LatencyMsMeasure(),latency_ms},{LineLengthsMeasure(),input.length()}},{{MethodKey(),"getLine"}});returninput;}std::stringprocessLine(conststd::string&in){absl::Timestart=absl::Now();std::stringout(in);for(autoit=out.begin();it!=out.end();it++){*it=std::toupper(*it);}absl::Timeend=absl::Now();doublelatency_ms=absl::ToDoubleMilliseconds(end-start);opencensus::stats::Record({{LatencyMsMeasure(),latency_ms}},{{MethodKey(),"processLine"}});returnout;}

Exporting to Prometheus

To examine our metrics, we’ll use Prometheus.

For assistance setting up Prometheus, click here for a guided codelab.

To use the Prometheus exporter for OpenCensus C++, we’ll need to update our BUILD, WORKSPACE and metrics.cc files
as below:

WORKSPACE

http_archive(name="io_opencensus_cpp",strip_prefix="opencensus-cpp-master",urls=["https://github.com/census-instrumentation/opencensus-cpp/archive/master.zip"],)# OpenCensus depends on Abseil so we have to explicitly to pull it in.# This is how diamond dependencies are prevented.http_archive(name="com_google_absl",strip_prefix="abseil-cpp-master",urls=["https://github.com/abseil/abseil-cpp/archive/master.zip"])# OpenCensus depends on jupp0r/prometheus-cpphttp_archive(name="com_github_jupp0r_prometheus_cpp",strip_prefix="prometheus-cpp-master",urls=["https://github.com/jupp0r/prometheus-cpp/archive/master.zip"],)load("@com_github_jupp0r_prometheus_cpp//:repositories.bzl","prometheus_cpp_repositories")prometheus_cpp_repositories()

End to end code

Our final code should now look like this

#include<iostream>#include"absl/strings/string_view.h"#include"absl/time/clock.h"#include"opencensus/exporters/stats/prometheus/prometheus_exporter.h"#include"opencensus/stats/stats.h"#include"opencensus/tags/tag_key.h"#include"prometheus/exposer.h"namespace{ABSL_CONST_INITconstabsl::string_viewkLatencyMeasureName="repl/latency";ABSL_CONST_INITconstabsl::string_viewkLineLengthsMeasureName="repl/line_lengths";// Treat Measures and TagKeys as singletons and initialize on
// demand in order to avoid initialization order issues.
opencensus::stats::MeasureDoubleLatencyMsMeasure(){staticconstautomeasure=opencensus::stats::MeasureDouble::Register(kLatencyMeasureName,"The latency in milliseconds","ms");returnmeasure;}opencensus::stats::MeasureInt64LineLengthsMeasure(){staticconstautomeasure=opencensus::stats::MeasureInt64::Register(kLineLengthsMeasureName,"The distributions of line lengths","By");returnmeasure;}opencensus::tags::TagKeyMethodKey(){staticconstautokey=opencensus::tags::TagKey::Register("method");returnkey;}voidregisterAsView(constopencensus::stats::ViewDescriptor&vd){opencensus::stats::Viewview(vd);vd.RegisterForExport();}std::stringgetLine(){absl::Timestart=absl::Now();std::stringinput;// Get the line
std::getline(std::cin,input);absl::Timeend=absl::Now();doublelatency_ms=absl::ToDoubleMilliseconds(end-start);// Record both measures at once.
opencensus::stats::Record({{LatencyMsMeasure(),latency_ms},{LineLengthsMeasure(),input.length()}},{{MethodKey(),"getLine"}});returninput;}std::stringprocessLine(conststd::string&in){absl::Timestart=absl::Now();std::stringout(in);for(autoit=out.begin();it!=out.end();it++){*it=std::toupper(*it);}absl::Timeend=absl::Now();doublelatency_ms=absl::ToDoubleMilliseconds(end-start);opencensus::stats::Record({{LatencyMsMeasure(),latency_ms}},{{MethodKey(),"processLine"}});returnout;}}// namespace
intmain(intargc,char**argv){// Firstly enable the Prometheus exporter
autoexporter=std::make_shared<opencensus::exporters::stats::PrometheusExporter>();// Expose Prometheus on :8888
prometheus::Exposerexposer("127.0.0.1:8888");exposer.RegisterCollectable(exporter);// Register Measures.
LatencyMsMeasure();LineLengthsMeasure();// Let's create the various views
// 1. Latency view
constopencensus::stats::ViewDescriptorlatency_view=opencensus::stats::ViewDescriptor().set_name("ocquickstart.io/latency").set_description("The various methods' latencies in milliseconds").set_measure(kLatencyMeasureName).set_aggregation(opencensus::stats::Aggregation::Distribution(opencensus::stats::BucketBoundaries::Explicit({0,25,50,75,100,200,400,600,800,1000,2000,4000,6000}))).add_column(MethodKey());// 2. Lines count: just a count aggregation on the latency measurement
constopencensus::stats::ViewDescriptorlines_count_view=opencensus::stats::ViewDescriptor().set_name("ocquickstart.io/lines_in").set_description("The number of lines read in").set_measure(kLineLengthsMeasureName).set_aggregation(opencensus::stats::Aggregation::Count()).add_column(MethodKey());// 3. The line lengths:
constopencensus::stats::ViewDescriptorline_lengths_view=opencensus::stats::ViewDescriptor().set_name("ocquickstart.io/line_lengths").set_description("The length of the lines read in").set_measure(kLineLengthsMeasureName).set_aggregation(opencensus::stats::Aggregation::Distribution(opencensus::stats::BucketBoundaries::Explicit({0,5,10,15,20,40,60,80,100,200,400,600,800,1000}))).add_column(MethodKey());// Register the views to enable stats aggregation.
registerAsView(latency_view);registerAsView(lines_count_view);registerAsView(line_lengths_view);while(1){std::cout<<"\n> ";std::stringinput=getLine();std::stringupper=processLine(input);std::cout<<"< "<<upper<<std::endl;}}

which will expose a Prometheus scrape endpoint at localhost:8888.
Before we run it, we’ll need to setup our Prometheus configuration file config.yaml