From 8ab1570f728f11011d9a0c2265d22610ec37c363 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Thu, 15 Nov 2018 14:32:04 -0500 Subject: [PATCH 01/36] Expose API server with metrics in prometheus format. --- .gitmodules | 3 ++ lib/prometheus-cpp | 1 + src/.gitignore | 1 + src/Makefile | 41 +++++++++++++++++----- src/agent.cc | 5 +-- src/agent.h | 7 ++++ src/api_server.cc | 32 ++++++++++++++++- src/api_server.h | 6 ++++ test/Makefile | 26 +++++++++----- test/api_server_unittest.cc | 70 +++++++++++++++++++++++++++++++++++++ 10 files changed, 173 insertions(+), 19 deletions(-) create mode 160000 lib/prometheus-cpp diff --git a/.gitmodules b/.gitmodules index 4aab48e6..f11a5d68 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ path = lib/googletest url = https://github.com/google/googletest ignore = dirty +[submodule "lib/prometheus-cpp"] + path = lib/prometheus-cpp + url = https://github.com/jupp0r/prometheus-cpp diff --git a/lib/prometheus-cpp b/lib/prometheus-cpp new file mode 160000 index 00000000..e14ba416 --- /dev/null +++ b/lib/prometheus-cpp @@ -0,0 +1 @@ +Subproject commit e14ba416e9bcde4439a3bf14fbdb93ef35321ae4 diff --git a/src/.gitignore b/src/.gitignore index 4dee5759..ef02ec57 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,4 +1,5 @@ init-submodules build-cpp-netlib build-yaml-cpp +build-prometheus-cpp metadatad diff --git a/src/Makefile b/src/Makefile index 9fd40c7f..37aa9135 100644 --- a/src/Makefile +++ b/src/Makefile @@ -23,7 +23,10 @@ NETWORK_URI_DIR=$(CPP_NETLIB_DIR)/deps/uri NETWORK_URI_LIBDIR=$(NETWORK_URI_DIR)/src YAML_CPP_DIR=$(LIBDIR)/yaml-cpp YAML_CPP_LIBDIR=$(YAML_CPP_DIR) -SUBMODULE_DIRS=$(CPP_NETLIB_DIR) $(YAML_CPP_DIR) +PROMETHEUS_CPP_DIR=$(LIBDIR)/prometheus-cpp +PROMETHEUS_CPP_LIBDIR=$(PROMETHEUS_CPP_DIR) +PROMETHEUS_CPP_CORE_LIBDIR=$(PROMETHEUS_CPP_LIBDIR)/core +SUBMODULE_DIRS=$(CPP_NETLIB_DIR) $(YAML_CPP_DIR) $(PROMETHEUS_CPP_DIR) GIT=git GIT_VERSION=$(shell $(GIT) --version | grep -oh '[0-9]\+\.[0-9]\+\.[0-9]\+') @@ -33,14 +36,16 @@ CMAKE=cmake CPPFLAGS=\ -DAGENT_VERSION='$(PKG_VERSION)-$(PKG_RELEASE)' \ -DENABLE_DOCKER_METADATA \ - -I$(CPP_NETLIB_DIR) -I$(NETWORK_URI_DIR)/include -I$(YAML_CPP_DIR)/include + -I$(CPP_NETLIB_DIR) -I$(NETWORK_URI_DIR)/include -I$(YAML_CPP_DIR)/include \ + -I$(PROMETHEUS_CPP_CORE_LIBDIR)/include CXXFLAGS=\ -std=c++11 -g -pthread -Wno-write-strings -Wno-deprecated -LDFLAGS=-L$(CPP_NETLIB_LIBDIR) -L$(NETWORK_URI_LIBDIR) -L$(YAML_CPP_LIBDIR) +LDFLAGS=-L$(CPP_NETLIB_LIBDIR) -L$(NETWORK_URI_LIBDIR) -L$(YAML_CPP_LIBDIR) \ + -L$(PROMETHEUS_CPP_CORE_LIBDIR) LDLIBS=\ -lcppnetlib-client-connections -lcppnetlib-server-parsers -lnetwork-uri \ -lboost_program_options -lboost_system -lboost_thread -lboost_filesystem \ - -lpthread -lyajl -lssl -lcrypto -lyaml-cpp + -lpthread -lyajl -lssl -lcrypto -lyaml-cpp -lprometheus-cpp-core SED_EXTRA=-e 's/-Wall/-Wall -Wno-deprecated/' UNAME_S=$(shell uname -s) @@ -88,7 +93,9 @@ CPP_NETLIB_LIBS=\ $(NETWORK_URI_LIBDIR)/libnetwork-uri.a YAML_CPP_LIBS=\ $(YAML_CPP_LIBDIR)/libyaml-cpp.a -LIBS=$(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) +PROMETHEUS_CPP_LIBS=\ + $(PROMETHEUS_CPP_CORE_LIBDIR)/libprometheus-cpp-core.a +LIBS=$(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) $(PROMETHEUS_CPP_LIBS) sbindir=/opt/stackdriver/metadata/sbin INSTALL=/usr/bin/install @@ -167,7 +174,7 @@ clean: $(RM) metadatad $(OBJS) purge: clean - $(RM) -r init-submodules build-cpp-netlib build-yaml-cpp + $(RM) -r init-submodules build-cpp-netlib build-yaml-cpp build-prometheus-cpp (cd .. && git submodule deinit -f $(SUBMODULE_DIRS:../%=%)) init-submodules: @@ -183,6 +190,8 @@ ifneq ($(findstring $(GIT_VERSION),2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.8 deps/*/.git cd $(CPP_NETLIB_DIR) && $(SED_I) -e 's@/src/.git/@../../../../../../../.git/@' \ libs/network/doc/_ext/breathe/.git + cd $(PROMETHEUS_CPP_DIR) && $(SED_I) -e 's@/src/.git/@../../../../.git/@' \ + 3rdparty/*/.git endif touch init-submodules @@ -217,12 +226,28 @@ build-yaml-cpp: $(YAML_CPP_DIR)/Makefile $(MAKE) touch build-yaml-cpp +$(PROMETHEUS_CPP_DIR)/Makefile: init-submodules + cd $(PROMETHEUS_CPP_DIR) && \ + $(CMAKE) -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS=-std=c++11 \ + -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ \ + -DENABLE_PUSH=OFF -DENABLE_PULL=OFF -DENABLE_COMPRESSION=OFF \ + -DENABLE_TESTING=OFF + +$(PROMETHEUS_CPP_LIBS): build-prometheus-cpp + +build-prometheus-cpp: $(PROMETHEUS_CPP_DIR)/Makefile + cd $(PROMETHEUS_CPP_DIR) && \ + $(MAKE) + touch build-prometheus-cpp + cpp-netlib: $(CPP_NETLIB_LIBS) yaml-cpp: $(YAML_CPP_LIBS) -submodules: cpp-netlib yaml-cpp +prometheus-cpp: $(PROMETHEUS_CPP_LIBS) + +submodules: cpp-netlib yaml-cpp prometheus-cpp all: submodules metadatad -.PHONY: all submodules cpp-netlib yaml-cpp purge clean install deb rpm +.PHONY: all submodules cpp-netlib yaml-cpp prometheus-cpp purge clean install deb rpm diff --git a/src/agent.cc b/src/agent.cc index 2aaac90c..407586ad 100644 --- a/src/agent.cc +++ b/src/agent.cc @@ -24,13 +24,14 @@ namespace google { MetadataAgent::MetadataAgent(const Configuration& config) - : config_(config), store_(config_), health_checker_(config, store_) {} + : config_(config), store_(config_), health_checker_(config, store_), + registry_(std::make_shared()) {} MetadataAgent::~MetadataAgent() {} void MetadataAgent::Start() { metadata_api_server_.reset(new MetadataApiServer( - config_, &health_checker_, store_, config_.MetadataApiNumThreads(), + config_, &health_checker_, registry_, store_, config_.MetadataApiNumThreads(), config_.MetadataApiBindAddress(), config_.MetadataApiPort())); reporter_.reset(new MetadataReporter( config_, &store_, config_.MetadataReporterIntervalSeconds())); diff --git a/src/agent.h b/src/agent.h index 45d9fe19..7a5efc35 100644 --- a/src/agent.h +++ b/src/agent.h @@ -17,6 +17,7 @@ #define AGENT_H_ #include +#include #include "store.h" #include "health_checker.h" @@ -60,6 +61,10 @@ class MetadataAgent { return &health_checker_; } + std::shared_ptr prometheus_registry() { + return registry_; + } + private: const Configuration& config_; @@ -68,6 +73,8 @@ class MetadataAgent { HealthChecker health_checker_; + std::shared_ptr registry_; + // The Metadata API server. std::unique_ptr metadata_api_server_; // The metadata reporter. diff --git a/src/api_server.cc b/src/api_server.cc index 71642f57..9c0fb8d5 100644 --- a/src/api_server.cc +++ b/src/api_server.cc @@ -17,6 +17,7 @@ #include "api_server.h" #include +#include #include "configuration.h" #include "health_checker.h" @@ -69,10 +70,12 @@ void MetadataApiServer::Dispatcher::log(const HttpServer::string_type& info) con MetadataApiServer::MetadataApiServer(const Configuration& config, const HealthChecker* health_checker, + const std::shared_ptr collectable, const MetadataStore& store, int server_threads, const std::string& host, int port) - : config_(config), health_checker_(health_checker), store_(store), + : config_(config), health_checker_(health_checker), collectable_(collectable), + store_(store), dispatcher_({ {{"GET", "/monitoredResource/"}, [=](const HttpServer::request& request, @@ -84,6 +87,11 @@ MetadataApiServer::MetadataApiServer(const Configuration& config, std::shared_ptr conn) { HandleHealthz(request, conn); }}, + {{"GET", "/metrics"}, + [=](const HttpServer::request& request, + std::shared_ptr conn) { + HandleMetrics(request, conn); + }}, }, config_.VerboseLogging()), server_( HttpServer::options(dispatcher_) @@ -200,4 +208,26 @@ void MetadataApiServer::HandleHealthz( } } +void MetadataApiServer::HandleMetrics( + const HttpServer::request& request, + std::shared_ptr conn) { + std::string response = SerializeMetricsToPrometheusTextFormat(); + conn->set_status(HttpServer::connection::ok); + conn->set_headers(std::map({ + {"Connection", "close"}, + {"Content-Length", std::to_string(response.size())}, + {"Content-Type", "application/json"}, + })); + conn->write(response); +} + +std::string MetadataApiServer::SerializeMetricsToPrometheusTextFormat() const { + if (!collectable_) { + return ""; + } + + prometheus::TextSerializer text_serializer; + return std::move(text_serializer.Serialize(collectable_->Collect())); +} + } diff --git a/src/api_server.h b/src/api_server.h index 687e8e8b..588369dd 100644 --- a/src/api_server.h +++ b/src/api_server.h @@ -18,6 +18,7 @@ #define BOOST_NETWORK_ENABLE_HTTPS #include +#include #include #include #include @@ -43,6 +44,7 @@ class MetadataApiServer { public: MetadataApiServer(const Configuration& config, const HealthChecker* health_checker, + const std::shared_ptr collectable, const MetadataStore& store, int server_threads, const std::string& host, int port); ~MetadataApiServer(); @@ -77,6 +79,9 @@ class MetadataApiServer { std::shared_ptr conn); void HandleHealthz(const HttpServer::request& request, std::shared_ptr conn); + void HandleMetrics(const HttpServer::request& request, + std::shared_ptr conn); + std::string SerializeMetricsToPrometheusTextFormat() const; const Configuration& config_; const HealthChecker* health_checker_; @@ -84,6 +89,7 @@ class MetadataApiServer { Dispatcher dispatcher_; HttpServer server_; std::vector server_pool_; + std::shared_ptr collectable_; }; } diff --git a/test/Makefile b/test/Makefile index 9a86575b..ddc535ce 100644 --- a/test/Makefile +++ b/test/Makefile @@ -32,23 +32,31 @@ NETWORK_URI_DIR=$(CPP_NETLIB_DIR)/deps/uri NETWORK_URI_LIBDIR=$(NETWORK_URI_DIR)/src YAML_CPP_DIR=$(LIBDIR)/yaml-cpp YAML_CPP_LIBDIR=$(YAML_CPP_DIR) +PROMETHEUS_CPP_DIR=$(LIBDIR)/prometheus-cpp +PROMETHEUS_CPP_LIBDIR=$(PROMETHEUS_CPP_DIR) +PROMETHEUS_CPP_CORE_LIBDIR=$(PROMETHEUS_CPP_LIBDIR)/core CPP_NETLIB_LIBS=\ $(CPP_NETLIB_LIBDIR)/libcppnetlib-client-connections.a \ $(CPP_NETLIB_LIBDIR)/libcppnetlib-server-parsers.a \ $(NETWORK_URI_LIBDIR)/libnetwork-uri.a YAML_CPP_LIBS=$(YAML_CPP_LIBDIR)/libyaml-cpp.a +PROMETHEUS_CPP_LIBS=\ + $(PROMETHEUS_CPP_CORE_LIBDIR)/libprometheus-cpp-core.a CPPFLAGS+= \ -isystem $(GTEST_DIR)/include -I$(GMOCK_DIR)/include \ - -I$(CPP_NETLIB_DIR) -I$(NETWORK_URI_DIR)/include -I$(YAML_CPP_DIR)/include + -I$(CPP_NETLIB_DIR) -I$(NETWORK_URI_DIR)/include -I$(YAML_CPP_DIR)/include \ + -I$(PROMETHEUS_CPP_CORE_LIBDIR)/include CXXFLAGS=\ -std=c++11 -g -pthread -Wno-write-strings -Wno-deprecated -LDFLAGS=-L$(CPP_NETLIB_LIBDIR) -L$(NETWORK_URI_LIBDIR) -L$(YAML_CPP_LIBDIR) +LDFLAGS=-L$(CPP_NETLIB_LIBDIR) -L$(NETWORK_URI_LIBDIR) -L$(YAML_CPP_LIBDIR) \ + -L$(PROMETHEUS_CPP_CORE_LIBDIR) LDLIBS=\ -lcppnetlib-client-connections -lcppnetlib-server-parsers -lnetwork-uri \ -lboost_program_options -lboost_system -lboost_thread -lboost_filesystem \ - -lboost_regex -lpthread -lyajl -lssl -lcrypto -lyaml-cpp + -lboost_regex -lpthread -lyajl -lssl -lcrypto -lyaml-cpp \ + -lprometheus-cpp-core UNAME_S=$(shell uname -s) ifeq ($(UNAME_S),Darwin) @@ -115,14 +123,16 @@ init-submodules: $(SRC_DIR)/init-submodules: cd $(SRC_DIR) && $(MAKE) $(@:$(SRC_DIR)/%=%) -$(SRC_DIR)/build-cpp-netlib $(SRC_DIR)/build-yaml-cpp: $(SRC_DIR)/init-submodules +$(SRC_DIR)/build-cpp-netlib $(SRC_DIR)/build-yaml-cpp $(SRC_DIR)/build-prometheus-cpp: $(SRC_DIR)/init-submodules cd $(SRC_DIR) && $(MAKE) $(@:$(SRC_DIR)/%=%) $(CPP_NETLIB_LIBS): $(SRC_DIR)/build-cpp-netlib $(YAML_CPP_LIBS): $(SRC_DIR)/build-yaml-cpp -$(SRC_DIR)/%.o: $(SRC_DIR)/build-cpp-netlib $(SRC_DIR)/build-yaml-cpp $(SRC_DIR)/%.cc +$(PROMETHEUS_CPP_LIBS): $(SRC_DIR)/build-prometheus-cpp + +$(SRC_DIR)/%.o: $(SRC_DIR)/build-cpp-netlib $(SRC_DIR)/build-yaml-cpp $(SRC_DIR)/build-prometheus-cpp $(SRC_DIR)/%.cc cd $(SRC_DIR) && $(MAKE) $(@:$(SRC_DIR)/%=%) $(GTEST_SOURCEDIR)/gtest-all.cc: init-submodules @@ -139,14 +149,14 @@ gmock_main.o: $(GMOCK_SOURCEDIR)/gmock_main.cc $(GTEST_LIB): gtest-all.o gmock-all.o gmock_main.o $(AR) $(ARFLAGS) $@ $^ -$(TESTS): $(GTEST_LIB) $(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) +$(TESTS): $(GTEST_LIB) $(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) $(PROMETHEUS_CPP_LIBS) # All unittest objects depend on GTEST_LIB. # Some headers need CPP_NETLIB_LIBS and YAML_CPP_LIBS. -$(TESTS:%=%.o): $(GTEST_LIB) $(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) +$(TESTS:%=%.o): $(GTEST_LIB) $(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) $(PROMETHEUS_CPP_LIBS) api_server_unittest: api_server_unittest.o $(SRC_DIR)/api_server.o $(SRC_DIR)/configuration.o $(SRC_DIR)/store.o $(SRC_DIR)/json.o $(SRC_DIR)/resource.o $(SRC_DIR)/logging.o $(SRC_DIR)/time.o $(SRC_DIR)/health_checker.o - $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ + $(CXX) $(LDFLAGS) $^ $(LDLIBS) -lprometheus-cpp-core -o $@ base64_unittest: base64_unittest.o $(SRC_DIR)/base64.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ configuration_unittest: configuration_unittest.o $(SRC_DIR)/configuration.o diff --git a/test/api_server_unittest.cc b/test/api_server_unittest.cc index 5c82ab2a..2f61de98 100644 --- a/test/api_server_unittest.cc +++ b/test/api_server_unittest.cc @@ -19,11 +19,19 @@ #include "../src/store.h" #include "gtest/gtest.h" +#include + namespace google { class ApiServerTest : public ::testing::Test { protected: using Dispatcher = MetadataApiServer::Dispatcher; + + static std::string SerializeMetricsToPrometheusTextFormat( + const google::MetadataApiServer& api_server) { + return api_server.SerializeMetricsToPrometheusTextFormat(); + } + std::unique_ptr CreateDispatcher( const std::map, std::function>& handlers) { @@ -95,4 +103,66 @@ TEST_F(ApiServerTest, DispatcherSubstringCheck) { InvokeDispatcher(dispatcher, "GET", "/testPath/subPath/"); EXPECT_TRUE(handler_called); } + +TEST_F(ApiServerTest, SerializationToPrometheusTextForNullPtr) { + google::Configuration config; + google::MetadataApiServer server( + config, + /*heapth_checker=*/nullptr, + /*std::shared_ptr=*/nullptr, + MetadataStore(config), + 0, "", 8080); + EXPECT_EQ("", SerializeMetricsToPrometheusTextFormat(server)); +} + +TEST_F(ApiServerTest, SerializationToPrometheusTextForEmptyRegistry) { + google::Configuration config; + std::shared_ptr registry; + google::MetadataApiServer server( + config, /*heapth_checker=*/nullptr, registry, + MetadataStore(config), + 0, "", 8080); + EXPECT_EQ("", SerializeMetricsToPrometheusTextFormat(server)); +} + +TEST_F(ApiServerTest, SerializationToPrometheusTextForNonEmptyRegistry) { + google::Configuration config; + auto registry = std::make_shared(); + prometheus::BuildCounter() + .Name("test_metric_counter") + .Help("help on test_metric_counter") + .Register(*registry); + std::string expected_result = + "# HELP test_metric_counter help on test_metric_counter\n" + "# TYPE test_metric_counter counter\n"; + google::MetadataApiServer server( + config, /*heapth_checker=*/nullptr, registry, + MetadataStore(config), + 0, "", 8080); + EXPECT_EQ(expected_result, SerializeMetricsToPrometheusTextFormat(server)); +} + + +TEST_F(ApiServerTest, SerializationToPrometheusTextWithLabeledCounter) { + google::Configuration config; + auto registry = std::make_shared(); + auto& counter_family = prometheus::BuildCounter() + .Name("test_metric_counter") + .Help("help on test_metric_counter") + .Register(*registry); + + // Add a labeled counter + counter_family.Add({{"foo", "bar"}}); + + std::string expected_result = + "# HELP test_metric_counter help on test_metric_counter\n" + "# TYPE test_metric_counter counter\n" + "test_metric_counter{foo=\"bar\"} 0.000000\n"; + google::MetadataApiServer server( + config, /*heapth_checker=*/nullptr, registry, + MetadataStore(config), + 0, "", 8080); + EXPECT_EQ(expected_result, SerializeMetricsToPrometheusTextFormat(server)); +} + } // namespace google From 2427bcebfd07e5ff416a187564ba068f3b135c85 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Fri, 16 Nov 2018 11:34:53 -0500 Subject: [PATCH 02/36] Fix indentation and line wrapping. --- src/api_server.cc | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/api_server.cc b/src/api_server.cc index 9c0fb8d5..6113cd83 100644 --- a/src/api_server.cc +++ b/src/api_server.cc @@ -68,14 +68,16 @@ void MetadataApiServer::Dispatcher::log(const HttpServer::string_type& info) con } -MetadataApiServer::MetadataApiServer(const Configuration& config, - const HealthChecker* health_checker, - const std::shared_ptr collectable, - const MetadataStore& store, - int server_threads, - const std::string& host, int port) - : config_(config), health_checker_(health_checker), collectable_(collectable), - store_(store), +MetadataApiServer::MetadataApiServer( + const Configuration& config, + const HealthChecker* health_checker, + const std::shared_ptr collectable, + const MetadataStore& store, + int server_threads, + const std::string& host, + int port) + : config_(config), health_checker_(health_checker), + collectable_(collectable), store_(store), dispatcher_({ {{"GET", "/monitoredResource/"}, [=](const HttpServer::request& request, From 7b3f07e39417588a3e8a9a2d3c609056bb72c048 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Fri, 16 Nov 2018 11:35:32 -0500 Subject: [PATCH 03/36] Remove a redundant test. --- test/api_server_unittest.cc | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/test/api_server_unittest.cc b/test/api_server_unittest.cc index 2f61de98..5cae4a53 100644 --- a/test/api_server_unittest.cc +++ b/test/api_server_unittest.cc @@ -125,24 +125,6 @@ TEST_F(ApiServerTest, SerializationToPrometheusTextForEmptyRegistry) { EXPECT_EQ("", SerializeMetricsToPrometheusTextFormat(server)); } -TEST_F(ApiServerTest, SerializationToPrometheusTextForNonEmptyRegistry) { - google::Configuration config; - auto registry = std::make_shared(); - prometheus::BuildCounter() - .Name("test_metric_counter") - .Help("help on test_metric_counter") - .Register(*registry); - std::string expected_result = - "# HELP test_metric_counter help on test_metric_counter\n" - "# TYPE test_metric_counter counter\n"; - google::MetadataApiServer server( - config, /*heapth_checker=*/nullptr, registry, - MetadataStore(config), - 0, "", 8080); - EXPECT_EQ(expected_result, SerializeMetricsToPrometheusTextFormat(server)); -} - - TEST_F(ApiServerTest, SerializationToPrometheusTextWithLabeledCounter) { google::Configuration config; auto registry = std::make_shared(); From 955a061bf9d779bf8ff9dcf9ef6bdd90bf136565 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Fri, 16 Nov 2018 11:39:12 -0500 Subject: [PATCH 04/36] Make indentation consistent in Makefile. --- src/Makefile | 7 +++++-- test/Makefile | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Makefile b/src/Makefile index 37aa9135..efebac9b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -40,8 +40,11 @@ CPPFLAGS=\ -I$(PROMETHEUS_CPP_CORE_LIBDIR)/include CXXFLAGS=\ -std=c++11 -g -pthread -Wno-write-strings -Wno-deprecated -LDFLAGS=-L$(CPP_NETLIB_LIBDIR) -L$(NETWORK_URI_LIBDIR) -L$(YAML_CPP_LIBDIR) \ - -L$(PROMETHEUS_CPP_CORE_LIBDIR) +LDFLAGS=\ + -L$(CPP_NETLIB_LIBDIR) \ + -L$(NETWORK_URI_LIBDIR) \ + -L$(YAML_CPP_LIBDIR) \ + -L$(PROMETHEUS_CPP_CORE_LIBDIR) LDLIBS=\ -lcppnetlib-client-connections -lcppnetlib-server-parsers -lnetwork-uri \ -lboost_program_options -lboost_system -lboost_thread -lboost_filesystem \ diff --git a/test/Makefile b/test/Makefile index ddc535ce..4bebdcfe 100644 --- a/test/Makefile +++ b/test/Makefile @@ -50,8 +50,11 @@ CPPFLAGS+= \ -I$(PROMETHEUS_CPP_CORE_LIBDIR)/include CXXFLAGS=\ -std=c++11 -g -pthread -Wno-write-strings -Wno-deprecated -LDFLAGS=-L$(CPP_NETLIB_LIBDIR) -L$(NETWORK_URI_LIBDIR) -L$(YAML_CPP_LIBDIR) \ - -L$(PROMETHEUS_CPP_CORE_LIBDIR) +LDFLAGS=\ + -L$(CPP_NETLIB_LIBDIR) \ + -L$(NETWORK_URI_LIBDIR) \ + -L$(YAML_CPP_LIBDIR) \ + -L$(PROMETHEUS_CPP_CORE_LIBDIR) LDLIBS=\ -lcppnetlib-client-connections -lcppnetlib-server-parsers -lnetwork-uri \ -lboost_program_options -lboost_system -lboost_thread -lboost_filesystem \ From 12b4a86aabcd26e73df5df031b976369e0ef93fa Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Fri, 16 Nov 2018 15:15:17 -0500 Subject: [PATCH 05/36] Fix typo. --- test/api_server_unittest.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/api_server_unittest.cc b/test/api_server_unittest.cc index 5cae4a53..02c9f12c 100644 --- a/test/api_server_unittest.cc +++ b/test/api_server_unittest.cc @@ -108,7 +108,7 @@ TEST_F(ApiServerTest, SerializationToPrometheusTextForNullPtr) { google::Configuration config; google::MetadataApiServer server( config, - /*heapth_checker=*/nullptr, + /*health_checker=*/nullptr, /*std::shared_ptr=*/nullptr, MetadataStore(config), 0, "", 8080); @@ -119,7 +119,7 @@ TEST_F(ApiServerTest, SerializationToPrometheusTextForEmptyRegistry) { google::Configuration config; std::shared_ptr registry; google::MetadataApiServer server( - config, /*heapth_checker=*/nullptr, registry, + config, /*health_checker=*/nullptr, registry, MetadataStore(config), 0, "", 8080); EXPECT_EQ("", SerializeMetricsToPrometheusTextFormat(server)); @@ -141,7 +141,7 @@ TEST_F(ApiServerTest, SerializationToPrometheusTextWithLabeledCounter) { "# TYPE test_metric_counter counter\n" "test_metric_counter{foo=\"bar\"} 0.000000\n"; google::MetadataApiServer server( - config, /*heapth_checker=*/nullptr, registry, + config, /*health_checker=*/nullptr, registry, MetadataStore(config), 0, "", 8080); EXPECT_EQ(expected_result, SerializeMetricsToPrometheusTextFormat(server)); From 5c065daf14a6ea1ef7d705fb02350e1dc8c1d027 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Wed, 21 Nov 2018 16:10:15 -0500 Subject: [PATCH 06/36] Instrument first metric with opencensus-cpp. --- .gitmodules | 3 + lib/opencensus-cpp | 1 + src/.gitignore | 1 + src/Makefile | 92 +++++++++++++++++++++--- src/agent.cc | 11 +-- src/agent.h | 7 -- src/api_server.cc | 31 +++----- src/api_server.h | 4 -- src/internal/measures_utils.cc | 37 ++++++++++ src/internal/measures_utils.h | 30 ++++++++ src/measures.cc | 64 +++++++++++++++++ src/measures.h | 39 ++++++++++ src/oauth2.cc | 19 ++++- src/oauth2.h | 8 +-- test/Makefile | 76 +++++++++++++++++--- test/api_server_unittest.cc | 52 -------------- test/internal/measures_utils_unittest.cc | 28 ++++++++ test/oauth2_unittest.cc | 34 +++++++++ 18 files changed, 418 insertions(+), 119 deletions(-) create mode 160000 lib/opencensus-cpp create mode 100644 src/internal/measures_utils.cc create mode 100644 src/internal/measures_utils.h create mode 100644 src/measures.cc create mode 100644 src/measures.h create mode 100644 test/internal/measures_utils_unittest.cc diff --git a/.gitmodules b/.gitmodules index f11a5d68..35b7a4e4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "lib/prometheus-cpp"] path = lib/prometheus-cpp url = https://github.com/jupp0r/prometheus-cpp +[submodule "lib/opencensus-cpp"] + path = lib/opencensus-cpp + url = https://github.com/census-instrumentation/opencensus-cpp diff --git a/lib/opencensus-cpp b/lib/opencensus-cpp new file mode 160000 index 00000000..f449234c --- /dev/null +++ b/lib/opencensus-cpp @@ -0,0 +1 @@ +Subproject commit f449234c435100413fad96608c6e9aeae7f07b5e diff --git a/src/.gitignore b/src/.gitignore index ef02ec57..85b85877 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -2,4 +2,5 @@ init-submodules build-cpp-netlib build-yaml-cpp build-prometheus-cpp +build-opencensus-cpp metadatad diff --git a/src/Makefile b/src/Makefile index efebac9b..933c4716 100644 --- a/src/Makefile +++ b/src/Makefile @@ -26,7 +26,12 @@ YAML_CPP_LIBDIR=$(YAML_CPP_DIR) PROMETHEUS_CPP_DIR=$(LIBDIR)/prometheus-cpp PROMETHEUS_CPP_LIBDIR=$(PROMETHEUS_CPP_DIR) PROMETHEUS_CPP_CORE_LIBDIR=$(PROMETHEUS_CPP_LIBDIR)/core -SUBMODULE_DIRS=$(CPP_NETLIB_DIR) $(YAML_CPP_DIR) $(PROMETHEUS_CPP_DIR) +OPENCENSUS_CPP_DIR=$(LIBDIR)/opencensus-cpp +OPENCENSUS_CPP_OPENCENSUS_DIR=$(OPENCENSUS_CPP_DIR)/opencensus +OPENCENSUS_CPP_OPENCENSUS_LIBDIR=$(OPENCENSUS_CPP_OPENCENSUS_DIR) +OPENCENSUS_CPP_ABSL_INCLUDEDIR=$(OPENCENSUS_CPP_DIR)/abseil-src +OPENCENSUS_CPP_ABSL_LIBDIR=$(OPENCENSUS_CPP_DIR)/abseil-build/absl +SUBMODULE_DIRS=$(CPP_NETLIB_DIR) $(YAML_CPP_DIR) $(PROMETHEUS_CPP_DIR) $(OPENCENSUS_CPP_DIR) GIT=git GIT_VERSION=$(shell $(GIT) --version | grep -oh '[0-9]\+\.[0-9]\+\.[0-9]\+') @@ -37,18 +42,46 @@ CPPFLAGS=\ -DAGENT_VERSION='$(PKG_VERSION)-$(PKG_RELEASE)' \ -DENABLE_DOCKER_METADATA \ -I$(CPP_NETLIB_DIR) -I$(NETWORK_URI_DIR)/include -I$(YAML_CPP_DIR)/include \ - -I$(PROMETHEUS_CPP_CORE_LIBDIR)/include + -I$(PROMETHEUS_CPP_CORE_LIBDIR)/include -I$(OPENCENSUS_CPP_DIR) \ + -I$(OPENCENSUS_CPP_ABSL_INCLUDEDIR) CXXFLAGS=\ -std=c++11 -g -pthread -Wno-write-strings -Wno-deprecated LDFLAGS=\ -L$(CPP_NETLIB_LIBDIR) \ -L$(NETWORK_URI_LIBDIR) \ -L$(YAML_CPP_LIBDIR) \ - -L$(PROMETHEUS_CPP_CORE_LIBDIR) + -L$(PROMETHEUS_CPP_CORE_LIBDIR) \ + -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/stats \ + -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/context \ + -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/exporters/stats/prometheus \ + -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/trace \ + -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/tags \ + -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/common/internal \ + -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/numeric \ + -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/strings \ + -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/synchronization \ + -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/time \ + -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/debugging \ + -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/base LDLIBS=\ -lcppnetlib-client-connections -lcppnetlib-server-parsers -lnetwork-uri \ -lboost_program_options -lboost_system -lboost_thread -lboost_filesystem \ - -lpthread -lyajl -lssl -lcrypto -lyaml-cpp -lprometheus-cpp-core + -lpthread -lyajl -lssl -lcrypto -lyaml-cpp -lprometheus-cpp-core \ + -lopencensus_exporters_stats_prometheus \ + -lopencensus_exporters_stats_prometheus_utils \ + -lopencensus_stats_core -lopencensus_stats_recording \ + -lopencensus_tags -lopencensus_tags_context_util \ + -lopencensus_context \ + -lopencensus_trace_context_util \ + -lopencensus_trace_with_span \ + -lopencensus_trace \ + -lopencensus_common_random \ + -labsl_strings -labsl_synchronization -labsl_time \ + -labsl_int128 \ + -labsl_stacktrace -labsl_symbolize \ + -labsl_demangle_internal -labsl_internal_debugging_internal \ + -labsl_base -labsl_dynamic_annotations -labsl_internal_spinlock_wait \ + -labsl_internal_malloc_internal -labsl_internal_throw_delegate SED_EXTRA=-e 's/-Wall/-Wall -Wno-deprecated/' UNAME_S=$(shell uname -s) @@ -79,6 +112,8 @@ SRCS=\ kubernetes.cc \ resource.cc \ oauth2.cc \ + measures.cc \ + internal/measures_utils.cc \ logging.cc \ local_stream_http.cc \ local_stream_delegate.cc \ @@ -98,7 +133,32 @@ YAML_CPP_LIBS=\ $(YAML_CPP_LIBDIR)/libyaml-cpp.a PROMETHEUS_CPP_LIBS=\ $(PROMETHEUS_CPP_CORE_LIBDIR)/libprometheus-cpp-core.a -LIBS=$(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) $(PROMETHEUS_CPP_LIBS) +OPENCENSUS_CPP_LIBS=\ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/base/libabsl_base.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/base/libabsl_internal_malloc_internal.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/base/libabsl_internal_throw_delegate.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/base/libabsl_internal_spinlock_wait.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/base/libabsl_dynamic_annotations.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/debugging/libabsl_demangle_internal.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/debugging/libabsl_internal_debugging_internal.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/debugging/libabsl_stacktrace.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/debugging/libabsl_symbolize.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/numeric/libabsl_int128.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/synchronization/libabsl_synchronization.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/strings/libabsl_strings.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/time/libabsl_time.a \ + $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/exporters/stats/prometheus/libopencensus_exporters_stats_prometheus.a \ + $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/exporters/stats/prometheus/libopencensus_exporters_stats_prometheus_utils.a \ + $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/stats/libopencensus_stats_core.a \ + $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/context/libopencensus_context.a \ + $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/tags/libopencensus_tags.a \ + $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/tags/libopencensus_tags_context_util.a \ + $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/trace/libopencensus_trace.a \ + $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/trace/libopencensus_trace_with_span.a \ + $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/trace/libopencensus_trace_context_util.a \ + $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/context/libopencensus_context.a \ + $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/common/internal/libopencensus_common_random.a +LIBS=$(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) $(PROMETHEUS_CPP_LIBS) $(OPENCENSUS_CPP_LIBS) sbindir=/opt/stackdriver/metadata/sbin INSTALL=/usr/bin/install @@ -177,7 +237,7 @@ clean: $(RM) metadatad $(OBJS) purge: clean - $(RM) -r init-submodules build-cpp-netlib build-yaml-cpp build-prometheus-cpp + $(RM) -r init-submodules build-cpp-netlib build-yaml-cpp build-prometheus-cpp build-opencensus-cpp (cd .. && git submodule deinit -f $(SUBMODULE_DIRS:../%=%)) init-submodules: @@ -243,14 +303,26 @@ build-prometheus-cpp: $(PROMETHEUS_CPP_DIR)/Makefile $(MAKE) touch build-prometheus-cpp -cpp-netlib: $(CPP_NETLIB_LIBS) +$(OPENCENSUS_CPP_DIR)/Makefile: init-submodules + cd $(OPENCENSUS_CPP_DIR) && \ + $(CMAKE) -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS=-std=c++11 \ + -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ \ + -DBUILD_TESTING=OFF -yaml-cpp: $(YAML_CPP_LIBS) +$(OPENCENSUS_CPP_LIBS): build-opencensus-cpp +build-opencensus-cpp: $(OPENCENSUS_CPP_DIR)/Makefile + cd $(OPENCENSUS_CPP_DIR) && \ + $(MAKE) + touch build-opencensus-cpp + +cpp-netlib: $(CPP_NETLIB_LIBS) +yaml-cpp: $(YAML_CPP_LIBS) prometheus-cpp: $(PROMETHEUS_CPP_LIBS) +opencensus-cpp: $(OPENCENSUS_CPP_LIBS) -submodules: cpp-netlib yaml-cpp prometheus-cpp +submodules: cpp-netlib yaml-cpp prometheus-cpp opencensus-cpp all: submodules metadatad -.PHONY: all submodules cpp-netlib yaml-cpp prometheus-cpp purge clean install deb rpm +.PHONY: all submodules cpp-netlib yaml-cpp prometheus-cpp opencensus-cpp purge clean install deb rpm diff --git a/src/agent.cc b/src/agent.cc index 407586ad..1375248e 100644 --- a/src/agent.cc +++ b/src/agent.cc @@ -16,25 +16,26 @@ #include "agent.h" -#include "configuration.h" #include "api_server.h" -#include "reporter.h" +#include "configuration.h" #include "health_checker.h" +#include "measures.h" +#include "reporter.h" namespace google { MetadataAgent::MetadataAgent(const Configuration& config) - : config_(config), store_(config_), health_checker_(config, store_), - registry_(std::make_shared()) {} + : config_(config), store_(config_), health_checker_(config, store_) {} MetadataAgent::~MetadataAgent() {} void MetadataAgent::Start() { metadata_api_server_.reset(new MetadataApiServer( - config_, &health_checker_, registry_, store_, config_.MetadataApiNumThreads(), + config_, &health_checker_, store_, config_.MetadataApiNumThreads(), config_.MetadataApiBindAddress(), config_.MetadataApiPort())); reporter_.reset(new MetadataReporter( config_, &store_, config_.MetadataReporterIntervalSeconds())); + ::google::RegisterAllViewsForExport(); } void MetadataAgent::Stop() { diff --git a/src/agent.h b/src/agent.h index 7a5efc35..45d9fe19 100644 --- a/src/agent.h +++ b/src/agent.h @@ -17,7 +17,6 @@ #define AGENT_H_ #include -#include #include "store.h" #include "health_checker.h" @@ -61,10 +60,6 @@ class MetadataAgent { return &health_checker_; } - std::shared_ptr prometheus_registry() { - return registry_; - } - private: const Configuration& config_; @@ -73,8 +68,6 @@ class MetadataAgent { HealthChecker health_checker_; - std::shared_ptr registry_; - // The Metadata API server. std::unique_ptr metadata_api_server_; // The metadata reporter. diff --git a/src/api_server.cc b/src/api_server.cc index 6113cd83..3c4ce11d 100644 --- a/src/api_server.cc +++ b/src/api_server.cc @@ -17,11 +17,11 @@ #include "api_server.h" #include -#include #include "configuration.h" #include "health_checker.h" #include "http_common.h" +#include "internal/measures_utils.h" #include "logging.h" #include "store.h" @@ -68,16 +68,12 @@ void MetadataApiServer::Dispatcher::log(const HttpServer::string_type& info) con } -MetadataApiServer::MetadataApiServer( - const Configuration& config, - const HealthChecker* health_checker, - const std::shared_ptr collectable, - const MetadataStore& store, - int server_threads, - const std::string& host, - int port) - : config_(config), health_checker_(health_checker), - collectable_(collectable), store_(store), +MetadataApiServer::MetadataApiServer(const Configuration& config, + const HealthChecker* health_checker, + const MetadataStore& store, + int server_threads, + const std::string& host, int port) + : config_(config), health_checker_(health_checker), store_(store), dispatcher_({ {{"GET", "/monitoredResource/"}, [=](const HttpServer::request& request, @@ -213,7 +209,7 @@ void MetadataApiServer::HandleHealthz( void MetadataApiServer::HandleMetrics( const HttpServer::request& request, std::shared_ptr conn) { - std::string response = SerializeMetricsToPrometheusTextFormat(); + std::string response = internal::SerializeMetricsToPrometheusTextFormat(); conn->set_status(HttpServer::connection::ok); conn->set_headers(std::map({ {"Connection", "close"}, @@ -223,13 +219,4 @@ void MetadataApiServer::HandleMetrics( conn->write(response); } -std::string MetadataApiServer::SerializeMetricsToPrometheusTextFormat() const { - if (!collectable_) { - return ""; - } - - prometheus::TextSerializer text_serializer; - return std::move(text_serializer.Serialize(collectable_->Collect())); -} - -} +} // namespace google diff --git a/src/api_server.h b/src/api_server.h index 588369dd..e78f9f82 100644 --- a/src/api_server.h +++ b/src/api_server.h @@ -18,7 +18,6 @@ #define BOOST_NETWORK_ENABLE_HTTPS #include -#include #include #include #include @@ -44,7 +43,6 @@ class MetadataApiServer { public: MetadataApiServer(const Configuration& config, const HealthChecker* health_checker, - const std::shared_ptr collectable, const MetadataStore& store, int server_threads, const std::string& host, int port); ~MetadataApiServer(); @@ -81,7 +79,6 @@ class MetadataApiServer { std::shared_ptr conn); void HandleMetrics(const HttpServer::request& request, std::shared_ptr conn); - std::string SerializeMetricsToPrometheusTextFormat() const; const Configuration& config_; const HealthChecker* health_checker_; @@ -89,7 +86,6 @@ class MetadataApiServer { Dispatcher dispatcher_; HttpServer server_; std::vector server_pool_; - std::shared_ptr collectable_; }; } diff --git a/src/internal/measures_utils.cc b/src/internal/measures_utils.cc new file mode 100644 index 00000000..04d19799 --- /dev/null +++ b/src/internal/measures_utils.cc @@ -0,0 +1,37 @@ +/* + * Copyright 2018 Google Inc. + * + * 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 "measures_utils.h" + +#include +#include + +namespace google { +namespace internal { + +namespace { + +::prometheus::TextSerializer text_serializer; +::opencensus::exporters::stats::PrometheusExporter exporter; + +} // namespace + +std::string SerializeMetricsToPrometheusTextFormat() { + return text_serializer.Serialize(exporter.Collect()); +} + +} // namespace internal +} // namespace google diff --git a/src/internal/measures_utils.h b/src/internal/measures_utils.h new file mode 100644 index 00000000..66fd7705 --- /dev/null +++ b/src/internal/measures_utils.h @@ -0,0 +1,30 @@ +/* + * Copyright 2018 Google Inc. + * + * 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. + **/ + +#ifndef METADATA_AGENT_INTERNAL_MEASURES_UTILS_H_ +#define METADATA_AGENT_INTERNAL_MEASURES_UTILS_H_ + +#include + +namespace google { +namespace internal { + +std::string SerializeMetricsToPrometheusTextFormat(); + +} // namespace internal +} // namespace google + +#endif /* METADATA_AGENT_INTERNAL_MEASURES_UTILS_H_ */ diff --git a/src/measures.cc b/src/measures.cc new file mode 100644 index 00000000..c80efb33 --- /dev/null +++ b/src/measures.cc @@ -0,0 +1,64 @@ +/* + * Copyright 2018 Google Inc. + * + * 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 "measures.h" + +#include +#include + +namespace google { + +namespace { + +constexpr char kUnitBytes[] = "By"; +constexpr char kCount[] = "1"; + +} // namespace + +ABSL_CONST_INIT const absl::string_view + kGceApiRequestErrors = + "container.googleapis.com/internal/metadata_agent/gce_api_request_errors"; + +::opencensus::stats::MeasureInt64 GceApiRequestErrors() { + static const auto measure = + ::opencensus::stats::MeasureInt64::Register( + kGceApiRequestErrors, + "Number of API request errors encountered.", + kCount); + return measure; +} + +::opencensus::stats::TagKey MethodTagKey() { + static const auto method_tag_key = + ::opencensus::stats::TagKey::Register("method"); + return method_tag_key; +} + +const ::opencensus::stats::ViewDescriptor& GceApiRequestErrorsCumulative() { + const static ::opencensus::stats::ViewDescriptor descriptor = + ::opencensus::stats::ViewDescriptor() + .set_name("gce_api_request_errors") + .set_measure(kGceApiRequestErrors) + .set_aggregation(::opencensus::stats::Aggregation::Count()) + .add_column(MethodTagKey()); + return descriptor; +} + +void RegisterAllViewsForExport() { + GceApiRequestErrorsCumulative().RegisterForExport(); +} + +} // namespace google diff --git a/src/measures.h b/src/measures.h new file mode 100644 index 00000000..13373080 --- /dev/null +++ b/src/measures.h @@ -0,0 +1,39 @@ +/* + * Copyright 2018 Google Inc. + * + * 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. + **/ + +#ifndef METADATA_AGENT_MEASURES_H_ +#define METADATA_AGENT_MEASURES_H_ + +#include + +namespace google { + +extern const absl::string_view kGceApiRequestErrors; + +// measures +::opencensus::stats::MeasureInt64 GceApiRequestErrors(); + +// tag keys +::opencensus::stats::TagKey MethodTagKey(); + +// view descriptors +const ::opencensus::stats::ViewDescriptor& GceApiRequestErrorsCumulative(); + +void RegisterAllViewsForExport(); + +} // namespace google + +#endif /* METADATA_AGENT_MEASURES_H_ */ diff --git a/src/oauth2.cc b/src/oauth2.cc index c78776be..6b61a8db 100644 --- a/src/oauth2.cc +++ b/src/oauth2.cc @@ -32,6 +32,7 @@ #include "http_common.h" #include "json.h" #include "logging.h" +#include "measures.h" #include "time.h" namespace http = boost::network::http; @@ -139,6 +140,17 @@ std::string Sign(const std::string& data, const PKey& pkey) { return std::string(reinterpret_cast(result.get()), actual_result_size); } +} // namespace + +OAuth2::OAuth2(const Environment& environment) + : OAuth2(environment, ExpirationImpl::New()) {} + +OAuth2::OAuth2(const Environment& environment, + std::unique_ptr expiration) + : environment_(environment), + token_expiration_(std::move(expiration)), + token_endpoint_(kDefaultTokenEndpoint) { + ::google::GceApiRequestErrors(); } json::value OAuth2::ComputeTokenFromCredentials() const { @@ -249,11 +261,14 @@ json::value OAuth2::ComputeTokenFromCredentials() const { return parsed_token; } catch (const json::Exception& e) { LOG(ERROR) << e.what(); - return nullptr; } catch (const boost::system::system_error& e) { LOG(ERROR) << "HTTP error: " << e.what(); - return nullptr; } + + ::opencensus::stats::Record( + {{::google::GceApiRequestErrors(), 1}}, + {{::google::MethodTagKey(), "oauth2"}}); + return nullptr; } json::value OAuth2::GetMetadataToken() const { diff --git a/src/oauth2.h b/src/oauth2.h index a27af2dd..6bbd1d97 100644 --- a/src/oauth2.h +++ b/src/oauth2.h @@ -33,16 +33,12 @@ constexpr const char kDefaultTokenEndpoint[] = class OAuth2 { public: - OAuth2(const Environment& environment) - : OAuth2(environment, ExpirationImpl::New()) {} + OAuth2(const Environment& environment); std::string GetAuthHeaderValue(); protected: - OAuth2(const Environment& environment, std::unique_ptr expiration) - : environment_(environment), - token_expiration_(std::move(expiration)), - token_endpoint_(kDefaultTokenEndpoint) {} + OAuth2(const Environment& environment, std::unique_ptr expiration); private: friend class OAuth2Test; diff --git a/test/Makefile b/test/Makefile index 4bebdcfe..6acfc787 100644 --- a/test/Makefile +++ b/test/Makefile @@ -35,6 +35,11 @@ YAML_CPP_LIBDIR=$(YAML_CPP_DIR) PROMETHEUS_CPP_DIR=$(LIBDIR)/prometheus-cpp PROMETHEUS_CPP_LIBDIR=$(PROMETHEUS_CPP_DIR) PROMETHEUS_CPP_CORE_LIBDIR=$(PROMETHEUS_CPP_LIBDIR)/core +OPENCENSUS_CPP_DIR=$(LIBDIR)/opencensus-cpp +OPENCENSUS_CPP_OPENCENSUS_DIR=$(OPENCENSUS_CPP_DIR)/opencensus +OPENCENSUS_CPP_OPENCENSUS_LIBDIR=$(OPENCENSUS_CPP_OPENCENSUS_DIR) +OPENCENSUS_CPP_ABSL_INCLUDEDIR=$(OPENCENSUS_CPP_DIR)/abseil-src +OPENCENSUS_CPP_ABSL_LIBDIR=$(OPENCENSUS_CPP_DIR)/abseil-build/absl CPP_NETLIB_LIBS=\ $(CPP_NETLIB_LIBDIR)/libcppnetlib-client-connections.a \ @@ -43,23 +48,67 @@ CPP_NETLIB_LIBS=\ YAML_CPP_LIBS=$(YAML_CPP_LIBDIR)/libyaml-cpp.a PROMETHEUS_CPP_LIBS=\ $(PROMETHEUS_CPP_CORE_LIBDIR)/libprometheus-cpp-core.a +OPENCENSUS_CPP_LIBS=\ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/base/libabsl_base.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/base/libabsl_internal_malloc_internal.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/base/libabsl_internal_throw_delegate.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/base/libabsl_internal_spinlock_wait.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/base/libabsl_dynamic_annotations.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/debugging/libabsl_stacktrace.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/debugging/libabsl_symbolize.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/numeric/libabsl_int128.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/synchronization/libabsl_synchronization.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/strings/libabsl_strings.a \ + $(OPENCENSUS_CPP_ABSL_LIBDIR)/time/libabsl_time.a \ + $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/exporters/stats/stdout/libopencensus_exporters_stats_stdout.a \ + $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/stats/libopencensus_stats_core.a \ + $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/stats/libopencensus_stats_test_utils.a \ + $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/tags/libopencensus_tags.a CPPFLAGS+= \ -isystem $(GTEST_DIR)/include -I$(GMOCK_DIR)/include \ -I$(CPP_NETLIB_DIR) -I$(NETWORK_URI_DIR)/include -I$(YAML_CPP_DIR)/include \ - -I$(PROMETHEUS_CPP_CORE_LIBDIR)/include + -I$(PROMETHEUS_CPP_CORE_LIBDIR)/include \ + -I$(OPENCENSUS_CPP_DIR) -I$(OPENCENSUS_CPP_ABSL_INCLUDEDIR) CXXFLAGS=\ -std=c++11 -g -pthread -Wno-write-strings -Wno-deprecated LDFLAGS=\ -L$(CPP_NETLIB_LIBDIR) \ -L$(NETWORK_URI_LIBDIR) \ -L$(YAML_CPP_LIBDIR) \ - -L$(PROMETHEUS_CPP_CORE_LIBDIR) + -L$(PROMETHEUS_CPP_CORE_LIBDIR) \ + -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/stats \ + -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/context \ + -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/exporters/stats/prometheus \ + -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/trace \ + -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/tags \ + -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/common/internal \ + -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/numeric \ + -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/strings \ + -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/synchronization \ + -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/time \ + -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/debugging \ + -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/base LDLIBS=\ -lcppnetlib-client-connections -lcppnetlib-server-parsers -lnetwork-uri \ -lboost_program_options -lboost_system -lboost_thread -lboost_filesystem \ -lboost_regex -lpthread -lyajl -lssl -lcrypto -lyaml-cpp \ - -lprometheus-cpp-core + -lprometheus-cpp-core \ + -lopencensus_exporters_stats_prometheus \ + -lopencensus_exporters_stats_prometheus_utils \ + -lopencensus_stats_core -lopencensus_stats_test_utils -lopencensus_stats_recording \ + -lopencensus_tags -lopencensus_tags_context_util \ + -lopencensus_context \ + -lopencensus_trace_context_util \ + -lopencensus_trace_with_span \ + -lopencensus_trace \ + -lopencensus_common_random \ + -labsl_strings -labsl_synchronization -labsl_time \ + -labsl_int128 \ + -labsl_stacktrace -labsl_symbolize \ + -labsl_demangle_internal -labsl_internal_debugging_internal \ + -labsl_base -labsl_dynamic_annotations -labsl_internal_spinlock_wait \ + -labsl_internal_malloc_internal -labsl_internal_throw_delegate UNAME_S=$(shell uname -s) ifeq ($(UNAME_S),Darwin) @@ -80,6 +129,7 @@ TEST_DIR=. TEST_SOURCES=$(wildcard $(TEST_DIR)/*_unittest.cc) TEST_OBJS=$(TEST_SOURCES:$(TEST_DIR)/%.cc=%.o) TESTS=\ + internal/measures_utils_unittest \ api_server_unittest \ base64_unittest \ configuration_unittest \ @@ -126,7 +176,7 @@ init-submodules: $(SRC_DIR)/init-submodules: cd $(SRC_DIR) && $(MAKE) $(@:$(SRC_DIR)/%=%) -$(SRC_DIR)/build-cpp-netlib $(SRC_DIR)/build-yaml-cpp $(SRC_DIR)/build-prometheus-cpp: $(SRC_DIR)/init-submodules +$(SRC_DIR)/build-cpp-netlib $(SRC_DIR)/build-yaml-cpp $(SRC_DIR)/build-prometheus-cpp $(SRC_DIR)/build-opencensus-cpp: $(SRC_DIR)/init-submodules cd $(SRC_DIR) && $(MAKE) $(@:$(SRC_DIR)/%=%) $(CPP_NETLIB_LIBS): $(SRC_DIR)/build-cpp-netlib @@ -135,7 +185,9 @@ $(YAML_CPP_LIBS): $(SRC_DIR)/build-yaml-cpp $(PROMETHEUS_CPP_LIBS): $(SRC_DIR)/build-prometheus-cpp -$(SRC_DIR)/%.o: $(SRC_DIR)/build-cpp-netlib $(SRC_DIR)/build-yaml-cpp $(SRC_DIR)/build-prometheus-cpp $(SRC_DIR)/%.cc +$(OPENCENSUS_CPP_LIBS): $(SRC_DIR)/build-opencensus-cpp + +$(SRC_DIR)/%.o: $(SRC_DIR)/build-cpp-netlib $(SRC_DIR)/build-yaml-cpp $(SRC_DIR)/build-prometheus-cpp $(SRC_DIR)/build-opencensus-cpp $(SRC_DIR)/%.cc cd $(SRC_DIR) && $(MAKE) $(@:$(SRC_DIR)/%=%) $(GTEST_SOURCEDIR)/gtest-all.cc: init-submodules @@ -152,14 +204,16 @@ gmock_main.o: $(GMOCK_SOURCEDIR)/gmock_main.cc $(GTEST_LIB): gtest-all.o gmock-all.o gmock_main.o $(AR) $(ARFLAGS) $@ $^ -$(TESTS): $(GTEST_LIB) $(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) $(PROMETHEUS_CPP_LIBS) +$(TESTS): $(GTEST_LIB) $(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) $(PROMETHEUS_CPP_LIBS) $(OPENCENSUS_CPP_LIBS) # All unittest objects depend on GTEST_LIB. # Some headers need CPP_NETLIB_LIBS and YAML_CPP_LIBS. -$(TESTS:%=%.o): $(GTEST_LIB) $(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) $(PROMETHEUS_CPP_LIBS) +$(TESTS:%=%.o): $(GTEST_LIB) $(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) $(PROMETHEUS_CPP_LIBS) $(OPENCENSUS_CPP_LIBS) -api_server_unittest: api_server_unittest.o $(SRC_DIR)/api_server.o $(SRC_DIR)/configuration.o $(SRC_DIR)/store.o $(SRC_DIR)/json.o $(SRC_DIR)/resource.o $(SRC_DIR)/logging.o $(SRC_DIR)/time.o $(SRC_DIR)/health_checker.o - $(CXX) $(LDFLAGS) $^ $(LDLIBS) -lprometheus-cpp-core -o $@ +internal/measures_utils_unittest: internal/measures_utils_unittest.o $(SRC_DIR)/internal/measures_utils.o + $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ +api_server_unittest: api_server_unittest.o $(SRC_DIR)/api_server.o $(SRC_DIR)/internal/measures_utils.o $(SRC_DIR)/configuration.o $(SRC_DIR)/store.o $(SRC_DIR)/json.o $(SRC_DIR)/resource.o $(SRC_DIR)/logging.o $(SRC_DIR)/time.o $(SRC_DIR)/health_checker.o + $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ base64_unittest: base64_unittest.o $(SRC_DIR)/base64.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ configuration_unittest: configuration_unittest.o $(SRC_DIR)/configuration.o @@ -178,11 +232,11 @@ kubernetes_unittest: kubernetes_unittest.o fake_http_server.o $(SRC_DIR)/kuberne $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ logging_unittest: logging_unittest.o $(SRC_DIR)/logging.o $(SRC_DIR)/time.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ -oauth2_unittest: oauth2_unittest.o fake_clock.o fake_http_server.o $(SRC_DIR)/oauth2.o $(SRC_DIR)/base64.o $(SRC_DIR)/configuration.o $(SRC_DIR)/environment.o $(SRC_DIR)/format.o $(SRC_DIR)/json.o $(SRC_DIR)/logging.o $(SRC_DIR)/time.o +oauth2_unittest: oauth2_unittest.o fake_clock.o fake_http_server.o $(SRC_DIR)/oauth2.o $(SRC_DIR)/base64.o $(SRC_DIR)/configuration.o $(SRC_DIR)/environment.o $(SRC_DIR)/format.o $(SRC_DIR)/json.o $(SRC_DIR)/logging.o $(SRC_DIR)/measures.o $(SRC_DIR)/time.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ resource_unittest: resource_unittest.o $(SRC_DIR)/resource.o $(SRC_DIR)/json.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ -reporter_unittest: reporter_unittest.o fake_clock.o fake_http_server.o $(SRC_DIR)/reporter.o $(SRC_DIR)/base64.o $(SRC_DIR)/configuration.o $(SRC_DIR)/environment.o $(SRC_DIR)/format.o $(SRC_DIR)/json.o $(SRC_DIR)/logging.o $(SRC_DIR)/oauth2.o $(SRC_DIR)/resource.o $(SRC_DIR)/store.o $(SRC_DIR)/time.o +reporter_unittest: reporter_unittest.o fake_clock.o fake_http_server.o $(SRC_DIR)/reporter.o $(SRC_DIR)/base64.o $(SRC_DIR)/configuration.o $(SRC_DIR)/environment.o $(SRC_DIR)/format.o $(SRC_DIR)/json.o $(SRC_DIR)/logging.o $(SRC_DIR)/measures.o $(SRC_DIR)/oauth2.o $(SRC_DIR)/resource.o $(SRC_DIR)/store.o $(SRC_DIR)/time.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ store_unittest: store_unittest.o $(SRC_DIR)/store.o $(SRC_DIR)/resource.o $(SRC_DIR)/json.o $(SRC_DIR)/logging.o $(SRC_DIR)/time.o $(SRC_DIR)/configuration.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ diff --git a/test/api_server_unittest.cc b/test/api_server_unittest.cc index 02c9f12c..5c82ab2a 100644 --- a/test/api_server_unittest.cc +++ b/test/api_server_unittest.cc @@ -19,19 +19,11 @@ #include "../src/store.h" #include "gtest/gtest.h" -#include - namespace google { class ApiServerTest : public ::testing::Test { protected: using Dispatcher = MetadataApiServer::Dispatcher; - - static std::string SerializeMetricsToPrometheusTextFormat( - const google::MetadataApiServer& api_server) { - return api_server.SerializeMetricsToPrometheusTextFormat(); - } - std::unique_ptr CreateDispatcher( const std::map, std::function>& handlers) { @@ -103,48 +95,4 @@ TEST_F(ApiServerTest, DispatcherSubstringCheck) { InvokeDispatcher(dispatcher, "GET", "/testPath/subPath/"); EXPECT_TRUE(handler_called); } - -TEST_F(ApiServerTest, SerializationToPrometheusTextForNullPtr) { - google::Configuration config; - google::MetadataApiServer server( - config, - /*health_checker=*/nullptr, - /*std::shared_ptr=*/nullptr, - MetadataStore(config), - 0, "", 8080); - EXPECT_EQ("", SerializeMetricsToPrometheusTextFormat(server)); -} - -TEST_F(ApiServerTest, SerializationToPrometheusTextForEmptyRegistry) { - google::Configuration config; - std::shared_ptr registry; - google::MetadataApiServer server( - config, /*health_checker=*/nullptr, registry, - MetadataStore(config), - 0, "", 8080); - EXPECT_EQ("", SerializeMetricsToPrometheusTextFormat(server)); -} - -TEST_F(ApiServerTest, SerializationToPrometheusTextWithLabeledCounter) { - google::Configuration config; - auto registry = std::make_shared(); - auto& counter_family = prometheus::BuildCounter() - .Name("test_metric_counter") - .Help("help on test_metric_counter") - .Register(*registry); - - // Add a labeled counter - counter_family.Add({{"foo", "bar"}}); - - std::string expected_result = - "# HELP test_metric_counter help on test_metric_counter\n" - "# TYPE test_metric_counter counter\n" - "test_metric_counter{foo=\"bar\"} 0.000000\n"; - google::MetadataApiServer server( - config, /*health_checker=*/nullptr, registry, - MetadataStore(config), - 0, "", 8080); - EXPECT_EQ(expected_result, SerializeMetricsToPrometheusTextFormat(server)); -} - } // namespace google diff --git a/test/internal/measures_utils_unittest.cc b/test/internal/measures_utils_unittest.cc new file mode 100644 index 00000000..d9dc699c --- /dev/null +++ b/test/internal/measures_utils_unittest.cc @@ -0,0 +1,28 @@ +/* + * Copyright 2018 Google Inc. + * + * 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 "../../src/internal/measures_utils.h" +#include "gtest/gtest.h" + +namespace google { +namespace internal { + +TEST(SerializeToPrometheusTextTest, Initialization) { + EXPECT_EQ("", SerializeMetricsToPrometheusTextFormat()); +} + +} // namespace internal +} // namespace google diff --git a/test/oauth2_unittest.cc b/test/oauth2_unittest.cc index 142307de..9dae18c3 100644 --- a/test/oauth2_unittest.cc +++ b/test/oauth2_unittest.cc @@ -15,6 +15,8 @@ **/ #include "../src/oauth2.h" + +#include "../src/measures.h" #include "environment_util.h" #include "fake_clock.h" #include "fake_http_server.h" @@ -22,12 +24,18 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include +#include #include namespace google { class OAuth2Test : public ::testing::Test { protected: + void SetUp() override { + ::opencensus::stats::testing::TestUtils::Flush(); + } + static void SetTokenEndpointForTest(OAuth2* auth, const std::string& endpoint) { auth->SetTokenEndpointForTest(endpoint); @@ -118,6 +126,32 @@ TEST_F(OAuth2Test, GetAuthHeaderValueUsingTokenFromMetadataServerAsFallback) { EXPECT_EQ("Bearer the-access-token", auth.GetAuthHeaderValue()); } +TEST_F(OAuth2Test, GetApiRequestErrorMetric) { + testing::FakeServer oauth_server; + testing::TemporaryFile credentials_file( + std::string(test_info_->name()) + "_creds.json", + "{\"client_email\":\"user@example.com\",\"private_key\":\"some_key\"}"); + Configuration config(std::istringstream( + "CredentialsFile: '" + credentials_file.FullPath().native() + "'\n" + )); + Environment environment(config); + OAuth2 auth(environment); + SetTokenEndpointForTest(&auth, oauth_server.GetUrl() + "/oauth2/v3/token"); + + ::opencensus::stats::View errors_view( + ::google::GceApiRequestErrorsCumulative()); + + // no record exists before internal function sent request to oauth_server + EXPECT_THAT(errors_view.GetData().int_data(), + ::testing::UnorderedElementsAre()); + + auth.GetAuthHeaderValue(); + ::opencensus::stats::testing::TestUtils::Flush(); + EXPECT_THAT(errors_view.GetData().int_data(), + ::testing::UnorderedElementsAre(::testing::Pair( + ::testing::ElementsAre("oauth2"), 1))); +} + TEST_F(OAuth2Test, GetAuthHeaderValueTokenJsonMissingField) { testing::FakeServer metadata_server; // JSON is missing "expires_in" field. From c6673885fb842e5b137ee21e47e4b9cf74680059 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Thu, 6 Dec 2018 05:48:17 +0000 Subject: [PATCH 07/36] Makefile change --- src/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Makefile b/src/Makefile index 933c4716..a31c77f1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -24,8 +24,8 @@ NETWORK_URI_LIBDIR=$(NETWORK_URI_DIR)/src YAML_CPP_DIR=$(LIBDIR)/yaml-cpp YAML_CPP_LIBDIR=$(YAML_CPP_DIR) PROMETHEUS_CPP_DIR=$(LIBDIR)/prometheus-cpp -PROMETHEUS_CPP_LIBDIR=$(PROMETHEUS_CPP_DIR) -PROMETHEUS_CPP_CORE_LIBDIR=$(PROMETHEUS_CPP_LIBDIR)/core +PROMETHEUS_CPP_CORE_DIR=$(PROMETHEUS_CPP_DIR)/core +PROMETHEUS_CPP_CORE_LIBDIR=$(PROMETHEUS_CPP_CORE_DIR) OPENCENSUS_CPP_DIR=$(LIBDIR)/opencensus-cpp OPENCENSUS_CPP_OPENCENSUS_DIR=$(OPENCENSUS_CPP_DIR)/opencensus OPENCENSUS_CPP_OPENCENSUS_LIBDIR=$(OPENCENSUS_CPP_OPENCENSUS_DIR) @@ -42,7 +42,7 @@ CPPFLAGS=\ -DAGENT_VERSION='$(PKG_VERSION)-$(PKG_RELEASE)' \ -DENABLE_DOCKER_METADATA \ -I$(CPP_NETLIB_DIR) -I$(NETWORK_URI_DIR)/include -I$(YAML_CPP_DIR)/include \ - -I$(PROMETHEUS_CPP_CORE_LIBDIR)/include -I$(OPENCENSUS_CPP_DIR) \ + -I$(PROMETHEUS_CPP_CORE_DIR)/include -I$(OPENCENSUS_CPP_DIR) \ -I$(OPENCENSUS_CPP_ABSL_INCLUDEDIR) CXXFLAGS=\ -std=c++11 -g -pthread -Wno-write-strings -Wno-deprecated From cf5f83301dcad5d73ab3c7d991bdf3033f96b435 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Thu, 6 Dec 2018 15:13:48 -0500 Subject: [PATCH 08/36] remove unused variable. --- src/measures.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/measures.cc b/src/measures.cc index c80efb33..be3878b1 100644 --- a/src/measures.cc +++ b/src/measures.cc @@ -23,7 +23,6 @@ namespace google { namespace { -constexpr char kUnitBytes[] = "By"; constexpr char kCount[] = "1"; } // namespace From b788df17df0bdbc6a5413a6fe86d3957e4209227 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Thu, 6 Dec 2018 15:16:58 -0500 Subject: [PATCH 09/36] expand comments on functions in measures.h --- src/measures.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/measures.h b/src/measures.h index 13373080..cffa7735 100644 --- a/src/measures.h +++ b/src/measures.h @@ -23,15 +23,27 @@ namespace google { extern const absl::string_view kGceApiRequestErrors; -// measures +// Measure accessors. If the measure variable is not initialized, these methods +// will initialize the variable. +// +// Reference of measure: https://opencensus.io/stats/measure/ ::opencensus::stats::MeasureInt64 GceApiRequestErrors(); -// tag keys +// Tag key accessors. If the tag key variable is not initialized, these methods +// will initialize the variable. +// +// Reference of measure: https://opencensus.io/tag/key/ ::opencensus::stats::TagKey MethodTagKey(); -// view descriptors +// View Descriptor accessors. If the view descriptor variable is not +// initialized, these methods will initialize the variable. const ::opencensus::stats::ViewDescriptor& GceApiRequestErrorsCumulative(); +// Register all the view descriptors declared above as view for export. +// +// Measures should be registered before calling RegisterAllViewsForExport(), +// otherwise calling this function will create invalid views, which exporter +// cannot export meaningful data. void RegisterAllViewsForExport(); } // namespace google From e49c64db020f93eb683fe5dd793c392312a4bd25 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Thu, 6 Dec 2018 15:18:12 -0500 Subject: [PATCH 10/36] remove declaration on internal variable --- src/measures.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/measures.h b/src/measures.h index cffa7735..e6d41c49 100644 --- a/src/measures.h +++ b/src/measures.h @@ -21,8 +21,6 @@ namespace google { -extern const absl::string_view kGceApiRequestErrors; - // Measure accessors. If the measure variable is not initialized, these methods // will initialize the variable. // From ec5a85933c4fcc9e36a76c0222559c8770c630fb Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Thu, 6 Dec 2018 15:18:57 -0500 Subject: [PATCH 11/36] make string declaration consistent --- src/measures.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/measures.cc b/src/measures.cc index be3878b1..b9daf876 100644 --- a/src/measures.cc +++ b/src/measures.cc @@ -23,7 +23,7 @@ namespace google { namespace { -constexpr char kCount[] = "1"; +ABSL_CONST_INIT const absl::string_view kCount = "1"; } // namespace From bbbd851bf0605d0bbd177a41edb51b38ac6cd059 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Thu, 6 Dec 2018 15:20:00 -0500 Subject: [PATCH 12/36] add comments on why accessing measure in OAuth2 constructor helps --- src/oauth2.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/oauth2.cc b/src/oauth2.cc index 6b61a8db..9900807e 100644 --- a/src/oauth2.cc +++ b/src/oauth2.cc @@ -150,6 +150,8 @@ OAuth2::OAuth2(const Environment& environment, : environment_(environment), token_expiration_(std::move(expiration)), token_endpoint_(kDefaultTokenEndpoint) { + // Access the measure to ensure it is initialized. Otherwise, creating a view before + // any the first error would cause an error. ::google::GceApiRequestErrors(); } From acac8897a31230122727184e7a157c85e1353322 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Thu, 6 Dec 2018 15:20:33 -0500 Subject: [PATCH 13/36] Change the place to register view. As we add more metrics, some of the metrics are other objects - e.g. KubernetesUpdater. View registration should happen after all the metrics are accessed. The lifecycle of all the measure are registered outside of MetadataAgent, so move view registration to the last step in main function. --- src/agent.cc | 2 -- src/metadatad.cc | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/agent.cc b/src/agent.cc index 1375248e..969cd434 100644 --- a/src/agent.cc +++ b/src/agent.cc @@ -19,7 +19,6 @@ #include "api_server.h" #include "configuration.h" #include "health_checker.h" -#include "measures.h" #include "reporter.h" namespace google { @@ -35,7 +34,6 @@ void MetadataAgent::Start() { config_.MetadataApiBindAddress(), config_.MetadataApiPort())); reporter_.reset(new MetadataReporter( config_, &store_, config_.MetadataReporterIntervalSeconds())); - ::google::RegisterAllViewsForExport(); } void MetadataAgent::Stop() { diff --git a/src/metadatad.cc b/src/metadatad.cc index 7363d2f5..f5636a46 100644 --- a/src/metadatad.cc +++ b/src/metadatad.cc @@ -24,6 +24,7 @@ #include "docker.h" #include "instance.h" #include "kubernetes.h" +#include "measures.h" #include "time.h" namespace google { @@ -92,6 +93,9 @@ int main(int ac, char** av) { server.Start(); + // Only register all the views after all the measures are initialized. + ::google::RegisterAllViewsForExport(); + // Wait for the server to shut down. google::cleanup_state->Wait(); } From ac7c9ea0b0a21a11a0823b450b1b83051714cc81 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Thu, 6 Dec 2018 15:33:58 -0500 Subject: [PATCH 14/36] Use the right header for prometheus compatible format. --- src/api_server.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api_server.cc b/src/api_server.cc index 3c4ce11d..dcd64618 100644 --- a/src/api_server.cc +++ b/src/api_server.cc @@ -214,7 +214,7 @@ void MetadataApiServer::HandleMetrics( conn->set_headers(std::map({ {"Connection", "close"}, {"Content-Length", std::to_string(response.size())}, - {"Content-Type", "application/json"}, + {"Content-Type", "text/plain; version=0.0.4"}, })); conn->write(response); } From 5ac289e54e25275b196e16186bfd55bdbf8af1a6 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Fri, 7 Dec 2018 12:47:31 -0500 Subject: [PATCH 15/36] Address comments on measurement organization. --- src/internal/measures_utils.cc | 13 +++++-------- src/measures.cc | 7 +++++++ src/measures.h | 4 ---- src/metadatad.cc | 4 +--- src/oauth2.cc | 6 +----- 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/internal/measures_utils.cc b/src/internal/measures_utils.cc index 04d19799..0c79abc9 100644 --- a/src/internal/measures_utils.cc +++ b/src/internal/measures_utils.cc @@ -22,15 +22,12 @@ namespace google { namespace internal { -namespace { - -::prometheus::TextSerializer text_serializer; -::opencensus::exporters::stats::PrometheusExporter exporter; - -} // namespace - std::string SerializeMetricsToPrometheusTextFormat() { - return text_serializer.Serialize(exporter.Collect()); + static const auto* const text_serializer = + new ::prometheus::TextSerializer(); + static auto* const exporter = + new ::opencensus::exporters::stats::PrometheusExporter(); + return text_serializer->Serialize(exporter->Collect()); } } // namespace internal diff --git a/src/measures.cc b/src/measures.cc index b9daf876..e82fa985 100644 --- a/src/measures.cc +++ b/src/measures.cc @@ -57,6 +57,13 @@ const ::opencensus::stats::ViewDescriptor& GceApiRequestErrorsCumulative() { } void RegisterAllViewsForExport() { + // Access metrics used by views to ensure metrics are initalized. + GceApiRequestErrors(); + + // Register all the views for export. + // + // To avoid view registration throwing error, when adding a new view, register + // measures used by this view in the section above. GceApiRequestErrorsCumulative().RegisterForExport(); } diff --git a/src/measures.h b/src/measures.h index e6d41c49..bc879c9e 100644 --- a/src/measures.h +++ b/src/measures.h @@ -38,10 +38,6 @@ ::opencensus::stats::TagKey MethodTagKey(); const ::opencensus::stats::ViewDescriptor& GceApiRequestErrorsCumulative(); // Register all the view descriptors declared above as view for export. -// -// Measures should be registered before calling RegisterAllViewsForExport(), -// otherwise calling this function will create invalid views, which exporter -// cannot export meaningful data. void RegisterAllViewsForExport(); } // namespace google diff --git a/src/metadatad.cc b/src/metadatad.cc index f5636a46..90abd44e 100644 --- a/src/metadatad.cc +++ b/src/metadatad.cc @@ -76,6 +76,7 @@ int main(int ac, char** av) { return parse_result < 0 ? 0 : parse_result; } + ::google::RegisterAllViewsForExport(); google::MetadataAgent server(config); google::InstanceUpdater instance_updater(config, server.mutable_store()); @@ -93,9 +94,6 @@ int main(int ac, char** av) { server.Start(); - // Only register all the views after all the measures are initialized. - ::google::RegisterAllViewsForExport(); - // Wait for the server to shut down. google::cleanup_state->Wait(); } diff --git a/src/oauth2.cc b/src/oauth2.cc index 9900807e..bdcad0ff 100644 --- a/src/oauth2.cc +++ b/src/oauth2.cc @@ -149,11 +149,7 @@ OAuth2::OAuth2(const Environment& environment, std::unique_ptr expiration) : environment_(environment), token_expiration_(std::move(expiration)), - token_endpoint_(kDefaultTokenEndpoint) { - // Access the measure to ensure it is initialized. Otherwise, creating a view before - // any the first error would cause an error. - ::google::GceApiRequestErrors(); -} + token_endpoint_(kDefaultTokenEndpoint) {} json::value OAuth2::ComputeTokenFromCredentials() const { const std::string service_account_email = From d8b3e3799c086cb45c255d62ac1c911357e59e06 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Fri, 7 Dec 2018 13:39:50 -0500 Subject: [PATCH 16/36] fix format in test file. --- test/oauth2_unittest.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/oauth2_unittest.cc b/test/oauth2_unittest.cc index 9dae18c3..e2a79d05 100644 --- a/test/oauth2_unittest.cc +++ b/test/oauth2_unittest.cc @@ -141,15 +141,14 @@ TEST_F(OAuth2Test, GetApiRequestErrorMetric) { ::opencensus::stats::View errors_view( ::google::GceApiRequestErrorsCumulative()); - // no record exists before internal function sent request to oauth_server - EXPECT_THAT(errors_view.GetData().int_data(), - ::testing::UnorderedElementsAre()); + // No record exists before internal function sent request to oauth_server. + EXPECT_THAT(errors_view.GetData().int_data(), ::testing::IsEmpty()); auth.GetAuthHeaderValue(); ::opencensus::stats::testing::TestUtils::Flush(); EXPECT_THAT(errors_view.GetData().int_data(), - ::testing::UnorderedElementsAre(::testing::Pair( - ::testing::ElementsAre("oauth2"), 1))); + ::testing::UnorderedElementsAre( + ::testing::Pair(::testing::ElementsAre("oauth2"), 1))); } TEST_F(OAuth2Test, GetAuthHeaderValueTokenJsonMissingField) { From 93790ed198985b43e9f38d57ec417ed816e785b0 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Fri, 7 Dec 2018 13:42:55 -0500 Subject: [PATCH 17/36] revert header/constructor because no need anymore. --- src/agent.cc | 4 ++-- src/oauth2.cc | 9 --------- src/oauth2.h | 8 ++++++-- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/agent.cc b/src/agent.cc index 969cd434..2aaac90c 100644 --- a/src/agent.cc +++ b/src/agent.cc @@ -16,10 +16,10 @@ #include "agent.h" -#include "api_server.h" #include "configuration.h" -#include "health_checker.h" +#include "api_server.h" #include "reporter.h" +#include "health_checker.h" namespace google { diff --git a/src/oauth2.cc b/src/oauth2.cc index bdcad0ff..ff60a143 100644 --- a/src/oauth2.cc +++ b/src/oauth2.cc @@ -142,15 +142,6 @@ std::string Sign(const std::string& data, const PKey& pkey) { } // namespace -OAuth2::OAuth2(const Environment& environment) - : OAuth2(environment, ExpirationImpl::New()) {} - -OAuth2::OAuth2(const Environment& environment, - std::unique_ptr expiration) - : environment_(environment), - token_expiration_(std::move(expiration)), - token_endpoint_(kDefaultTokenEndpoint) {} - json::value OAuth2::ComputeTokenFromCredentials() const { const std::string service_account_email = environment_.CredentialsClientEmail(); diff --git a/src/oauth2.h b/src/oauth2.h index 6bbd1d97..4d48c4b5 100644 --- a/src/oauth2.h +++ b/src/oauth2.h @@ -33,12 +33,16 @@ constexpr const char kDefaultTokenEndpoint[] = class OAuth2 { public: - OAuth2(const Environment& environment); + OAuth2(const Environment& environment) + : OAuth2(environment, ExpirationImpl::New()) {} std::string GetAuthHeaderValue(); protected: - OAuth2(const Environment& environment, std::unique_ptr expiration); + OAuth2(const Environment& environment, std::unique_ptr expiration) + : environment_(environment), + token_expiration_(std::move(expiration)), + token_endpoint_(kDefaultTokenEndpoint) {} private: friend class OAuth2Test; From 786245f04984da28ac426213f7396f47d07800f8 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Fri, 7 Dec 2018 14:14:04 -0500 Subject: [PATCH 18/36] Wrap opencensus related code into a class. --- src/Makefile | 2 +- src/measures.h | 45 ---------------------------- src/metadatad.cc | 4 +-- src/{measures.cc => metrics.cc} | 52 +++++++++++++++++++-------------- src/metrics.h | 51 ++++++++++++++++++++++++++++++++ src/oauth2.cc | 6 ++-- test/Makefile | 4 +-- test/oauth2_unittest.cc | 4 +-- 8 files changed, 90 insertions(+), 78 deletions(-) delete mode 100644 src/measures.h rename src/{measures.cc => metrics.cc} (79%) create mode 100644 src/metrics.h diff --git a/src/Makefile b/src/Makefile index a31c77f1..cdf7c2c6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -112,7 +112,7 @@ SRCS=\ kubernetes.cc \ resource.cc \ oauth2.cc \ - measures.cc \ + metrics.cc \ internal/measures_utils.cc \ logging.cc \ local_stream_http.cc \ diff --git a/src/measures.h b/src/measures.h deleted file mode 100644 index bc879c9e..00000000 --- a/src/measures.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2018 Google Inc. - * - * 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. - **/ - -#ifndef METADATA_AGENT_MEASURES_H_ -#define METADATA_AGENT_MEASURES_H_ - -#include - -namespace google { - -// Measure accessors. If the measure variable is not initialized, these methods -// will initialize the variable. -// -// Reference of measure: https://opencensus.io/stats/measure/ -::opencensus::stats::MeasureInt64 GceApiRequestErrors(); - -// Tag key accessors. If the tag key variable is not initialized, these methods -// will initialize the variable. -// -// Reference of measure: https://opencensus.io/tag/key/ -::opencensus::stats::TagKey MethodTagKey(); - -// View Descriptor accessors. If the view descriptor variable is not -// initialized, these methods will initialize the variable. -const ::opencensus::stats::ViewDescriptor& GceApiRequestErrorsCumulative(); - -// Register all the view descriptors declared above as view for export. -void RegisterAllViewsForExport(); - -} // namespace google - -#endif /* METADATA_AGENT_MEASURES_H_ */ diff --git a/src/metadatad.cc b/src/metadatad.cc index 90abd44e..9702cc57 100644 --- a/src/metadatad.cc +++ b/src/metadatad.cc @@ -24,7 +24,7 @@ #include "docker.h" #include "instance.h" #include "kubernetes.h" -#include "measures.h" +#include "metrics.h" #include "time.h" namespace google { @@ -76,7 +76,7 @@ int main(int ac, char** av) { return parse_result < 0 ? 0 : parse_result; } - ::google::RegisterAllViewsForExport(); + ::google::Metrics::RegisterAllViewsForExport(); google::MetadataAgent server(config); google::InstanceUpdater instance_updater(config, server.mutable_store()); diff --git a/src/measures.cc b/src/metrics.cc similarity index 79% rename from src/measures.cc rename to src/metrics.cc index e82fa985..c830469a 100644 --- a/src/measures.cc +++ b/src/metrics.cc @@ -14,7 +14,7 @@ * limitations under the License. **/ -#include "measures.h" +#include "metrics.h" #include #include @@ -31,22 +31,26 @@ ABSL_CONST_INIT const absl::string_view kGceApiRequestErrors = "container.googleapis.com/internal/metadata_agent/gce_api_request_errors"; -::opencensus::stats::MeasureInt64 GceApiRequestErrors() { - static const auto measure = - ::opencensus::stats::MeasureInt64::Register( - kGceApiRequestErrors, - "Number of API request errors encountered.", - kCount); - return measure; -} +void Metrics::RegisterAllViewsForExport() { + // Access metrics used by views to ensure metrics are initalized. + GceApiRequestErrors(); -::opencensus::stats::TagKey MethodTagKey() { - static const auto method_tag_key = - ::opencensus::stats::TagKey::Register("method"); - return method_tag_key; + // Register all the views for export. + // + // To avoid view registration throwing error, when adding a new view, register + // measures used by this view in the section above. + GceApiRequestErrorsCumulative().RegisterForExport(); } -const ::opencensus::stats::ViewDescriptor& GceApiRequestErrorsCumulative() { +void Metrics::RecordGceApiRequestErrors(int64_t value, + const std::string& method) { + ::opencensus::stats::Record( + {{GceApiRequestErrors(), value}}, + {{MethodTagKey(), method}}); +}; + +const ::opencensus::stats::ViewDescriptor& + Metrics::GceApiRequestErrorsCumulative() { const static ::opencensus::stats::ViewDescriptor descriptor = ::opencensus::stats::ViewDescriptor() .set_name("gce_api_request_errors") @@ -56,15 +60,19 @@ const ::opencensus::stats::ViewDescriptor& GceApiRequestErrorsCumulative() { return descriptor; } -void RegisterAllViewsForExport() { - // Access metrics used by views to ensure metrics are initalized. - GceApiRequestErrors(); +::opencensus::stats::MeasureInt64 Metrics::GceApiRequestErrors() { + static const auto measure = + ::opencensus::stats::MeasureInt64::Register( + kGceApiRequestErrors, + "Number of API request errors encountered.", + kCount); + return measure; +} - // Register all the views for export. - // - // To avoid view registration throwing error, when adding a new view, register - // measures used by this view in the section above. - GceApiRequestErrorsCumulative().RegisterForExport(); +::opencensus::stats::TagKey Metrics::MethodTagKey() { + static const auto method_tag_key = + ::opencensus::stats::TagKey::Register("method"); + return method_tag_key; } } // namespace google diff --git a/src/metrics.h b/src/metrics.h new file mode 100644 index 00000000..8938a91e --- /dev/null +++ b/src/metrics.h @@ -0,0 +1,51 @@ +/* + * Copyright 2018 Google Inc. + * + * 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. + **/ + +#ifndef METADATA_AGENT_METRICS_H_ +#define METADATA_AGENT_METRICS_H_ + +#include + +namespace google { + +class Metrics { + public: + // Register all the view descriptors declared above as view for export. + static void RegisterAllViewsForExport(); + + static void RecordGceApiRequestErrors(int64_t value, const std::string& method); + + // View Descriptor accessors. If the view descriptor variable is not + // initialized, these methods will initialize the variable. + static const ::opencensus::stats::ViewDescriptor& GceApiRequestErrorsCumulative(); + + private: + // Measure accessors. If the measure variable is not initialized, these methods + // will initialize the variable. + // + // Reference of measure: https://opencensus.io/stats/measure/ + static ::opencensus::stats::MeasureInt64 GceApiRequestErrors(); + + // Tag key accessors. If the tag key variable is not initialized, these methods + // will initialize the variable. + // + // Reference of measure: https://opencensus.io/tag/key/ + static ::opencensus::stats::TagKey MethodTagKey(); +}; + +} // namespace google + +#endif /* METADATA_AGENT_METRICS_H_ */ diff --git a/src/oauth2.cc b/src/oauth2.cc index ff60a143..56b6fde4 100644 --- a/src/oauth2.cc +++ b/src/oauth2.cc @@ -32,7 +32,7 @@ #include "http_common.h" #include "json.h" #include "logging.h" -#include "measures.h" +#include "metrics.h" #include "time.h" namespace http = boost::network::http; @@ -254,9 +254,7 @@ json::value OAuth2::ComputeTokenFromCredentials() const { LOG(ERROR) << "HTTP error: " << e.what(); } - ::opencensus::stats::Record( - {{::google::GceApiRequestErrors(), 1}}, - {{::google::MethodTagKey(), "oauth2"}}); + ::google::Metrics::RecordGceApiRequestErrors(1, "oauth2"); return nullptr; } diff --git a/test/Makefile b/test/Makefile index 6acfc787..164a7ba8 100644 --- a/test/Makefile +++ b/test/Makefile @@ -232,11 +232,11 @@ kubernetes_unittest: kubernetes_unittest.o fake_http_server.o $(SRC_DIR)/kuberne $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ logging_unittest: logging_unittest.o $(SRC_DIR)/logging.o $(SRC_DIR)/time.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ -oauth2_unittest: oauth2_unittest.o fake_clock.o fake_http_server.o $(SRC_DIR)/oauth2.o $(SRC_DIR)/base64.o $(SRC_DIR)/configuration.o $(SRC_DIR)/environment.o $(SRC_DIR)/format.o $(SRC_DIR)/json.o $(SRC_DIR)/logging.o $(SRC_DIR)/measures.o $(SRC_DIR)/time.o +oauth2_unittest: oauth2_unittest.o fake_clock.o fake_http_server.o $(SRC_DIR)/oauth2.o $(SRC_DIR)/base64.o $(SRC_DIR)/configuration.o $(SRC_DIR)/environment.o $(SRC_DIR)/format.o $(SRC_DIR)/json.o $(SRC_DIR)/logging.o $(SRC_DIR)/metrics.o $(SRC_DIR)/time.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ resource_unittest: resource_unittest.o $(SRC_DIR)/resource.o $(SRC_DIR)/json.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ -reporter_unittest: reporter_unittest.o fake_clock.o fake_http_server.o $(SRC_DIR)/reporter.o $(SRC_DIR)/base64.o $(SRC_DIR)/configuration.o $(SRC_DIR)/environment.o $(SRC_DIR)/format.o $(SRC_DIR)/json.o $(SRC_DIR)/logging.o $(SRC_DIR)/measures.o $(SRC_DIR)/oauth2.o $(SRC_DIR)/resource.o $(SRC_DIR)/store.o $(SRC_DIR)/time.o +reporter_unittest: reporter_unittest.o fake_clock.o fake_http_server.o $(SRC_DIR)/reporter.o $(SRC_DIR)/base64.o $(SRC_DIR)/configuration.o $(SRC_DIR)/environment.o $(SRC_DIR)/format.o $(SRC_DIR)/json.o $(SRC_DIR)/logging.o $(SRC_DIR)/metrics.o $(SRC_DIR)/oauth2.o $(SRC_DIR)/resource.o $(SRC_DIR)/store.o $(SRC_DIR)/time.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ store_unittest: store_unittest.o $(SRC_DIR)/store.o $(SRC_DIR)/resource.o $(SRC_DIR)/json.o $(SRC_DIR)/logging.o $(SRC_DIR)/time.o $(SRC_DIR)/configuration.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ diff --git a/test/oauth2_unittest.cc b/test/oauth2_unittest.cc index e2a79d05..16ee0e49 100644 --- a/test/oauth2_unittest.cc +++ b/test/oauth2_unittest.cc @@ -16,7 +16,7 @@ #include "../src/oauth2.h" -#include "../src/measures.h" +#include "../src/metrics.h" #include "environment_util.h" #include "fake_clock.h" #include "fake_http_server.h" @@ -139,7 +139,7 @@ TEST_F(OAuth2Test, GetApiRequestErrorMetric) { SetTokenEndpointForTest(&auth, oauth_server.GetUrl() + "/oauth2/v3/token"); ::opencensus::stats::View errors_view( - ::google::GceApiRequestErrorsCumulative()); + ::google::Metrics::GceApiRequestErrorsCumulative()); // No record exists before internal function sent request to oauth_server. EXPECT_THAT(errors_view.GetData().int_data(), ::testing::IsEmpty()); From c22faacac2045ce833fb030b6cf77f0669de822d Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Fri, 7 Dec 2018 14:24:00 -0500 Subject: [PATCH 19/36] Move util function into Metrics Class. --- src/Makefile | 1 - src/api_server.cc | 5 +-- src/internal/measures_utils.cc | 34 ------------------- src/internal/measures_utils.h | 30 ---------------- src/metrics.cc | 10 ++++++ src/metrics.h | 3 ++ test/Makefile | 8 ++--- ..._utils_unittest.cc => metrics_unittest.cc} | 7 ++-- 8 files changed, 23 insertions(+), 75 deletions(-) delete mode 100644 src/internal/measures_utils.cc delete mode 100644 src/internal/measures_utils.h rename test/{internal/measures_utils_unittest.cc => metrics_unittest.cc} (82%) diff --git a/src/Makefile b/src/Makefile index cdf7c2c6..1e7657b5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -113,7 +113,6 @@ SRCS=\ resource.cc \ oauth2.cc \ metrics.cc \ - internal/measures_utils.cc \ logging.cc \ local_stream_http.cc \ local_stream_delegate.cc \ diff --git a/src/api_server.cc b/src/api_server.cc index dcd64618..4f196d1d 100644 --- a/src/api_server.cc +++ b/src/api_server.cc @@ -21,7 +21,7 @@ #include "configuration.h" #include "health_checker.h" #include "http_common.h" -#include "internal/measures_utils.h" +#include "metrics.h" #include "logging.h" #include "store.h" @@ -209,7 +209,8 @@ void MetadataApiServer::HandleHealthz( void MetadataApiServer::HandleMetrics( const HttpServer::request& request, std::shared_ptr conn) { - std::string response = internal::SerializeMetricsToPrometheusTextFormat(); + std::string response = + ::google::Metrics::SerializeMetricsToPrometheusTextFormat(); conn->set_status(HttpServer::connection::ok); conn->set_headers(std::map({ {"Connection", "close"}, diff --git a/src/internal/measures_utils.cc b/src/internal/measures_utils.cc deleted file mode 100644 index 0c79abc9..00000000 --- a/src/internal/measures_utils.cc +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2018 Google Inc. - * - * 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 "measures_utils.h" - -#include -#include - -namespace google { -namespace internal { - -std::string SerializeMetricsToPrometheusTextFormat() { - static const auto* const text_serializer = - new ::prometheus::TextSerializer(); - static auto* const exporter = - new ::opencensus::exporters::stats::PrometheusExporter(); - return text_serializer->Serialize(exporter->Collect()); -} - -} // namespace internal -} // namespace google diff --git a/src/internal/measures_utils.h b/src/internal/measures_utils.h deleted file mode 100644 index 66fd7705..00000000 --- a/src/internal/measures_utils.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2018 Google Inc. - * - * 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. - **/ - -#ifndef METADATA_AGENT_INTERNAL_MEASURES_UTILS_H_ -#define METADATA_AGENT_INTERNAL_MEASURES_UTILS_H_ - -#include - -namespace google { -namespace internal { - -std::string SerializeMetricsToPrometheusTextFormat(); - -} // namespace internal -} // namespace google - -#endif /* METADATA_AGENT_INTERNAL_MEASURES_UTILS_H_ */ diff --git a/src/metrics.cc b/src/metrics.cc index c830469a..39fccd1e 100644 --- a/src/metrics.cc +++ b/src/metrics.cc @@ -17,7 +17,9 @@ #include "metrics.h" #include +#include #include +#include namespace google { @@ -60,6 +62,14 @@ const ::opencensus::stats::ViewDescriptor& return descriptor; } +std::string Metrics::SerializeMetricsToPrometheusTextFormat() { + static const auto* const text_serializer = + new ::prometheus::TextSerializer(); + static auto* const exporter = + new ::opencensus::exporters::stats::PrometheusExporter(); + return text_serializer->Serialize(exporter->Collect()); +} + ::opencensus::stats::MeasureInt64 Metrics::GceApiRequestErrors() { static const auto measure = ::opencensus::stats::MeasureInt64::Register( diff --git a/src/metrics.h b/src/metrics.h index 8938a91e..f888879b 100644 --- a/src/metrics.h +++ b/src/metrics.h @@ -18,6 +18,7 @@ #define METADATA_AGENT_METRICS_H_ #include +#include namespace google { @@ -32,6 +33,8 @@ class Metrics { // initialized, these methods will initialize the variable. static const ::opencensus::stats::ViewDescriptor& GceApiRequestErrorsCumulative(); + static std::string SerializeMetricsToPrometheusTextFormat(); + private: // Measure accessors. If the measure variable is not initialized, these methods // will initialize the variable. diff --git a/test/Makefile b/test/Makefile index 164a7ba8..985bee24 100644 --- a/test/Makefile +++ b/test/Makefile @@ -129,7 +129,6 @@ TEST_DIR=. TEST_SOURCES=$(wildcard $(TEST_DIR)/*_unittest.cc) TEST_OBJS=$(TEST_SOURCES:$(TEST_DIR)/%.cc=%.o) TESTS=\ - internal/measures_utils_unittest \ api_server_unittest \ base64_unittest \ configuration_unittest \ @@ -137,6 +136,7 @@ TESTS=\ format_unittest \ health_checker_unittest \ instance_unittest \ + metrics_unittest \ json_unittest \ kubernetes_unittest \ logging_unittest \ @@ -210,9 +210,7 @@ $(TESTS): $(GTEST_LIB) $(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) $(PROMETHEUS_CPP_LIBS # Some headers need CPP_NETLIB_LIBS and YAML_CPP_LIBS. $(TESTS:%=%.o): $(GTEST_LIB) $(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) $(PROMETHEUS_CPP_LIBS) $(OPENCENSUS_CPP_LIBS) -internal/measures_utils_unittest: internal/measures_utils_unittest.o $(SRC_DIR)/internal/measures_utils.o - $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ -api_server_unittest: api_server_unittest.o $(SRC_DIR)/api_server.o $(SRC_DIR)/internal/measures_utils.o $(SRC_DIR)/configuration.o $(SRC_DIR)/store.o $(SRC_DIR)/json.o $(SRC_DIR)/resource.o $(SRC_DIR)/logging.o $(SRC_DIR)/time.o $(SRC_DIR)/health_checker.o +api_server_unittest: api_server_unittest.o $(SRC_DIR)/api_server.o $(SRC_DIR)/metrics.o $(SRC_DIR)/configuration.o $(SRC_DIR)/store.o $(SRC_DIR)/json.o $(SRC_DIR)/resource.o $(SRC_DIR)/logging.o $(SRC_DIR)/time.o $(SRC_DIR)/health_checker.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ base64_unittest: base64_unittest.o $(SRC_DIR)/base64.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ @@ -232,6 +230,8 @@ kubernetes_unittest: kubernetes_unittest.o fake_http_server.o $(SRC_DIR)/kuberne $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ logging_unittest: logging_unittest.o $(SRC_DIR)/logging.o $(SRC_DIR)/time.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ +metrics_unittest: metrics_unittest.o $(SRC_DIR)/metrics.o + $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ oauth2_unittest: oauth2_unittest.o fake_clock.o fake_http_server.o $(SRC_DIR)/oauth2.o $(SRC_DIR)/base64.o $(SRC_DIR)/configuration.o $(SRC_DIR)/environment.o $(SRC_DIR)/format.o $(SRC_DIR)/json.o $(SRC_DIR)/logging.o $(SRC_DIR)/metrics.o $(SRC_DIR)/time.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ resource_unittest: resource_unittest.o $(SRC_DIR)/resource.o $(SRC_DIR)/json.o diff --git a/test/internal/measures_utils_unittest.cc b/test/metrics_unittest.cc similarity index 82% rename from test/internal/measures_utils_unittest.cc rename to test/metrics_unittest.cc index d9dc699c..7a8eb523 100644 --- a/test/internal/measures_utils_unittest.cc +++ b/test/metrics_unittest.cc @@ -14,15 +14,14 @@ * limitations under the License. **/ -#include "../../src/internal/measures_utils.h" +#include "../../src/metrics.h" #include "gtest/gtest.h" namespace google { -namespace internal { TEST(SerializeToPrometheusTextTest, Initialization) { - EXPECT_EQ("", SerializeMetricsToPrometheusTextFormat()); + EXPECT_EQ("", + ::google::Metrics::SerializeMetricsToPrometheusTextFormat()); } -} // namespace internal } // namespace google From cdfe9c1dcae48cad6a1ac7dbe1fb73edf67657a4 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Fri, 7 Dec 2018 14:53:15 -0500 Subject: [PATCH 20/36] remove explicit dependency on prometheus-cpp. --- src/Makefile | 47 +++++++++++++++-------------------------------- test/Makefile | 32 ++++++++++++++------------------ 2 files changed, 29 insertions(+), 50 deletions(-) diff --git a/src/Makefile b/src/Makefile index 1e7657b5..7e2b21af 100644 --- a/src/Makefile +++ b/src/Makefile @@ -23,15 +23,15 @@ NETWORK_URI_DIR=$(CPP_NETLIB_DIR)/deps/uri NETWORK_URI_LIBDIR=$(NETWORK_URI_DIR)/src YAML_CPP_DIR=$(LIBDIR)/yaml-cpp YAML_CPP_LIBDIR=$(YAML_CPP_DIR) -PROMETHEUS_CPP_DIR=$(LIBDIR)/prometheus-cpp -PROMETHEUS_CPP_CORE_DIR=$(PROMETHEUS_CPP_DIR)/core -PROMETHEUS_CPP_CORE_LIBDIR=$(PROMETHEUS_CPP_CORE_DIR) OPENCENSUS_CPP_DIR=$(LIBDIR)/opencensus-cpp OPENCENSUS_CPP_OPENCENSUS_DIR=$(OPENCENSUS_CPP_DIR)/opencensus OPENCENSUS_CPP_OPENCENSUS_LIBDIR=$(OPENCENSUS_CPP_OPENCENSUS_DIR) OPENCENSUS_CPP_ABSL_INCLUDEDIR=$(OPENCENSUS_CPP_DIR)/abseil-src OPENCENSUS_CPP_ABSL_LIBDIR=$(OPENCENSUS_CPP_DIR)/abseil-build/absl -SUBMODULE_DIRS=$(CPP_NETLIB_DIR) $(YAML_CPP_DIR) $(PROMETHEUS_CPP_DIR) $(OPENCENSUS_CPP_DIR) +OPENCENSUS_CPP_PROMETHEUS_CPP_DIR=$(OPENCENSUS_CPP_DIR)/prometheus-src +OPENCENSUS_CPP_PROMETHEUS_CPP_CORE_DIR=$(OPENCENSUS_CPP_PROMETHEUS_CPP_DIR)/core +OPENCENSUS_CPP_PROMETHEUS_CPP_CORE_LIBDIR=$(OPENCENSUS_CPP_DIR)/prometheus-build/core +SUBMODULE_DIRS=$(CPP_NETLIB_DIR) $(YAML_CPP_DIR) $(OPENCENSUS_CPP_DIR) GIT=git GIT_VERSION=$(shell $(GIT) --version | grep -oh '[0-9]\+\.[0-9]\+\.[0-9]\+') @@ -42,21 +42,21 @@ CPPFLAGS=\ -DAGENT_VERSION='$(PKG_VERSION)-$(PKG_RELEASE)' \ -DENABLE_DOCKER_METADATA \ -I$(CPP_NETLIB_DIR) -I$(NETWORK_URI_DIR)/include -I$(YAML_CPP_DIR)/include \ - -I$(PROMETHEUS_CPP_CORE_DIR)/include -I$(OPENCENSUS_CPP_DIR) \ - -I$(OPENCENSUS_CPP_ABSL_INCLUDEDIR) + -I$(OPENCENSUS_CPP_DIR) -I$(OPENCENSUS_CPP_ABSL_INCLUDEDIR) \ + -I$(OPENCENSUS_CPP_PROMETHEUS_CPP_CORE_DIR)/include CXXFLAGS=\ -std=c++11 -g -pthread -Wno-write-strings -Wno-deprecated LDFLAGS=\ -L$(CPP_NETLIB_LIBDIR) \ -L$(NETWORK_URI_LIBDIR) \ -L$(YAML_CPP_LIBDIR) \ - -L$(PROMETHEUS_CPP_CORE_LIBDIR) \ -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/stats \ -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/context \ -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/exporters/stats/prometheus \ -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/trace \ -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/tags \ -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/common/internal \ + -L$(OPENCENSUS_CPP_PROMETHEUS_CPP_CORE_LIBDIR) \ -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/numeric \ -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/strings \ -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/synchronization \ @@ -66,7 +66,7 @@ LDFLAGS=\ LDLIBS=\ -lcppnetlib-client-connections -lcppnetlib-server-parsers -lnetwork-uri \ -lboost_program_options -lboost_system -lboost_thread -lboost_filesystem \ - -lpthread -lyajl -lssl -lcrypto -lyaml-cpp -lprometheus-cpp-core \ + -lpthread -lyajl -lssl -lcrypto -lyaml-cpp \ -lopencensus_exporters_stats_prometheus \ -lopencensus_exporters_stats_prometheus_utils \ -lopencensus_stats_core -lopencensus_stats_recording \ @@ -76,6 +76,7 @@ LDLIBS=\ -lopencensus_trace_with_span \ -lopencensus_trace \ -lopencensus_common_random \ + -lprometheus-cpp-core \ -labsl_strings -labsl_synchronization -labsl_time \ -labsl_int128 \ -labsl_stacktrace -labsl_symbolize \ @@ -130,8 +131,6 @@ CPP_NETLIB_LIBS=\ $(NETWORK_URI_LIBDIR)/libnetwork-uri.a YAML_CPP_LIBS=\ $(YAML_CPP_LIBDIR)/libyaml-cpp.a -PROMETHEUS_CPP_LIBS=\ - $(PROMETHEUS_CPP_CORE_LIBDIR)/libprometheus-cpp-core.a OPENCENSUS_CPP_LIBS=\ $(OPENCENSUS_CPP_ABSL_LIBDIR)/base/libabsl_base.a \ $(OPENCENSUS_CPP_ABSL_LIBDIR)/base/libabsl_internal_malloc_internal.a \ @@ -156,8 +155,9 @@ OPENCENSUS_CPP_LIBS=\ $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/trace/libopencensus_trace_with_span.a \ $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/trace/libopencensus_trace_context_util.a \ $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/context/libopencensus_context.a \ - $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/common/internal/libopencensus_common_random.a -LIBS=$(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) $(PROMETHEUS_CPP_LIBS) $(OPENCENSUS_CPP_LIBS) + $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/common/internal/libopencensus_common_random.a \ + $(OPENCENSUS_CPP_PROMETHEUS_CPP_CORE_LIBDIR)/libprometheus-cpp-core.a +LIBS=$(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) $(OPENCENSUS_CPP_LIBS) sbindir=/opt/stackdriver/metadata/sbin INSTALL=/usr/bin/install @@ -236,7 +236,7 @@ clean: $(RM) metadatad $(OBJS) purge: clean - $(RM) -r init-submodules build-cpp-netlib build-yaml-cpp build-prometheus-cpp build-opencensus-cpp + $(RM) -r init-submodules build-cpp-netlib build-yaml-cpp build-opencensus-cpp (cd .. && git submodule deinit -f $(SUBMODULE_DIRS:../%=%)) init-submodules: @@ -252,8 +252,6 @@ ifneq ($(findstring $(GIT_VERSION),2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.8 deps/*/.git cd $(CPP_NETLIB_DIR) && $(SED_I) -e 's@/src/.git/@../../../../../../../.git/@' \ libs/network/doc/_ext/breathe/.git - cd $(PROMETHEUS_CPP_DIR) && $(SED_I) -e 's@/src/.git/@../../../../.git/@' \ - 3rdparty/*/.git endif touch init-submodules @@ -288,20 +286,6 @@ build-yaml-cpp: $(YAML_CPP_DIR)/Makefile $(MAKE) touch build-yaml-cpp -$(PROMETHEUS_CPP_DIR)/Makefile: init-submodules - cd $(PROMETHEUS_CPP_DIR) && \ - $(CMAKE) -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS=-std=c++11 \ - -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ \ - -DENABLE_PUSH=OFF -DENABLE_PULL=OFF -DENABLE_COMPRESSION=OFF \ - -DENABLE_TESTING=OFF - -$(PROMETHEUS_CPP_LIBS): build-prometheus-cpp - -build-prometheus-cpp: $(PROMETHEUS_CPP_DIR)/Makefile - cd $(PROMETHEUS_CPP_DIR) && \ - $(MAKE) - touch build-prometheus-cpp - $(OPENCENSUS_CPP_DIR)/Makefile: init-submodules cd $(OPENCENSUS_CPP_DIR) && \ $(CMAKE) -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS=-std=c++11 \ @@ -317,11 +301,10 @@ build-opencensus-cpp: $(OPENCENSUS_CPP_DIR)/Makefile cpp-netlib: $(CPP_NETLIB_LIBS) yaml-cpp: $(YAML_CPP_LIBS) -prometheus-cpp: $(PROMETHEUS_CPP_LIBS) opencensus-cpp: $(OPENCENSUS_CPP_LIBS) -submodules: cpp-netlib yaml-cpp prometheus-cpp opencensus-cpp +submodules: cpp-netlib yaml-cpp opencensus-cpp all: submodules metadatad -.PHONY: all submodules cpp-netlib yaml-cpp prometheus-cpp opencensus-cpp purge clean install deb rpm +.PHONY: all submodules cpp-netlib yaml-cpp opencensus-cpp purge clean install deb rpm diff --git a/test/Makefile b/test/Makefile index 985bee24..4db8a760 100644 --- a/test/Makefile +++ b/test/Makefile @@ -32,22 +32,20 @@ NETWORK_URI_DIR=$(CPP_NETLIB_DIR)/deps/uri NETWORK_URI_LIBDIR=$(NETWORK_URI_DIR)/src YAML_CPP_DIR=$(LIBDIR)/yaml-cpp YAML_CPP_LIBDIR=$(YAML_CPP_DIR) -PROMETHEUS_CPP_DIR=$(LIBDIR)/prometheus-cpp -PROMETHEUS_CPP_LIBDIR=$(PROMETHEUS_CPP_DIR) -PROMETHEUS_CPP_CORE_LIBDIR=$(PROMETHEUS_CPP_LIBDIR)/core OPENCENSUS_CPP_DIR=$(LIBDIR)/opencensus-cpp OPENCENSUS_CPP_OPENCENSUS_DIR=$(OPENCENSUS_CPP_DIR)/opencensus OPENCENSUS_CPP_OPENCENSUS_LIBDIR=$(OPENCENSUS_CPP_OPENCENSUS_DIR) OPENCENSUS_CPP_ABSL_INCLUDEDIR=$(OPENCENSUS_CPP_DIR)/abseil-src OPENCENSUS_CPP_ABSL_LIBDIR=$(OPENCENSUS_CPP_DIR)/abseil-build/absl +OPENCENSUS_CPP_PROMETHEUS_CPP_DIR=$(OPENCENSUS_CPP_DIR)/prometheus-src +OPENCENSUS_CPP_PROMETHEUS_CPP_CORE_DIR=$(OPENCENSUS_CPP_PROMETHEUS_CPP_DIR)/core +OPENCENSUS_CPP_PROMETHEUS_CPP_CORE_LIBDIR=$(OPENCENSUS_CPP_DIR)/prometheus-build/core CPP_NETLIB_LIBS=\ $(CPP_NETLIB_LIBDIR)/libcppnetlib-client-connections.a \ $(CPP_NETLIB_LIBDIR)/libcppnetlib-server-parsers.a \ $(NETWORK_URI_LIBDIR)/libnetwork-uri.a YAML_CPP_LIBS=$(YAML_CPP_LIBDIR)/libyaml-cpp.a -PROMETHEUS_CPP_LIBS=\ - $(PROMETHEUS_CPP_CORE_LIBDIR)/libprometheus-cpp-core.a OPENCENSUS_CPP_LIBS=\ $(OPENCENSUS_CPP_ABSL_LIBDIR)/base/libabsl_base.a \ $(OPENCENSUS_CPP_ABSL_LIBDIR)/base/libabsl_internal_malloc_internal.a \ @@ -63,20 +61,19 @@ OPENCENSUS_CPP_LIBS=\ $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/exporters/stats/stdout/libopencensus_exporters_stats_stdout.a \ $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/stats/libopencensus_stats_core.a \ $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/stats/libopencensus_stats_test_utils.a \ - $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/tags/libopencensus_tags.a - + $(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/tags/libopencensus_tags.a \ + $(OPENCENSUS_CPP_PROMETHEUS_CPP_CORE_LIBDIR)/libprometheus-cpp-core.a CPPFLAGS+= \ -isystem $(GTEST_DIR)/include -I$(GMOCK_DIR)/include \ -I$(CPP_NETLIB_DIR) -I$(NETWORK_URI_DIR)/include -I$(YAML_CPP_DIR)/include \ - -I$(PROMETHEUS_CPP_CORE_LIBDIR)/include \ - -I$(OPENCENSUS_CPP_DIR) -I$(OPENCENSUS_CPP_ABSL_INCLUDEDIR) + -I$(OPENCENSUS_CPP_DIR) -I$(OPENCENSUS_CPP_ABSL_INCLUDEDIR) \ + -I$(OPENCENSUS_CPP_PROMETHEUS_CPP_CORE_DIR)/include CXXFLAGS=\ -std=c++11 -g -pthread -Wno-write-strings -Wno-deprecated LDFLAGS=\ -L$(CPP_NETLIB_LIBDIR) \ -L$(NETWORK_URI_LIBDIR) \ -L$(YAML_CPP_LIBDIR) \ - -L$(PROMETHEUS_CPP_CORE_LIBDIR) \ -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/stats \ -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/context \ -L$(OPENCENSUS_CPP_OPENCENSUS_LIBDIR)/exporters/stats/prometheus \ @@ -88,12 +85,12 @@ LDFLAGS=\ -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/synchronization \ -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/time \ -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/debugging \ - -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/base + -L$(OPENCENSUS_CPP_ABSL_LIBDIR)/base \ + -L$(OPENCENSUS_CPP_PROMETHEUS_CPP_CORE_LIBDIR) LDLIBS=\ -lcppnetlib-client-connections -lcppnetlib-server-parsers -lnetwork-uri \ -lboost_program_options -lboost_system -lboost_thread -lboost_filesystem \ -lboost_regex -lpthread -lyajl -lssl -lcrypto -lyaml-cpp \ - -lprometheus-cpp-core \ -lopencensus_exporters_stats_prometheus \ -lopencensus_exporters_stats_prometheus_utils \ -lopencensus_stats_core -lopencensus_stats_test_utils -lopencensus_stats_recording \ @@ -103,6 +100,7 @@ LDLIBS=\ -lopencensus_trace_with_span \ -lopencensus_trace \ -lopencensus_common_random \ + -lprometheus-cpp-core \ -labsl_strings -labsl_synchronization -labsl_time \ -labsl_int128 \ -labsl_stacktrace -labsl_symbolize \ @@ -176,18 +174,16 @@ init-submodules: $(SRC_DIR)/init-submodules: cd $(SRC_DIR) && $(MAKE) $(@:$(SRC_DIR)/%=%) -$(SRC_DIR)/build-cpp-netlib $(SRC_DIR)/build-yaml-cpp $(SRC_DIR)/build-prometheus-cpp $(SRC_DIR)/build-opencensus-cpp: $(SRC_DIR)/init-submodules +$(SRC_DIR)/build-cpp-netlib $(SRC_DIR)/build-yaml-cpp $(SRC_DIR)/build-opencensus-cpp: $(SRC_DIR)/init-submodules cd $(SRC_DIR) && $(MAKE) $(@:$(SRC_DIR)/%=%) $(CPP_NETLIB_LIBS): $(SRC_DIR)/build-cpp-netlib $(YAML_CPP_LIBS): $(SRC_DIR)/build-yaml-cpp -$(PROMETHEUS_CPP_LIBS): $(SRC_DIR)/build-prometheus-cpp - $(OPENCENSUS_CPP_LIBS): $(SRC_DIR)/build-opencensus-cpp -$(SRC_DIR)/%.o: $(SRC_DIR)/build-cpp-netlib $(SRC_DIR)/build-yaml-cpp $(SRC_DIR)/build-prometheus-cpp $(SRC_DIR)/build-opencensus-cpp $(SRC_DIR)/%.cc +$(SRC_DIR)/%.o: $(SRC_DIR)/build-cpp-netlib $(SRC_DIR)/build-yaml-cpp $(SRC_DIR)/build-opencensus-cpp $(SRC_DIR)/%.cc cd $(SRC_DIR) && $(MAKE) $(@:$(SRC_DIR)/%=%) $(GTEST_SOURCEDIR)/gtest-all.cc: init-submodules @@ -204,11 +200,11 @@ gmock_main.o: $(GMOCK_SOURCEDIR)/gmock_main.cc $(GTEST_LIB): gtest-all.o gmock-all.o gmock_main.o $(AR) $(ARFLAGS) $@ $^ -$(TESTS): $(GTEST_LIB) $(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) $(PROMETHEUS_CPP_LIBS) $(OPENCENSUS_CPP_LIBS) +$(TESTS): $(GTEST_LIB) $(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) $(OPENCENSUS_CPP_LIBS) # All unittest objects depend on GTEST_LIB. # Some headers need CPP_NETLIB_LIBS and YAML_CPP_LIBS. -$(TESTS:%=%.o): $(GTEST_LIB) $(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) $(PROMETHEUS_CPP_LIBS) $(OPENCENSUS_CPP_LIBS) +$(TESTS:%=%.o): $(GTEST_LIB) $(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) $(OPENCENSUS_CPP_LIBS) api_server_unittest: api_server_unittest.o $(SRC_DIR)/api_server.o $(SRC_DIR)/metrics.o $(SRC_DIR)/configuration.o $(SRC_DIR)/store.o $(SRC_DIR)/json.o $(SRC_DIR)/resource.o $(SRC_DIR)/logging.o $(SRC_DIR)/time.o $(SRC_DIR)/health_checker.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ From 7514b25abe899d3bfe85244532b8453b87c7ef4c Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Fri, 7 Dec 2018 14:55:04 -0500 Subject: [PATCH 21/36] Clean up prometheus-cpp dependency on gitmodules as well. --- .gitmodules | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index 35b7a4e4..7f232799 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,9 +10,7 @@ path = lib/googletest url = https://github.com/google/googletest ignore = dirty -[submodule "lib/prometheus-cpp"] - path = lib/prometheus-cpp - url = https://github.com/jupp0r/prometheus-cpp [submodule "lib/opencensus-cpp"] path = lib/opencensus-cpp url = https://github.com/census-instrumentation/opencensus-cpp + ignore = dirty \ No newline at end of file From 4f3788278282407529c63f9bc3fc9af1ba2186e8 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Fri, 7 Dec 2018 14:59:55 -0500 Subject: [PATCH 22/36] Revert submodules on prometheus-cpp. --- lib/prometheus-cpp | 1 - 1 file changed, 1 deletion(-) delete mode 160000 lib/prometheus-cpp diff --git a/lib/prometheus-cpp b/lib/prometheus-cpp deleted file mode 160000 index e14ba416..00000000 --- a/lib/prometheus-cpp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e14ba416e9bcde4439a3bf14fbdb93ef35321ae4 From 96b268a24c7f869a7d8df260af730f96830e93ff Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Fri, 7 Dec 2018 15:21:15 -0500 Subject: [PATCH 23/36] Revert chnage for prometheus-cpp. --- src/.gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/src/.gitignore b/src/.gitignore index 85b85877..def7fad5 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,6 +1,5 @@ init-submodules build-cpp-netlib build-yaml-cpp -build-prometheus-cpp build-opencensus-cpp metadatad From 64929c839d78198658fdf952d9dbb0c5d1175b3f Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Fri, 7 Dec 2018 15:25:12 -0500 Subject: [PATCH 24/36] Flush metrics only within one test, and add comments. --- test/oauth2_unittest.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/oauth2_unittest.cc b/test/oauth2_unittest.cc index 16ee0e49..77f987c5 100644 --- a/test/oauth2_unittest.cc +++ b/test/oauth2_unittest.cc @@ -32,10 +32,6 @@ namespace google { class OAuth2Test : public ::testing::Test { protected: - void SetUp() override { - ::opencensus::stats::testing::TestUtils::Flush(); - } - static void SetTokenEndpointForTest(OAuth2* auth, const std::string& endpoint) { auth->SetTokenEndpointForTest(endpoint); @@ -126,7 +122,10 @@ TEST_F(OAuth2Test, GetAuthHeaderValueUsingTokenFromMetadataServerAsFallback) { EXPECT_EQ("Bearer the-access-token", auth.GetAuthHeaderValue()); } -TEST_F(OAuth2Test, GetApiRequestErrorMetric) { +TEST_F(OAuth2Test, PropagateGceApiRequestErrorsCumulativeToView) { + // Flush to prevents other test contaminate the metrics. + ::opencensus::stats::testing::TestUtils::Flush(); + testing::FakeServer oauth_server; testing::TemporaryFile credentials_file( std::string(test_info_->name()) + "_creds.json", @@ -145,7 +144,10 @@ TEST_F(OAuth2Test, GetApiRequestErrorMetric) { EXPECT_THAT(errors_view.GetData().int_data(), ::testing::IsEmpty()); auth.GetAuthHeaderValue(); + + // Flush to propagate recorded stats to views. ::opencensus::stats::testing::TestUtils::Flush(); + EXPECT_THAT(errors_view.GetData().int_data(), ::testing::UnorderedElementsAre( ::testing::Pair(::testing::ElementsAre("oauth2"), 1))); From 88830d0d3f616db03c5ad7baf5b3aef63ac51445 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Fri, 7 Dec 2018 17:20:20 -0500 Subject: [PATCH 25/36] Avoid using string_view for constant string. --- src/metrics.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/metrics.cc b/src/metrics.cc index 39fccd1e..923c7708 100644 --- a/src/metrics.cc +++ b/src/metrics.cc @@ -25,7 +25,7 @@ namespace google { namespace { -ABSL_CONST_INIT const absl::string_view kCount = "1"; +constexpr const char kCount[] = "1"; } // namespace From 6ee8ab800e59a9272df8b75a38ce5efa9fd9d1c9 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Mon, 10 Dec 2018 07:11:40 +0000 Subject: [PATCH 26/36] Use constexpr consistently. --- src/metrics.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/metrics.cc b/src/metrics.cc index 923c7708..7cd74cf0 100644 --- a/src/metrics.cc +++ b/src/metrics.cc @@ -16,7 +16,6 @@ #include "metrics.h" -#include #include #include #include @@ -25,12 +24,11 @@ namespace google { namespace { -constexpr const char kCount[] = "1"; +constexpr char kCount[] = "1"; } // namespace -ABSL_CONST_INIT const absl::string_view - kGceApiRequestErrors = +constexpr char kGceApiRequestErrors[] = "container.googleapis.com/internal/metadata_agent/gce_api_request_errors"; void Metrics::RegisterAllViewsForExport() { From bee8a32f7252e3ac1758afc9cb7fa5c4b9d8fba5 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Mon, 10 Dec 2018 07:20:05 +0000 Subject: [PATCH 27/36] Refactor code, fix tests which is not idempotent. --- src/metadatad.cc | 2 -- src/metrics.cc | 69 +++++++++++++++++++++-------------------- src/metrics.h | 21 +++++-------- test/oauth2_unittest.cc | 18 +++++------ 4 files changed, 52 insertions(+), 58 deletions(-) diff --git a/src/metadatad.cc b/src/metadatad.cc index 9702cc57..7363d2f5 100644 --- a/src/metadatad.cc +++ b/src/metadatad.cc @@ -24,7 +24,6 @@ #include "docker.h" #include "instance.h" #include "kubernetes.h" -#include "metrics.h" #include "time.h" namespace google { @@ -76,7 +75,6 @@ int main(int ac, char** av) { return parse_result < 0 ? 0 : parse_result; } - ::google::Metrics::RegisterAllViewsForExport(); google::MetadataAgent server(config); google::InstanceUpdater instance_updater(config, server.mutable_store()); diff --git a/src/metrics.cc b/src/metrics.cc index 7cd74cf0..435da97c 100644 --- a/src/metrics.cc +++ b/src/metrics.cc @@ -22,65 +22,66 @@ namespace google { +const char Metrics::kGceApiRequestErrors[] = + "container.googleapis.com/internal/metadata_agent/gce_api_request_errors"; + namespace { constexpr char kCount[] = "1"; -} // namespace +::opencensus::stats::TagKey MethodTagKey() { + static const auto method_tag_key = + ::opencensus::stats::TagKey::Register("method"); + return method_tag_key; +} -constexpr char kGceApiRequestErrors[] = - "container.googleapis.com/internal/metadata_agent/gce_api_request_errors"; +} // namespace -void Metrics::RegisterAllViewsForExport() { - // Access metrics used by views to ensure metrics are initalized. - GceApiRequestErrors(); - - // Register all the views for export. - // - // To avoid view registration throwing error, when adding a new view, register - // measures used by this view in the section above. - GceApiRequestErrorsCumulative().RegisterForExport(); -} void Metrics::RecordGceApiRequestErrors(int64_t value, const std::string& method) { ::opencensus::stats::Record( {{GceApiRequestErrors(), value}}, {{MethodTagKey(), method}}); -}; +} -const ::opencensus::stats::ViewDescriptor& +const ::opencensus::stats::ViewDescriptor Metrics::GceApiRequestErrorsCumulative() { - const static ::opencensus::stats::ViewDescriptor descriptor = - ::opencensus::stats::ViewDescriptor() - .set_name("gce_api_request_errors") - .set_measure(kGceApiRequestErrors) - .set_aggregation(::opencensus::stats::Aggregation::Count()) - .add_column(MethodTagKey()); - return descriptor; + return ::opencensus::stats::ViewDescriptor() + .set_name(kGceApiRequestErrors) + .set_measure(kGceApiRequestErrors) + .set_aggregation(::opencensus::stats::Aggregation::Count()) + .add_column(MethodTagKey()); } -std::string Metrics::SerializeMetricsToPrometheusTextFormat() { - static const auto* const text_serializer = - new ::prometheus::TextSerializer(); - static auto* const exporter = - new ::opencensus::exporters::stats::PrometheusExporter(); - return text_serializer->Serialize(exporter->Collect()); +::opencensus::stats::MeasureInt64 Metrics::GceApiRequestErrors() { + static const auto measure = Metrics::GceApiRequestErrorsInitialize(); + return measure; } -::opencensus::stats::MeasureInt64 Metrics::GceApiRequestErrors() { - static const auto measure = +::opencensus::stats::MeasureInt64 Metrics::GceApiRequestErrorsInitialize() { + auto measure = ::opencensus::stats::MeasureInt64::Register( kGceApiRequestErrors, "Number of API request errors encountered.", kCount); + Metrics::GceApiRequestErrorsCumulative().RegisterForExport(); return measure; } -::opencensus::stats::TagKey Metrics::MethodTagKey() { - static const auto method_tag_key = - ::opencensus::stats::TagKey::Register("method"); - return method_tag_key; +::opencensus::stats::ViewData::DataMap + Metrics::GetGceApiRequestErrorsCumulativeViewIntData() { + static ::opencensus::stats::View errors_view( + GceApiRequestErrorsCumulative()); + return errors_view.GetData().int_data(); +} + +std::string Metrics::SerializeMetricsToPrometheusTextFormat() { + static const auto* const text_serializer = + new ::prometheus::TextSerializer(); + static auto* const exporter = + new ::opencensus::exporters::stats::PrometheusExporter(); + return text_serializer->Serialize(exporter->Collect()); } } // namespace google diff --git a/src/metrics.h b/src/metrics.h index f888879b..86a05ef8 100644 --- a/src/metrics.h +++ b/src/metrics.h @@ -24,29 +24,24 @@ namespace google { class Metrics { public: - // Register all the view descriptors declared above as view for export. - static void RegisterAllViewsForExport(); + static const char kGceApiRequestErrors[]; static void RecordGceApiRequestErrors(int64_t value, const std::string& method); // View Descriptor accessors. If the view descriptor variable is not // initialized, these methods will initialize the variable. - static const ::opencensus::stats::ViewDescriptor& GceApiRequestErrorsCumulative(); + static const ::opencensus::stats::ViewDescriptor GceApiRequestErrorsCumulative(); + + static ::opencensus::stats::ViewData::DataMap + GetGceApiRequestErrorsCumulativeViewIntData(); static std::string SerializeMetricsToPrometheusTextFormat(); private: - // Measure accessors. If the measure variable is not initialized, these methods - // will initialize the variable. - // - // Reference of measure: https://opencensus.io/stats/measure/ + static ::opencensus::stats::MeasureInt64 GceApiRequestErrorsInitialize(); static ::opencensus::stats::MeasureInt64 GceApiRequestErrors(); - - // Tag key accessors. If the tag key variable is not initialized, these methods - // will initialize the variable. - // - // Reference of measure: https://opencensus.io/tag/key/ - static ::opencensus::stats::TagKey MethodTagKey(); + static const ::opencensus::stats::ViewDescriptor GceApiRequestErrorsCumulative( + const std::string& name); }; } // namespace google diff --git a/test/oauth2_unittest.cc b/test/oauth2_unittest.cc index 77f987c5..e17f1ff7 100644 --- a/test/oauth2_unittest.cc +++ b/test/oauth2_unittest.cc @@ -123,9 +123,6 @@ TEST_F(OAuth2Test, GetAuthHeaderValueUsingTokenFromMetadataServerAsFallback) { } TEST_F(OAuth2Test, PropagateGceApiRequestErrorsCumulativeToView) { - // Flush to prevents other test contaminate the metrics. - ::opencensus::stats::testing::TestUtils::Flush(); - testing::FakeServer oauth_server; testing::TemporaryFile credentials_file( std::string(test_info_->name()) + "_creds.json", @@ -137,15 +134,18 @@ TEST_F(OAuth2Test, PropagateGceApiRequestErrorsCumulativeToView) { OAuth2 auth(environment); SetTokenEndpointForTest(&auth, oauth_server.GetUrl() + "/oauth2/v3/token"); - ::opencensus::stats::View errors_view( - ::google::Metrics::GceApiRequestErrorsCumulative()); - - // No record exists before internal function sent request to oauth_server. - EXPECT_THAT(errors_view.GetData().int_data(), ::testing::IsEmpty()); + // Remove existing view on kGceApiRequestErrors to avoid + // other tests affecting the result. + ::opencensus::stats::StatsExporter::RemoveView( + ::google::Metrics::kGceApiRequestErrors); + // Flush to propagate records to views, including records from other tests. + ::opencensus::stats::testing::TestUtils::Flush(); auth.GetAuthHeaderValue(); - // Flush to propagate recorded stats to views. + // Flush records to propogate to views. + ::opencensus::stats::View errors_view( + ::google::Metrics::GceApiRequestErrorsCumulative()); ::opencensus::stats::testing::TestUtils::Flush(); EXPECT_THAT(errors_view.GetData().int_data(), From 26877287a413466a5ade80dfb2dc013f0826b8ef Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Mon, 10 Dec 2018 09:25:08 +0000 Subject: [PATCH 28/36] initialize export related object every time to be safe - because we do not know they will match google style guide. --- src/metrics.cc | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/metrics.cc b/src/metrics.cc index 435da97c..75c7c47b 100644 --- a/src/metrics.cc +++ b/src/metrics.cc @@ -77,11 +77,8 @@ ::opencensus::stats::ViewData::DataMap } std::string Metrics::SerializeMetricsToPrometheusTextFormat() { - static const auto* const text_serializer = - new ::prometheus::TextSerializer(); - static auto* const exporter = - new ::opencensus::exporters::stats::PrometheusExporter(); - return text_serializer->Serialize(exporter->Collect()); + return ::prometheus::TextSerializer().Serialize( + ::opencensus::exporters::stats::PrometheusExporter().Collect()); } } // namespace google From 5c6526e209f02556b1cdb39a951647dbb6385530 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Mon, 10 Dec 2018 09:25:42 +0000 Subject: [PATCH 29/36] reorder variable definition. --- src/metrics.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/metrics.cc b/src/metrics.cc index 75c7c47b..7123ce99 100644 --- a/src/metrics.cc +++ b/src/metrics.cc @@ -22,9 +22,6 @@ namespace google { -const char Metrics::kGceApiRequestErrors[] = - "container.googleapis.com/internal/metadata_agent/gce_api_request_errors"; - namespace { constexpr char kCount[] = "1"; @@ -37,6 +34,8 @@ ::opencensus::stats::TagKey MethodTagKey() { } // namespace +const char Metrics::kGceApiRequestErrors[] = + "container.googleapis.com/internal/metadata_agent/gce_api_request_errors"; void Metrics::RecordGceApiRequestErrors(int64_t value, const std::string& method) { From 546958f5d841d4acbd144d3bcd54647633f92f8d Mon Sep 17 00:00:00 2001 From: StevenYCChou <3055688+StevenYCChou@users.noreply.github.com> Date: Mon, 10 Dec 2018 15:41:32 -0800 Subject: [PATCH 30/36] Use constexpr const. --- src/metrics.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/metrics.cc b/src/metrics.cc index 7123ce99..788524f7 100644 --- a/src/metrics.cc +++ b/src/metrics.cc @@ -24,7 +24,7 @@ namespace google { namespace { -constexpr char kCount[] = "1"; +constexpr const char kCount[] = "1"; ::opencensus::stats::TagKey MethodTagKey() { static const auto method_tag_key = From 775737c54ab3b257e58af373da5a7354e76802a3 Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Tue, 11 Dec 2018 08:20:18 +0000 Subject: [PATCH 31/36] Add metrics tests on GCE Api Request Errors. --- src/metrics.cc | 1 + test/metrics_unittest.cc | 55 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/metrics.cc b/src/metrics.cc index 788524f7..d7c9dae6 100644 --- a/src/metrics.cc +++ b/src/metrics.cc @@ -50,6 +50,7 @@ const ::opencensus::stats::ViewDescriptor .set_name(kGceApiRequestErrors) .set_measure(kGceApiRequestErrors) .set_aggregation(::opencensus::stats::Aggregation::Count()) + .set_description("The total number of HTTP request errors.") .add_column(MethodTagKey()); } diff --git a/test/metrics_unittest.cc b/test/metrics_unittest.cc index 7a8eb523..9922de41 100644 --- a/test/metrics_unittest.cc +++ b/test/metrics_unittest.cc @@ -15,13 +15,64 @@ **/ #include "../../src/metrics.h" + +#include +#include +#include "gmock/gmock.h" #include "gtest/gtest.h" namespace google { -TEST(SerializeToPrometheusTextTest, Initialization) { +TEST(SerializeToPrometheusTextTest, NoMetricExists) { EXPECT_EQ("", - ::google::Metrics::SerializeMetricsToPrometheusTextFormat()); + ::google::Metrics::SerializeMetricsToPrometheusTextFormat()); +} + +TEST(SerializeToPrometheusTextTest, SingleOpencensusView) { + const char measure_name[] = "test_measure"; + const char view_name[] = "test_view"; + const ::opencensus::stats::MeasureInt64 test_measure = + ::opencensus::stats::MeasureInt64::Register( + measure_name, "description on test view", "1"); + const ::opencensus::stats::ViewDescriptor test_view_descriptor = + ::opencensus::stats::ViewDescriptor() + .set_name(view_name) + .set_description("description on test view") + .set_measure(measure_name) + .set_aggregation(opencensus::stats::Aggregation::Count()); + // remove view and flush the result before the actual test. + ::opencensus::stats::StatsExporter::RemoveView(view_name); + ::opencensus::stats::testing::TestUtils::Flush(); + + test_view_descriptor.RegisterForExport(); + opencensus::stats::Record({{test_measure, 1}}); + ::opencensus::stats::testing::TestUtils::Flush(); + EXPECT_THAT(::google::Metrics::SerializeMetricsToPrometheusTextFormat(), + ::testing::MatchesRegex( + "# HELP test_view_1 description on test view\n" + "# TYPE test_view_1 counter\n" + "test_view_1 1.000000 [0-9]*\n")); + + // clean up the view which we registered for export. + ::opencensus::stats::StatsExporter::RemoveView(view_name); } + +TEST(SerializeToPrometheusTextTest, RecordGceApiRequestErrors) { + // remove view and flush the result before the actual test. + ::opencensus::stats::StatsExporter::RemoveView(::google::Metrics::kGceApiRequestErrors); + ::opencensus::stats::testing::TestUtils::Flush(); + + ::google::Metrics::RecordGceApiRequestErrors(1, "test_kind"); + ::opencensus::stats::testing::TestUtils::Flush(); + EXPECT_THAT(::google::Metrics::SerializeMetricsToPrometheusTextFormat(), + ::testing::MatchesRegex( + "# HELP container_googleapis_com_internal_metadata_agent_gce_api_request_errors_1 The total number of HTTP request errors.\n" + "# TYPE container_googleapis_com_internal_metadata_agent_gce_api_request_errors_1 counter\n" + "container_googleapis_com_internal_metadata_agent_gce_api_request_errors_1\\{method=\"test_kind\"\\} 1.000000 [0-9]*\n" + )); + + // clean up the view which we registered for export. + ::opencensus::stats::StatsExporter::RemoveView(::google::Metrics::kGceApiRequestErrors); +} } // namespace google From fc935e60f4e659bf79173f12c8dc1610badca9fb Mon Sep 17 00:00:00 2001 From: Yen-Cheng Chou Date: Tue, 11 Dec 2018 09:32:37 +0000 Subject: [PATCH 32/36] fix format. --- .gitmodules | 3 ++- src/metrics.cc | 25 +++++++++---------------- src/metrics.h | 14 ++++++-------- src/oauth2.h | 4 ++-- test/metrics_unittest.cc | 2 +- test/oauth2_unittest.cc | 5 +++-- 6 files changed, 23 insertions(+), 30 deletions(-) diff --git a/.gitmodules b/.gitmodules index 7f232799..fca60520 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,4 +13,5 @@ [submodule "lib/opencensus-cpp"] path = lib/opencensus-cpp url = https://github.com/census-instrumentation/opencensus-cpp - ignore = dirty \ No newline at end of file + ignore = dirty + diff --git a/src/metrics.cc b/src/metrics.cc index d7c9dae6..6f185ffd 100644 --- a/src/metrics.cc +++ b/src/metrics.cc @@ -44,16 +44,6 @@ void Metrics::RecordGceApiRequestErrors(int64_t value, {{MethodTagKey(), method}}); } -const ::opencensus::stats::ViewDescriptor - Metrics::GceApiRequestErrorsCumulative() { - return ::opencensus::stats::ViewDescriptor() - .set_name(kGceApiRequestErrors) - .set_measure(kGceApiRequestErrors) - .set_aggregation(::opencensus::stats::Aggregation::Count()) - .set_description("The total number of HTTP request errors.") - .add_column(MethodTagKey()); -} - ::opencensus::stats::MeasureInt64 Metrics::GceApiRequestErrors() { static const auto measure = Metrics::GceApiRequestErrorsInitialize(); return measure; @@ -65,15 +55,18 @@ ::opencensus::stats::MeasureInt64 Metrics::GceApiRequestErrorsInitialize() { kGceApiRequestErrors, "Number of API request errors encountered.", kCount); - Metrics::GceApiRequestErrorsCumulative().RegisterForExport(); + Metrics::GceApiRequestErrorsCumulativeViewDescriptor().RegisterForExport(); return measure; } -::opencensus::stats::ViewData::DataMap - Metrics::GetGceApiRequestErrorsCumulativeViewIntData() { - static ::opencensus::stats::View errors_view( - GceApiRequestErrorsCumulative()); - return errors_view.GetData().int_data(); +const ::opencensus::stats::ViewDescriptor + Metrics::GceApiRequestErrorsCumulativeViewDescriptor() { + return ::opencensus::stats::ViewDescriptor() + .set_name(kGceApiRequestErrors) + .set_measure(kGceApiRequestErrors) + .set_aggregation(::opencensus::stats::Aggregation::Count()) + .set_description("The total number of HTTP request errors.") + .add_column(MethodTagKey()); } std::string Metrics::SerializeMetricsToPrometheusTextFormat() { diff --git a/src/metrics.h b/src/metrics.h index 86a05ef8..84a595e0 100644 --- a/src/metrics.h +++ b/src/metrics.h @@ -26,22 +26,20 @@ class Metrics { public: static const char kGceApiRequestErrors[]; + // Record an API request error on a method, e.g. oauth2 is one of the methods. static void RecordGceApiRequestErrors(int64_t value, const std::string& method); + // Serialize all the available metrics as prometheus text format. + static std::string SerializeMetricsToPrometheusTextFormat(); + // View Descriptor accessors. If the view descriptor variable is not // initialized, these methods will initialize the variable. - static const ::opencensus::stats::ViewDescriptor GceApiRequestErrorsCumulative(); - - static ::opencensus::stats::ViewData::DataMap - GetGceApiRequestErrorsCumulativeViewIntData(); - - static std::string SerializeMetricsToPrometheusTextFormat(); + static const ::opencensus::stats::ViewDescriptor + GceApiRequestErrorsCumulativeViewDescriptor(); private: static ::opencensus::stats::MeasureInt64 GceApiRequestErrorsInitialize(); static ::opencensus::stats::MeasureInt64 GceApiRequestErrors(); - static const ::opencensus::stats::ViewDescriptor GceApiRequestErrorsCumulative( - const std::string& name); }; } // namespace google diff --git a/src/oauth2.h b/src/oauth2.h index 4d48c4b5..93b4f1e0 100644 --- a/src/oauth2.h +++ b/src/oauth2.h @@ -41,8 +41,8 @@ class OAuth2 { protected: OAuth2(const Environment& environment, std::unique_ptr expiration) : environment_(environment), - token_expiration_(std::move(expiration)), - token_endpoint_(kDefaultTokenEndpoint) {} + token_expiration_(std::move(expiration)), + token_endpoint_(kDefaultTokenEndpoint) {} private: friend class OAuth2Test; diff --git a/test/metrics_unittest.cc b/test/metrics_unittest.cc index 9922de41..7f89edc4 100644 --- a/test/metrics_unittest.cc +++ b/test/metrics_unittest.cc @@ -57,7 +57,6 @@ TEST(SerializeToPrometheusTextTest, SingleOpencensusView) { ::opencensus::stats::StatsExporter::RemoveView(view_name); } - TEST(SerializeToPrometheusTextTest, RecordGceApiRequestErrors) { // remove view and flush the result before the actual test. ::opencensus::stats::StatsExporter::RemoveView(::google::Metrics::kGceApiRequestErrors); @@ -75,4 +74,5 @@ TEST(SerializeToPrometheusTextTest, RecordGceApiRequestErrors) { // clean up the view which we registered for export. ::opencensus::stats::StatsExporter::RemoveView(::google::Metrics::kGceApiRequestErrors); } + } // namespace google diff --git a/test/oauth2_unittest.cc b/test/oauth2_unittest.cc index e17f1ff7..50da116b 100644 --- a/test/oauth2_unittest.cc +++ b/test/oauth2_unittest.cc @@ -136,16 +136,17 @@ TEST_F(OAuth2Test, PropagateGceApiRequestErrorsCumulativeToView) { // Remove existing view on kGceApiRequestErrors to avoid // other tests affecting the result. + // Flush to propagate existing records to views, including records from other + // tests. ::opencensus::stats::StatsExporter::RemoveView( ::google::Metrics::kGceApiRequestErrors); - // Flush to propagate records to views, including records from other tests. ::opencensus::stats::testing::TestUtils::Flush(); auth.GetAuthHeaderValue(); // Flush records to propogate to views. ::opencensus::stats::View errors_view( - ::google::Metrics::GceApiRequestErrorsCumulative()); + ::google::Metrics::GceApiRequestErrorsCumulativeViewDescriptor()); ::opencensus::stats::testing::TestUtils::Flush(); EXPECT_THAT(errors_view.GetData().int_data(), From 1fe4649d9c8565ca40877324acf1f5858371937a Mon Sep 17 00:00:00 2001 From: StevenYCChou <3055688+StevenYCChou@users.noreply.github.com> Date: Tue, 11 Dec 2018 20:47:07 -0800 Subject: [PATCH 33/36] Fix format on namespace. --- src/api_server.cc | 2 +- src/metrics.cc | 4 ++-- src/metrics.h | 2 +- src/oauth2.cc | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/api_server.cc b/src/api_server.cc index 4f196d1d..b31dece2 100644 --- a/src/api_server.cc +++ b/src/api_server.cc @@ -220,4 +220,4 @@ void MetadataApiServer::HandleMetrics( conn->write(response); } -} // namespace google +} // namespace google diff --git a/src/metrics.cc b/src/metrics.cc index 6f185ffd..9db5cbc3 100644 --- a/src/metrics.cc +++ b/src/metrics.cc @@ -32,7 +32,7 @@ ::opencensus::stats::TagKey MethodTagKey() { return method_tag_key; } -} // namespace +} // namespace const char Metrics::kGceApiRequestErrors[] = "container.googleapis.com/internal/metadata_agent/gce_api_request_errors"; @@ -74,4 +74,4 @@ std::string Metrics::SerializeMetricsToPrometheusTextFormat() { ::opencensus::exporters::stats::PrometheusExporter().Collect()); } -} // namespace google +} // namespace google diff --git a/src/metrics.h b/src/metrics.h index 84a595e0..05517116 100644 --- a/src/metrics.h +++ b/src/metrics.h @@ -42,6 +42,6 @@ class Metrics { static ::opencensus::stats::MeasureInt64 GceApiRequestErrors(); }; -} // namespace google +} // namespace google #endif /* METADATA_AGENT_METRICS_H_ */ diff --git a/src/oauth2.cc b/src/oauth2.cc index 56b6fde4..87ba3afd 100644 --- a/src/oauth2.cc +++ b/src/oauth2.cc @@ -140,7 +140,7 @@ std::string Sign(const std::string& data, const PKey& pkey) { return std::string(reinterpret_cast(result.get()), actual_result_size); } -} // namespace +} // namespace json::value OAuth2::ComputeTokenFromCredentials() const { const std::string service_account_email = From 1099767f6d39845d943ed5c8c1a479b9b8b38c08 Mon Sep 17 00:00:00 2001 From: StevenYCChou <3055688+StevenYCChou@users.noreply.github.com> Date: Tue, 11 Dec 2018 20:47:23 -0800 Subject: [PATCH 34/36] Fix typo. --- test/oauth2_unittest.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/oauth2_unittest.cc b/test/oauth2_unittest.cc index 50da116b..35a2ca67 100644 --- a/test/oauth2_unittest.cc +++ b/test/oauth2_unittest.cc @@ -144,7 +144,7 @@ TEST_F(OAuth2Test, PropagateGceApiRequestErrorsCumulativeToView) { auth.GetAuthHeaderValue(); - // Flush records to propogate to views. + // Flush records to propagate to views. ::opencensus::stats::View errors_view( ::google::Metrics::GceApiRequestErrorsCumulativeViewDescriptor()); ::opencensus::stats::testing::TestUtils::Flush(); From 1e56d36faa3b6fa3fed3b1477c25351b0ec4ad7f Mon Sep 17 00:00:00 2001 From: StevenYCChou <3055688+StevenYCChou@users.noreply.github.com> Date: Fri, 14 Dec 2018 03:44:22 -0800 Subject: [PATCH 35/36] Address feedbacks. --- test/metrics_unittest.cc | 21 ++++++++++++--------- test/oauth2_unittest.cc | 38 +++++++++++++++++++++++++++----------- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/test/metrics_unittest.cc b/test/metrics_unittest.cc index 7f89edc4..8742f9d8 100644 --- a/test/metrics_unittest.cc +++ b/test/metrics_unittest.cc @@ -28,9 +28,9 @@ TEST(SerializeToPrometheusTextTest, NoMetricExists) { ::google::Metrics::SerializeMetricsToPrometheusTextFormat()); } -TEST(SerializeToPrometheusTextTest, SingleOpencensusView) { - const char measure_name[] = "test_measure"; - const char view_name[] = "test_view"; +TEST(SerializeToPrometheusTextTest, SingleMetricAndViewRegisteredForExport) { + const char* measure_name = "test_measure"; + const char* view_name = "test_view"; const ::opencensus::stats::MeasureInt64 test_measure = ::opencensus::stats::MeasureInt64::Register( measure_name, "description on test view", "1"); @@ -40,12 +40,13 @@ TEST(SerializeToPrometheusTextTest, SingleOpencensusView) { .set_description("description on test view") .set_measure(measure_name) .set_aggregation(opencensus::stats::Aggregation::Count()); - // remove view and flush the result before the actual test. + // Remove view and flush the result before the actual test. ::opencensus::stats::StatsExporter::RemoveView(view_name); ::opencensus::stats::testing::TestUtils::Flush(); test_view_descriptor.RegisterForExport(); - opencensus::stats::Record({{test_measure, 1}}); + ::opencensus::stats::Record({{test_measure, 1}}); + // Flush to propagate existing records to views. ::opencensus::stats::testing::TestUtils::Flush(); EXPECT_THAT(::google::Metrics::SerializeMetricsToPrometheusTextFormat(), ::testing::MatchesRegex( @@ -53,17 +54,19 @@ TEST(SerializeToPrometheusTextTest, SingleOpencensusView) { "# TYPE test_view_1 counter\n" "test_view_1 1.000000 [0-9]*\n")); - // clean up the view which we registered for export. + // Clean up the view which we registered for export. ::opencensus::stats::StatsExporter::RemoveView(view_name); } TEST(SerializeToPrometheusTextTest, RecordGceApiRequestErrors) { - // remove view and flush the result before the actual test. + // Remove view and flush the result before the actual test. ::opencensus::stats::StatsExporter::RemoveView(::google::Metrics::kGceApiRequestErrors); ::opencensus::stats::testing::TestUtils::Flush(); ::google::Metrics::RecordGceApiRequestErrors(1, "test_kind"); + // Flush to propagate existing records to views. ::opencensus::stats::testing::TestUtils::Flush(); + EXPECT_THAT(::google::Metrics::SerializeMetricsToPrometheusTextFormat(), ::testing::MatchesRegex( "# HELP container_googleapis_com_internal_metadata_agent_gce_api_request_errors_1 The total number of HTTP request errors.\n" @@ -71,8 +74,8 @@ TEST(SerializeToPrometheusTextTest, RecordGceApiRequestErrors) { "container_googleapis_com_internal_metadata_agent_gce_api_request_errors_1\\{method=\"test_kind\"\\} 1.000000 [0-9]*\n" )); - // clean up the view which we registered for export. + // Clean up the view which we registered for export. ::opencensus::stats::StatsExporter::RemoveView(::google::Metrics::kGceApiRequestErrors); } -} // namespace google +} // namespace google diff --git a/test/oauth2_unittest.cc b/test/oauth2_unittest.cc index 35a2ca67..e94aa9e0 100644 --- a/test/oauth2_unittest.cc +++ b/test/oauth2_unittest.cc @@ -134,24 +134,40 @@ TEST_F(OAuth2Test, PropagateGceApiRequestErrorsCumulativeToView) { OAuth2 auth(environment); SetTokenEndpointForTest(&auth, oauth_server.GetUrl() + "/oauth2/v3/token"); - // Remove existing view on kGceApiRequestErrors to avoid - // other tests affecting the result. - // Flush to propagate existing records to views, including records from other - // tests. + // Remove existing view on kGceApiRequestErrors to avoid other tests + // affecting the result, then flush to propagate existing records + // to views, including records from other tests. ::opencensus::stats::StatsExporter::RemoveView( ::google::Metrics::kGceApiRequestErrors); ::opencensus::stats::testing::TestUtils::Flush(); + // We want to test this auth.GetAuthHeaderValue() that it records and + // register the view, but as inside the auth.GetAuthHeaderValue() we + // use singleton pattern, once we remove the view in previous section, it is + // unable to add the view back within auth.GetAuthHeaderValue(). Add a view + // to export here helps us to test the data inside the view, it also makes + // the test fragile if auth.GetAuthHeaderValue() does not register view + // correctly. + // TODO: Fix this hack if we can contribute to opencensus that when we add + // a view, we only add view if a view name is not existed. Current + // StatsExporter::AddView always add a new view and destroy the old one, + // which is not suitable for our + // Metrics::GceApiRequestErrorsCumulativeViewDescriptor(). + ::google::Metrics::GceApiRequestErrorsCumulativeViewDescriptor(). + RegisterForExport(); auth.GetAuthHeaderValue(); - - // Flush records to propagate to views. - ::opencensus::stats::View errors_view( - ::google::Metrics::GceApiRequestErrorsCumulativeViewDescriptor()); + // Flush to propagate existing records to views. ::opencensus::stats::testing::TestUtils::Flush(); - EXPECT_THAT(errors_view.GetData().int_data(), - ::testing::UnorderedElementsAre( - ::testing::Pair(::testing::ElementsAre("oauth2"), 1))); + EXPECT_THAT(::opencensus::stats::StatsExporter::GetViewData(), + ::testing::Contains(::testing::Pair( + Metrics::GceApiRequestErrorsCumulativeViewDescriptor(), + ::testing::Property( + &::opencensus::stats::ViewData::int_data, + ::testing::UnorderedElementsAre( + ::testing::Pair( + ::testing::ElementsAre("oauth2"), + 1)))))); } TEST_F(OAuth2Test, GetAuthHeaderValueTokenJsonMissingField) { From d6c6ac3f0e0a1e126199a72ee903d4f015f318e9 Mon Sep 17 00:00:00 2001 From: StevenYCChou <3055688+StevenYCChou@users.noreply.github.com> Date: Fri, 14 Dec 2018 03:49:34 -0800 Subject: [PATCH 36/36] Add const. --- src/metrics.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/metrics.cc b/src/metrics.cc index 9db5cbc3..acc2e809 100644 --- a/src/metrics.cc +++ b/src/metrics.cc @@ -50,7 +50,7 @@ ::opencensus::stats::MeasureInt64 Metrics::GceApiRequestErrors() { } ::opencensus::stats::MeasureInt64 Metrics::GceApiRequestErrorsInitialize() { - auto measure = + const auto measure = ::opencensus::stats::MeasureInt64::Register( kGceApiRequestErrors, "Number of API request errors encountered.",