├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── Readme.md ├── installDependencies.sh ├── src └── cppmetrics │ ├── concurrent │ ├── simple_scheduled_thread_pool_executor.cpp │ ├── simple_scheduled_thread_pool_executor.h │ ├── simple_thread_pool_executor.cpp │ └── simple_thread_pool_executor.h │ ├── core │ ├── console_reporter.cpp │ ├── console_reporter.h │ ├── counter.h │ ├── ewma.cpp │ ├── ewma.h │ ├── exp_decay_sample.cpp │ ├── exp_decay_sample.h │ ├── gauge.h │ ├── histogram.cpp │ ├── histogram.h │ ├── meter.cpp │ ├── meter.h │ ├── metered.h │ ├── metric.h │ ├── metric_registry.cpp │ ├── metric_registry.h │ ├── reporter.h │ ├── sample.h │ ├── sampling.h │ ├── scheduled_reporter.cpp │ ├── scheduled_reporter.h │ ├── snapshot.cpp │ ├── snapshot.h │ ├── timer.cpp │ ├── timer.h │ ├── timer_context.cpp │ ├── timer_context.h │ ├── types.h │ ├── uniform_sample.cpp │ ├── uniform_sample.h │ └── utils.h │ ├── cppmetrics.h │ └── graphite │ ├── graphite_reporter.cpp │ ├── graphite_reporter.h │ ├── graphite_sender.h │ ├── graphite_sender_tcp.cpp │ └── graphite_sender_tcp.h └── test └── cppmetrics ├── concurrent ├── test_simple_scheduled_thread_pool_executor.cpp └── test_simple_thread_pool_executor.cpp ├── core ├── test_console_reporter.cpp ├── test_counter.cpp ├── test_ewma.cpp ├── test_exp_decay_sample.cpp ├── test_histogram.cpp ├── test_meter.cpp ├── test_metric_registry.cpp ├── test_scheduled_reporter.cpp ├── test_snapshot.cpp ├── test_timer.cpp └── test_uniform_sample.cpp └── graphite ├── test_graphite_reporter.cpp └── test_graphite_sender_tcp.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .project 3 | .cproject 4 | .settings 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | env: 4 | - DEPENDENCIES_ROOT=`pwd`/dependencies 5 | 6 | compiler: 7 | - gcc 8 | 9 | before_install: 10 | - if [ $TRAVIS_OS_NAME == linux ]; then sudo apt-add-repository -y ppa:boost-latest/ppa && sudo apt-get update && sudo apt-get install -y libboost1.54-all-dev; fi 11 | 12 | install: 13 | - echo "Dependencies root $DEPENDENCIES_ROOT" 14 | - mkdir -p $DEPENDENCIES_ROOT 15 | - echo `pwd` 16 | - ./installDependencies.sh $DEPENDENCIES_ROOT 17 | 18 | before_script: 19 | - rm -rf build 20 | - mkdir build 21 | - cd build 22 | - DEPENDENCIES_LOCATION=$DEPENDENCIES_ROOT/install 23 | - cmake -DCMAKE_CXX_COMPILER=g++ -DCMAKE_INSTALL_PREFIX=dist -DINCLUDE_SYSTEM_DIRS=1 -DGLOG_DIR=$DEPENDENCIES_LOCATION ../ 24 | 25 | script: make gtest VERBOSE=ON 26 | 27 | branches: 28 | only: 29 | - master 30 | 31 | os: 32 | - linux 33 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.5.7) 2 | 3 | project (cppmetrics) 4 | 5 | set (CPACK_GENERATOR TGZ) 6 | set (CPACK_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) 7 | 8 | set (cppmetrics_VERSION_MAJOR 0) 9 | set (cppmetrics_VERSION_MINOR 1) 10 | set (cppmetrics_VERSION_PATCH 1) 11 | set (cppmetrics_VERSION_TAG "") 12 | set (cppmetrics_VERSION "${cppmetrics_VERSION_MAJOR}.${cppmetrics_VERSION_MINOR}.${cppmetrics_VERSION_PATCH}${cppmetrics_VERSION_TAG}") 13 | set(CPACK_PACKAGE_VERSION ${cppmetrics_VERSION}) 14 | INCLUDE(CPack) 15 | 16 | set (cppmetrics_PREPROC_FLAGS -DBOOST_NO_CXX11_SMART_PTR) 17 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O2 -Werror -Wall -Winit-self -m64 -pipe") 18 | 19 | # Last ditch effort : look for boost in /usr/local and /usr/lib 20 | IF (DEFINED INCLUDE_SYSTEM_DIRS) 21 | SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/usr/include") 22 | SET (EXTRA_LD_FLAGS "-L/usr/lib") 23 | ENDIF() 24 | 25 | set (BOOST_LD_FLAGS "-lboost_timer -lboost_chrono -lboost_system -lboost_filesystem -lboost_thread -lboost_date_time -lpthread -lrt") 26 | set (GLOG_LD_FLAGS "-lglog") 27 | 28 | set (cppmetrics_global_EXTERNAL_HEADERS 29 | src/cppmetrics/cppmetrics.h 30 | ) 31 | 32 | set (cppmetrics_SOURCES 33 | src/cppmetrics/core/histogram.cpp 34 | src/cppmetrics/core/meter.cpp 35 | src/cppmetrics/core/metric_registry.cpp 36 | src/cppmetrics/core/scheduled_reporter.cpp 37 | src/cppmetrics/core/timer_context.cpp 38 | src/cppmetrics/core/timer.cpp 39 | src/cppmetrics/concurrent/simple_thread_pool_executor.cpp 40 | src/cppmetrics/concurrent/simple_scheduled_thread_pool_executor.cpp 41 | src/cppmetrics/core/ewma.cpp 42 | src/cppmetrics/core/exp_decay_sample.cpp 43 | src/cppmetrics/core/snapshot.cpp 44 | src/cppmetrics/core/uniform_sample.cpp 45 | src/cppmetrics/graphite/graphite_sender_tcp.cpp 46 | src/cppmetrics/graphite/graphite_reporter.cpp 47 | src/cppmetrics/core/console_reporter.cpp 48 | ) 49 | 50 | set (cppmetrics_core_EXTERNAL_HEADERS 51 | src/cppmetrics/core/counter.h 52 | src/cppmetrics/core/histogram.h 53 | src/cppmetrics/core/gauge.h 54 | src/cppmetrics/core/meter.h 55 | src/cppmetrics/core/metered.h 56 | src/cppmetrics/core/metric.h 57 | src/cppmetrics/core/metric_registry.h 58 | src/cppmetrics/core/reporter.h 59 | src/cppmetrics/core/scheduled_reporter.h 60 | src/cppmetrics/core/timer.h 61 | src/cppmetrics/core/timer_context.h 62 | src/cppmetrics/core/exp_decay_sample.h 63 | src/cppmetrics/core/sample.h 64 | src/cppmetrics/core/snapshot.h 65 | src/cppmetrics/core/uniform_sample.h 66 | src/cppmetrics/core/sampling.h 67 | src/cppmetrics/core/types.h 68 | src/cppmetrics/core/console_reporter.h 69 | ) 70 | 71 | set (cppmetrics_graphite_EXTERNAL_HEADERS 72 | src/cppmetrics/graphite/graphite_sender.h 73 | src/cppmetrics/graphite/graphite_sender_tcp.h 74 | src/cppmetrics/graphite/graphite_reporter.h 75 | ) 76 | 77 | set (cppmetrics_concurrent_EXTERNAL_HEADERS 78 | src/cppmetrics/concurrent/simple_thread_pool_executor.h 79 | src/cppmetrics/concurrent/simple_scheduled_thread_pool_executor.h 80 | ) 81 | 82 | set (cppmetrics_HEADERS 83 | src/cppmetrics/core/ewma.h 84 | ${cppmetrics_core_EXTERNAL_HEADERS} 85 | ${cppmetrics_concurrent_EXTERNAL_HEADERS} 86 | ${cppmetrics_graphite_EXTERNAL_HEADERS} 87 | ) 88 | 89 | set (cppmetrics_core_TEST_SOURCES 90 | test/cppmetrics/core/test_counter.cpp 91 | test/cppmetrics/core/test_ewma.cpp 92 | test/cppmetrics/core/test_exp_decay_sample.cpp 93 | test/cppmetrics/core/test_histogram.cpp 94 | test/cppmetrics/core/test_meter.cpp 95 | test/cppmetrics/core/test_metric_registry.cpp 96 | test/cppmetrics/core/test_scheduled_reporter.cpp 97 | test/cppmetrics/core/test_snapshot.cpp 98 | test/cppmetrics/core/test_timer.cpp 99 | test/cppmetrics/core/test_uniform_sample.cpp 100 | test/cppmetrics/core/test_console_reporter.cpp 101 | ) 102 | 103 | set (cppmetrics_graphite_TEST_SOURCES 104 | test/cppmetrics/graphite/test_graphite_sender_tcp.cpp 105 | test/cppmetrics/graphite/test_graphite_reporter.cpp 106 | ) 107 | 108 | set (cppmetrics_concurrent_TEST_SOURCES 109 | test/cppmetrics/concurrent/test_simple_thread_pool_executor.cpp 110 | test/cppmetrics/concurrent/test_simple_scheduled_thread_pool_executor.cpp 111 | ) 112 | 113 | set (cppmetrics_TEST_SOURCES 114 | ${cppmetrics_core_TEST_SOURCES} 115 | ${cppmetrics_concurrent_TEST_SOURCES} 116 | ${cppmetrics_graphite_TEST_SOURCES} 117 | ) 118 | 119 | set (GTEST_LD_FLAGS "${EXTRA_LD_FLAGS} ${BOOST_LD_FLAGS} ${GLOG_LD_FLAGS} -lgtest_main -lgtest") 120 | set (DIST_INCLUDE_DIR include/cppmetrics) 121 | 122 | IF (NOT DEFINED BOOST_DIR) 123 | find_package(Boost 1.53.0) 124 | if(Boost_FOUND) 125 | set (BOOST_INC_DIR ${Boost_INCLUDE_DIRS}) 126 | set (BOOST_LIB_DIR ${Boost_LIBRARY_DIRS}) 127 | else () 128 | MESSAGE(STATUS "BOOST distro not found") 129 | endif() 130 | ELSE () 131 | set (BOOST_INC_DIR ${BOOST_DIR}/include) 132 | set (BOOST_LIB_DIR ${BOOST_DIR}/lib) 133 | ENDIF () 134 | 135 | 136 | IF (DEFINED GLOG_DIR) 137 | set (GLOG_INCLUDE_DIR ${GLOG_DIR}/include) 138 | set (GLOG_LIB_DIR ${GLOG_DIR}/lib) 139 | ENDIF () 140 | 141 | IF (DEFINED GTEST_DIR) 142 | set (GTEST_INCLUDE_DIR ${GTEST_DIR}/include) 143 | set (GTEST_LIB_DIR ${GTEST_DIR}/lib) 144 | ENDIF () 145 | 146 | include_directories (src ${BOOST_INC_DIR} ${GLOG_INCLUDE_DIR} ${GTEST_DIR}) 147 | link_directories (${BOOST_LIB_DIR} ${GLOG_LIB_DIR} ${GTEST_DIR}) 148 | install (FILES ${cppmetrics_global_EXTERNAL_HEADERS} DESTINATION ${DIST_INCLUDE_DIR}) 149 | install (FILES ${cppmetrics_core_EXTERNAL_HEADERS} DESTINATION ${DIST_INCLUDE_DIR}/core) 150 | install (FILES ${cppmetrics_concurrent_EXTERNAL_HEADERS} DESTINATION ${DIST_INCLUDE_DIR}/concurrent) 151 | install (FILES ${cppmetrics_graphite_EXTERNAL_HEADERS} DESTINATION ${DIST_INCLUDE_DIR}/graphite) 152 | 153 | add_library (cppmetrics STATIC ${cppmetrics_HEADERS} ${cppmetrics_SOURCES}) 154 | install (TARGETS cppmetrics DESTINATION lib) 155 | 156 | # Re-enable them when the boost is built with shared library option too. 157 | # add_library (cppmetricsshared SHARED ${cppmetrics_HEADERS} ${cppmetrics_SOURCES}) 158 | # target_link_libraries (cppmetricsshared ${BOOST_LD_FLAGS}) 159 | # install (TARGETS cppmetricsshared DESTINATION lib) 160 | 161 | add_executable(gtest_cppmetrics EXCLUDE_FROM_ALL ${cppmetrics_TEST_SOURCES}) 162 | target_link_libraries (gtest_cppmetrics cppmetrics ${GTEST_LD_FLAGS}) 163 | add_custom_target(gtest gtest_cppmetrics --gtest_output=xml DEPENDS gtest_cppmetrics) 164 | 165 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2014 NeuStar, Inc. All rights reserved. 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | ##Background 2 | 3 | cppmetrics is a C++ port of the [DropWizard metrics!](https://dropwizard.github.io/metrics/3.1.0/). 4 | The library implements the standard metrics primitives like Gauge, Counter, Histogram, Meter and Timer and the provides the reporter 5 | implementations like the ConsoleReporter, GraphiteRepoter out of the box. 6 | Its written in C++98 to make the integration into existing pre-C++11 codebases easier and should be portable across different 7 | platforms but being used only in linux environment. 8 | 9 | [![Build Status](https://travis-ci.org/ultradns/cppmetrics.png)](https://travis-ci.org/ultradns/cppmetrics) 10 | 11 | ## Build dependencies 12 | - cmake (>= 2.6.5) 13 | - boost libraries (>= 1.53.0) 14 | - google logging framework (>= 0.3.1) 15 | - gtest (>= 1.6.0, dependency for the unit tests only.) 16 | 17 | ## How to build 18 | 19 | ``` 20 | # It is recommended to create the build directory in the parent directory of cppmetrics source as opposed to creating in the cppmetrics directory. 21 | mkdir build 22 | cd build 23 | cmake -DCMAKE_CXX_COMPILER=g++ -DCMAKE_INSTALL_PREFIX=dist -DBOOST_DIR= -DGLOG_DIR= -DGTEST_DIR= ../cppmetrics/ 24 | make gtest 25 | make package 26 | ``` 27 | 28 | The above process produces a tar file of include files and a static library and should be used to statically link in your existing application. The shared library option is 29 | not turned off by default but can be turned on easily if required. 30 | 31 | ##Sample code snippet 32 | 33 | ####Using a Histogram or a timer or a meter.. 34 | ``` cpp 35 | #include 36 | ... 37 | 38 | bool QueryHandler::doProcess(const Query& query) { 39 | cppmetrics::core::MetricRegistryPtr registry( 40 | cppmetrics::core::MetricRegistry::DEFAULT_REGISTRY()); 41 | 42 | // More initialization. 43 | 44 | cppmetrics::core::CounterPtr query_counter(registry->counter("get_requests")); 45 | query_counter->increment(); 46 | // More processing 47 | { 48 | cppmetrics::core::TimerContextPtr timer( 49 | metrics->timer("query_process")->timerContextPtr()); 50 | // Do some computation or IO. 51 | // timer stats will be updated in the registry at the end of the scope. 52 | } 53 | } 54 | ``` 55 | 56 | ####Creating the default metrics registry and a graphite reporter that pushes the data to graphite server. 57 | 58 | ```cpp 59 | #include 60 | #include 61 | #include 62 | 63 | namespace sample { 64 | 65 | class GraphiteReporterOptions { 66 | public: 67 | std::string host_; ///< The graphite server. 68 | boost::uint32_t port_; ///< The graphite port. 69 | std::string prefix_; ///< The prefix to the graphite. 70 | boost::uint32_t interval_in_secs_; ///< The reporting period in secs. 71 | }; 72 | 73 | /* 74 | * Helper class that sets up the default registry and the graphite reporter. 75 | */ 76 | class Controller : boost::noncopyable 77 | { 78 | public: 79 | cppmetrics::core::MetricRegistryPtr getRegistry() { 80 | return core::MetricRegistry::DEFAULT_REGISTRY(); 81 | } 82 | 83 | void configureAndStartGraphiteReporter(const GraphiteReporterOptions& graphite_options) { 84 | if (!graphite_reporter_) { 85 | const std::string& graphite_host(graphite_options.host_); 86 | 87 | boost::uint32_t graphite_port(graphite_options.port_); 88 | graphite::GraphiteSenderPtr graphite_sender( 89 | new graphite::GraphiteSenderTCP(graphite_host, graphite_port)); 90 | 91 | graphite_reporter_.reset( 92 | new graphite::GraphiteReporter(getRegistry(), graphite_sender, 93 | graphite_options.prefix_)); 94 | graphite_reporter_->start(boost::chrono::seconds(graphite_options.interval_in_secs_)); 95 | } else { 96 | LOG(ERROR) << "Graphite reporter already configured."; 97 | } 98 | } 99 | private: 100 | boost::scoped_ptr graphite_reporter_; 101 | }; 102 | 103 | } 104 | ``` 105 | 106 | ###TODO 107 | - Currently the Timer and Meter resolutions are in millis and per-minute respectively, make this configurable. 108 | - Provide more reporters out of the box. 109 | 110 | 111 | -------------------------------------------------------------------------------- /installDependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | GLOG_TARGET=glog-0.3.3 4 | GLOG_TARGET_PACKAGE=${GLOG_TARGET}.tar.gz 5 | GTEST_TARGET=gtest-1.7.0 6 | GTEST_TARGET_PACKAGE=${GTEST_TARGET}.zip 7 | 8 | make_glog() { 9 | INSTALL_DIR=$1 10 | echo "Fetching glog package." 11 | curl https://google-glog.googlecode.com/files/${GLOG_TARGET_PACKAGE} -o ${GLOG_TARGET_PACKAGE} 12 | echo "Unzipping ${GLOG_TARGET_PACKAGE} package." 13 | tar -zxvf ${GLOG_TARGET_PACKAGE} 14 | cd ${GLOG_TARGET} && ./configure --prefix=${INSTALL_DIR} --enable-shared=false 15 | make install 16 | } 17 | 18 | 19 | make_gtest() { 20 | INSTALL_DIR=$1 21 | curl -v https://googletest.googlecode.com/files/${GTEST_TARGET_PACKAGE} -o ${GTEST_TARGET_PACKAGE} 22 | unzip ${GTEST_TARGET_PACKAGE} 23 | cd ${GTEST_TARGET} && ./configure --prefix=${INSTALL_DIR} --enable-shared=false 24 | make 25 | echo "Installing from ${PWD} into ${INSTALL_DIR}" 26 | test -z "${INSTALL_DIR}/lib" || /bin/mkdir -p "${INSTALL_DIR}/lib" 27 | # since libtool doesnt have same params in all versions.. 28 | /usr/bin/install -c ./lib/.libs/libgtest.lai ${INSTALL_DIR}/lib/libgtest.la 29 | /usr/bin/install -c ./lib/.libs/libgtest.a ${INSTALL_DIR}/lib/libgtest.a 30 | /usr/bin/install -c ./lib/.libs/libgtest_main.lai ${INSTALL_DIR}/lib/libgtest_main.la 31 | /usr/bin/install -c ./lib/.libs/libgtest_main.a ${INSTALL_DIR}/lib/libgtest_main.a 32 | chmod 644 ${INSTALL_DIR}/lib/libgtest*.a 33 | ranlib ${INSTALL_DIR}/lib/libgtest*.a 34 | test -z "${INSTALL_DIR}/include/gtest" || /bin/mkdir -p "${INSTALL_DIR}/include/gtest" 35 | test -z "${INSTALL_DIR}/include/gtest/internal" || /bin/mkdir -p "${INSTALL_DIR}/include/gtest/internal" 36 | find include -name "*.h" -exec /usr/bin/install -c -m 644 '{}' "${INSTALL_DIR}/{}" \; 37 | } 38 | 39 | # A platform independent way to find the absolute path 40 | fullpath() { 41 | pushd . >/dev/null 42 | cd "$(dirname "$1")" 43 | LINK=$(readlink "$(basename "$1")") 44 | while [ "$LINK" ]; do 45 | cd "$(dirname "$LINK")" 46 | LINK=$(readlink "$(basename "$1")") 47 | done 48 | REALPATH="$PWD/$(basename "$1")" 49 | popd > /dev/null 50 | echo $REALPATH 51 | } 52 | 53 | fetch_and_install_dependencies() { 54 | DEPENDENCY_DIR=$1 55 | SOURCE_DIR=${DEPENDENCY_DIR}/sources 56 | INSTALL_DIR=${DEPENDENCY_DIR}/install 57 | mkdir -p ${SOURCE_DIR} 58 | echo "Created ${SOURCE_DIR}" 59 | mkdir -p ${INSTALL_DIR} 60 | echo "Created ${INSTALL_DIR}" 61 | cd ${SOURCE_DIR} && make_glog ${INSTALL_DIR} 62 | cd ${SOURCE_DIR} && make_gtest ${INSTALL_DIR} 63 | } 64 | 65 | if [ "x$1" == "x" ] || [ -d "$1" ] 66 | then 67 | echo "Must provided the name of a non existent folder as a parameter (will be used to install depenedencies)" 68 | exit 1 69 | fi 70 | 71 | fetch_and_install_dependencies `fullpath $1` 72 | -------------------------------------------------------------------------------- /src/cppmetrics/concurrent/simple_scheduled_thread_pool_executor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * simple_scheduled_thread_pool_executor.cpp 11 | * 12 | * Created on: Jun 11, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include "cppmetrics/concurrent/simple_scheduled_thread_pool_executor.h" 18 | 19 | namespace cppmetrics { 20 | namespace concurrent { 21 | 22 | namespace { 23 | typedef boost::asio::deadline_timer Timer; 24 | typedef boost::shared_ptr TimerPtr; 25 | } 26 | 27 | class SimpleScheduledThreadPoolExecutor::TimerTask { 28 | public: 29 | TimerTask() : 30 | period_(1000) { 31 | }; 32 | TimerTask(TimerPtr timer, boost::function task, 33 | boost::posix_time::milliseconds period, bool fixed_rate) : 34 | timer_(timer), task_(task), period_(period), fixed_rate_(fixed_rate) { 35 | 36 | } 37 | TimerPtr timer_; 38 | boost::function task_; 39 | boost::posix_time::milliseconds period_; 40 | bool fixed_rate_; 41 | }; 42 | 43 | SimpleScheduledThreadPoolExecutor::SimpleScheduledThreadPoolExecutor( 44 | size_t thread_count) : 45 | running_(true), 46 | work_ptr_(new boost::asio::io_service::work(io_service_)) { 47 | for (size_t i = 0; i < thread_count; ++i) { 48 | thread_group_.create_thread( 49 | boost::bind(&boost::asio::io_service::run, &io_service_)); 50 | } 51 | } 52 | 53 | SimpleScheduledThreadPoolExecutor::~SimpleScheduledThreadPoolExecutor() { 54 | shutdownNow(); 55 | } 56 | 57 | void SimpleScheduledThreadPoolExecutor::cancelTimers() { 58 | boost::lock_guard lock(timer_task_mutex_); 59 | BOOST_FOREACH(const TimerTask& timer_task, timer_tasks_) { 60 | boost::system::error_code ec; 61 | timer_task.timer_->cancel(ec); 62 | } 63 | } 64 | 65 | void SimpleScheduledThreadPoolExecutor::timerHandler( 66 | const boost::system::error_code& ec, size_t timer_index) { 67 | if (!running_) { 68 | LOG(ERROR)<< "Timer not started."; 69 | return; 70 | } 71 | 72 | if (ec) { 73 | LOG(ERROR) << "Unable to execute the timer, reason " << ec.message(); 74 | return; 75 | } 76 | 77 | TimerTask timer_task; 78 | try { 79 | boost::lock_guard lock(timer_task_mutex_); 80 | timer_task = timer_tasks_.at(timer_index); 81 | } catch (const std::out_of_range& oor) { 82 | LOG(ERROR) << "Unable to find the timer at index " << timer_index; 83 | return; 84 | } 85 | 86 | if (!timer_task.timer_) { 87 | LOG(ERROR) << "Unable to find the timer at index " << timer_index; 88 | return; 89 | } 90 | 91 | timer_task.task_(); 92 | boost::system::error_code eec; 93 | if (timer_task.fixed_rate_) { 94 | timer_task.timer_->expires_at( 95 | timer_task.timer_->expires_at() + timer_task.period_, eec); 96 | } else { 97 | timer_task.timer_->expires_from_now(timer_task.period_, eec); 98 | } 99 | 100 | if (eec) { 101 | LOG(ERROR) << "Unable to restart the time, reason " << eec.message(); 102 | } 103 | 104 | timer_task.timer_->async_wait( 105 | boost::bind(&SimpleScheduledThreadPoolExecutor::timerHandler, this, 106 | boost::asio::placeholders::error, timer_index)); 107 | } 108 | 109 | void SimpleScheduledThreadPoolExecutor::shutdown() { 110 | if (!running_) { 111 | return; 112 | } 113 | running_ = false; 114 | work_ptr_.reset(); 115 | thread_group_.interrupt_all(); 116 | thread_group_.join_all(); 117 | } 118 | 119 | void SimpleScheduledThreadPoolExecutor::shutdownNow() { 120 | if (!running_) { 121 | return; 122 | } 123 | running_ = false; 124 | cancelTimers(); 125 | io_service_.stop(); 126 | thread_group_.interrupt_all(); 127 | thread_group_.join_all(); 128 | } 129 | 130 | bool SimpleScheduledThreadPoolExecutor::isShutdown() const { 131 | return !running_; 132 | } 133 | 134 | void SimpleScheduledThreadPoolExecutor::scheduleTimer( 135 | boost::function task, boost::chrono::milliseconds interval, 136 | bool fixed_rate) { 137 | boost::posix_time::milliseconds period(interval.count()); 138 | TimerPtr timer(new Timer(io_service_, period)); 139 | size_t timer_index = 0; 140 | { 141 | boost::lock_guard lock(timer_task_mutex_); 142 | timer_tasks_.push_back(TimerTask(timer, task, period, fixed_rate)); 143 | timer_index = timer_tasks_.size() - 1; 144 | } 145 | timer->async_wait( 146 | boost::bind(&SimpleScheduledThreadPoolExecutor::timerHandler, this, 147 | boost::asio::placeholders::error, timer_index)); 148 | } 149 | 150 | void SimpleScheduledThreadPoolExecutor::scheduleAtFixedDelay( 151 | boost::function task, boost::chrono::milliseconds period) { 152 | scheduleTimer(task, period, false); 153 | } 154 | 155 | void SimpleScheduledThreadPoolExecutor::scheduleAtFixedRate( 156 | boost::function task, boost::chrono::milliseconds period) { 157 | scheduleTimer(task, period, true); 158 | } 159 | 160 | } /* namespace concurrent */ 161 | } /* namespace cppmetrics */ 162 | -------------------------------------------------------------------------------- /src/cppmetrics/concurrent/simple_scheduled_thread_pool_executor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * simple_scheduled_thread_pool_executor.h 11 | * 12 | * Created on: Jun 11, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef SIMPLE_SCHEDULED_THREAD_POOL_EXECUTOR_H_ 17 | #define SIMPLE_SCHEDULED_THREAD_POOL_EXECUTOR_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | namespace cppmetrics { 28 | namespace concurrent { 29 | 30 | /** 31 | * A simple threadpool that executes a given command at a given interval of time. 32 | */ 33 | class SimpleScheduledThreadPoolExecutor { 34 | public: 35 | 36 | /** 37 | * Creates a new instance with the given thread size. 38 | * @param pool_size The number of threads in the threadpool. 39 | */ 40 | SimpleScheduledThreadPoolExecutor(size_t pool_size); 41 | 42 | virtual ~SimpleScheduledThreadPoolExecutor(); 43 | 44 | /** 45 | * Executes the give task at the configured interval rate until shutdown is called. The given command 46 | * is executed at a fixed rate and therefore there might be more than one command running at a time 47 | * depending on the duration of the command. 48 | * @param command The command to execute at fixed interval. 49 | * @param period The interval between the start of the tasks. 50 | */ 51 | virtual void scheduleAtFixedRate(boost::function command, 52 | boost::chrono::milliseconds period); 53 | 54 | /** 55 | * Executes the give task at the configured interval delay until shutdown is called. The given command 56 | * is executed at a fixed delay. There can be only one task instance running at a given time. 57 | * @param command The command to execute at fixed delay. 58 | * @param period The time period between the end of the tasks. 59 | */ 60 | virtual void scheduleAtFixedDelay(boost::function command, 61 | boost::chrono::milliseconds period); 62 | 63 | /** 64 | * Shuts down the service, may or may not return immediately depending on the pending tasks. 65 | */ 66 | virtual void shutdown(); 67 | 68 | /** 69 | * Shuts down the service, will return immediately. 70 | */ 71 | virtual void shutdownNow(); 72 | 73 | /** 74 | * gets the threadpool state. 75 | * @return True if this is shutdown or shutting down, false otherwise. 76 | */ 77 | virtual bool isShutdown() const; 78 | private: 79 | void cancelTimers(); 80 | void timerHandler(const boost::system::error_code& ec, size_t timer_index); 81 | 82 | void scheduleTimer(boost::function task, 83 | boost::chrono::milliseconds period, bool fixed_rate); 84 | 85 | boost::atomic running_; 86 | boost::asio::io_service io_service_; 87 | boost::scoped_ptr work_ptr_; 88 | boost::thread_group thread_group_; 89 | 90 | class TimerTask; 91 | typedef std::vector TimerTasks; 92 | TimerTasks timer_tasks_; 93 | mutable boost::mutex timer_task_mutex_; 94 | }; 95 | 96 | } /* namespace concurrent */ 97 | } /* namespace cppmetrics */ 98 | #endif /* SIMPLE_SCHEDULED_THREAD_POOL_EXECUTOR_H_ */ 99 | -------------------------------------------------------------------------------- /src/cppmetrics/concurrent/simple_thread_pool_executor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * thread_pool_executor.cpp 11 | * 12 | * Created on: Jun 10, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include "cppmetrics/concurrent/simple_thread_pool_executor.h" 17 | 18 | namespace cppmetrics { 19 | namespace concurrent { 20 | 21 | SimpleThreadPoolExecutor::SimpleThreadPoolExecutor(size_t thread_count) : 22 | running_(true), 23 | work_ptr_(new boost::asio::io_service::work(io_service_)) { 24 | for (size_t i = 0; i < thread_count; ++i) { 25 | thread_group_.create_thread( 26 | boost::bind(&boost::asio::io_service::run, &io_service_)); 27 | } 28 | } 29 | 30 | SimpleThreadPoolExecutor::~SimpleThreadPoolExecutor() { 31 | shutdownNow(); 32 | } 33 | 34 | void SimpleThreadPoolExecutor::shutdown() { 35 | if (!running_) { 36 | return; 37 | } 38 | running_ = false; 39 | work_ptr_.reset(); 40 | thread_group_.interrupt_all(); 41 | thread_group_.join_all(); 42 | } 43 | 44 | void SimpleThreadPoolExecutor::shutdownNow() { 45 | if (!running_) { 46 | return; 47 | } 48 | running_ = false; 49 | io_service_.stop(); 50 | thread_group_.interrupt_all(); 51 | thread_group_.join_all(); 52 | } 53 | 54 | bool SimpleThreadPoolExecutor::isShutdown() const { 55 | return !running_; 56 | } 57 | 58 | void SimpleThreadPoolExecutor::execute(boost::function command) { 59 | io_service_.post(command); 60 | } 61 | 62 | } /* namespace concurrent */ 63 | } /* namespace cppmetrics */ 64 | -------------------------------------------------------------------------------- /src/cppmetrics/concurrent/simple_thread_pool_executor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * simple_thread_pool_executor.h 11 | * 12 | * Created on: Jun 10, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef SIMPLE_THREAD_POOL_EXECUTOR_H_ 17 | #define SIMPLE_THREAD_POOL_EXECUTOR_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | namespace cppmetrics { 28 | namespace concurrent { 29 | 30 | /** 31 | * A simple threadpool modeled after similar class in java. 32 | */ 33 | class SimpleThreadPoolExecutor { 34 | public: 35 | 36 | /** 37 | * Creates a new thread pool with the given number of threads. 38 | * @param thread_count The number of threads in the thread pool. 39 | */ 40 | SimpleThreadPoolExecutor(size_t thread_count); 41 | 42 | virtual ~SimpleThreadPoolExecutor(); 43 | 44 | /** 45 | * Executes the given task in one of the threads. 46 | * @param task The task to be executed. 47 | */ 48 | virtual void execute(boost::function command); 49 | 50 | /** 51 | * Shuts down the service, may or may not return immediately. 52 | */ 53 | virtual void shutdown(); 54 | 55 | /** 56 | * Shuts down the service, will return immediately. 57 | */ 58 | virtual void shutdownNow(); 59 | 60 | /** 61 | * gets the threadpool state. 62 | * @return True if this is shutdown or shutting down, false otherwise. 63 | */ 64 | virtual bool isShutdown() const; 65 | 66 | private: 67 | boost::atomic running_; 68 | boost::asio::io_service io_service_; 69 | boost::scoped_ptr work_ptr_; 70 | boost::thread_group thread_group_; 71 | }; 72 | 73 | } /* namespace concurrent */ 74 | } /* namespace cppmetrics */ 75 | #endif /* SIMPLE_THREAD_POOL_EXECUTOR_H_ */ 76 | -------------------------------------------------------------------------------- /src/cppmetrics/core/console_reporter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * console_reporter.cpp 11 | * 12 | * Created on: Jul 1, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include "console_reporter.h" 18 | #include "utils.h" 19 | 20 | namespace cppmetrics { 21 | namespace core { 22 | 23 | ConsoleReporter::ConsoleReporter(MetricRegistryPtr registry, 24 | std::ostream& ostr, 25 | boost::chrono::milliseconds rate_unit) : 26 | ScheduledReporter(registry, rate_unit), ostr_(ostr) { 27 | ostr_.setf(std::ios_base::fixed, std::ios_base::floatfield); 28 | ostr_.width(2); 29 | ostr_.precision(2); 30 | } 31 | 32 | ConsoleReporter::~ConsoleReporter() { 33 | } 34 | 35 | void ConsoleReporter::report(core::CounterMap counter_map, 36 | core::HistogramMap histogram_map, 37 | core::MeteredMap meter_map, 38 | core::TimerMap timer_map, 39 | core::GaugeMap gauge_map) { 40 | 41 | std::string timestamp = utc_timestamp(ostr_.getloc()); 42 | printWithBanner(timestamp, '='); 43 | 44 | if (!gauge_map.empty()) { 45 | printWithBanner("-- Gauges", '-'); 46 | BOOST_FOREACH(const core::GaugeMap::value_type& entry, gauge_map) { 47 | ostr_ << entry.first << std::endl; 48 | printGauge(entry.second); 49 | } 50 | ostr_ << std::endl; 51 | } 52 | 53 | if (!counter_map.empty()) { 54 | printWithBanner("-- Counters", '-'); 55 | BOOST_FOREACH(const core::CounterMap::value_type& entry, counter_map){ 56 | ostr_ << entry.first << std::endl; 57 | printCounter(entry.second); 58 | } 59 | ostr_ << std::endl; 60 | } 61 | 62 | if (!histogram_map.empty()) { 63 | printWithBanner("-- Histograms", '-'); 64 | BOOST_FOREACH(const core::HistogramMap::value_type& entry, histogram_map) { 65 | ostr_ << entry.first << std::endl; 66 | printHistogram(entry.second); 67 | } 68 | ostr_ << std::endl; 69 | } 70 | 71 | if (!meter_map.empty()) { 72 | printWithBanner("-- Meters", '-'); 73 | BOOST_FOREACH(const core::MeteredMap::value_type& entry, meter_map) { 74 | ostr_ << entry.first << std::endl; 75 | printMeter(entry.second); 76 | } 77 | ostr_ << std::endl; 78 | } 79 | 80 | if (!timer_map.empty()) { 81 | printWithBanner("-- Timers", '-'); 82 | BOOST_FOREACH(const core::TimerMap::value_type& entry, timer_map) { 83 | ostr_ << entry.first << std::endl; 84 | printTimer(entry.second); 85 | } 86 | ostr_ << std::endl; 87 | } 88 | ostr_ << std::endl; 89 | ostr_.flush(); 90 | } 91 | 92 | void ConsoleReporter::printMeter(const core::MeteredMap::mapped_type& meter) { 93 | ostr_ << " count = " << meter->getCount() << std::endl; 94 | ostr_ << " mean rate = " << convertRateUnit(meter->getMeanRate()) 95 | << " events per " << rateUnitInSec() << std::endl; 96 | ostr_ << " 1-minute rate = " 97 | << convertRateUnit(meter->getOneMinuteRate()) << " events per " 98 | << rateUnitInSec() << std::endl; 99 | ostr_ << " 5-minute rate = " 100 | << convertRateUnit(meter->getFiveMinuteRate()) << " events per " 101 | << rateUnitInSec() << std::endl; 102 | ostr_ << " 15-minute rate = " 103 | << convertRateUnit(meter->getFifteenMinuteRate()) << " events per " 104 | << rateUnitInSec() << std::endl; 105 | } 106 | 107 | void ConsoleReporter::printCounter(const core::CounterMap::mapped_type& counter_ptr) { 108 | ostr_ << " count = " << counter_ptr->getCount() << std::endl; 109 | } 110 | 111 | void ConsoleReporter::printGauge(const core::GaugeMap::mapped_type& gauge_ptr) { 112 | ostr_ << " value = " << gauge_ptr->getValue() << std::endl; 113 | } 114 | 115 | void ConsoleReporter::printHistogram(const core::HistogramMap::mapped_type& histogram_ptr) { 116 | ostr_ << " count = " << histogram_ptr->getCount() << std::endl; 117 | SnapshotPtr snapshot = histogram_ptr->getSnapshot(); 118 | ostr_ << " min = " << snapshot->getMin() << std::endl; 119 | ostr_ << " max = " << snapshot->getMax() << std::endl; 120 | ostr_ << " mean = " << snapshot->getMean() << std::endl; 121 | ostr_ << " stddev = " << snapshot->getStdDev() << std::endl; 122 | ostr_ << " median = " << snapshot->getMedian() << std::endl; 123 | ostr_ << " 75% <= " << snapshot->get75thPercentile() << std::endl; 124 | ostr_ << " 95% <= " << snapshot->get95thPercentile() << std::endl; 125 | ostr_ << " 98% <= " << snapshot->get98thPercentile() << std::endl; 126 | ostr_ << " 99% <= " << snapshot->get99thPercentile() << std::endl; 127 | ostr_ << " 99.9% <= " << snapshot->get999thPercentile() << std::endl; 128 | } 129 | 130 | void ConsoleReporter::printTimer(const core::TimerMap::mapped_type& timer) { 131 | SnapshotPtr snapshot = timer->getSnapshot(); 132 | ostr_ << " count = " << timer->getCount() << std::endl; 133 | ostr_ << " mean rate = " << convertRateUnit(timer->getMeanRate()) 134 | << " calls per " << rateUnitInSec() << std::endl; 135 | ostr_ << " 1-minute rate = " << convertRateUnit(timer->getOneMinuteRate()) 136 | << " calls per " << rateUnitInSec() << std::endl; 137 | ostr_ << " 5-minute rate = " << convertRateUnit(timer->getFiveMinuteRate()) 138 | << " calls per " << rateUnitInSec() << std::endl; 139 | ostr_ << " 15-minute rate = " << convertRateUnit(timer->getFifteenMinuteRate()) 140 | << " calls per " << rateUnitInSec() << std::endl; 141 | ostr_ << " min = " << convertDurationUnit(snapshot->getMin()) << " millis " << std::endl; 142 | ostr_ << " max = " << convertDurationUnit(snapshot->getMax()) << " millis " << std::endl; 143 | ostr_ << " mean = " << convertDurationUnit(snapshot->getMean()) << " millis " << std::endl; 144 | ostr_ << " stddev = " << convertDurationUnit(snapshot->getStdDev()) << " millis " << std::endl; 145 | ostr_ << " median = " << convertDurationUnit(snapshot->getMedian()) << " millis "<< std::endl; 146 | ostr_ << " 75% <= " << convertDurationUnit(snapshot->get75thPercentile()) << " millis " << std::endl; 147 | ostr_ << " 95% <= " << convertDurationUnit(snapshot->get95thPercentile()) << " millis " << std::endl; 148 | ostr_ << " 98% <= " << convertDurationUnit(snapshot->get98thPercentile()) << " millis " << std::endl; 149 | ostr_ << " 99% <= " << convertDurationUnit(snapshot->get99thPercentile()) << " millis " << std::endl; 150 | ostr_ << " 99.9% <= " << convertDurationUnit(snapshot->get999thPercentile())<< " millis " << std::endl; 151 | } 152 | 153 | void ConsoleReporter::printWithBanner(const std::string& s, char sep) { 154 | ostr_ << s << ' '; 155 | for (size_t i = 0; i < (CONSOLE_WIDTH - s.size() - 1); i++) { 156 | ostr_ << sep; 157 | } 158 | ostr_ << std::endl; 159 | } 160 | 161 | } /* namespace core */ 162 | } /* namespace cppmetrics */ 163 | -------------------------------------------------------------------------------- /src/cppmetrics/core/console_reporter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * console_reporter.h 11 | * 12 | * Created on: Jul 1, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef CONSOLE_REPORTER_H_ 17 | #define CONSOLE_REPORTER_H_ 18 | 19 | #include "cppmetrics/core/scheduled_reporter.h" 20 | 21 | namespace cppmetrics { 22 | namespace core { 23 | 24 | /* 25 | * A GLOG console reporter that periodically logs the metric values. 26 | */ 27 | class ConsoleReporter: public ScheduledReporter, boost::noncopyable { 28 | public: 29 | 30 | /** 31 | * Creates a {@link ConsoleReporter} instance. Uses the given registry. 32 | * @param registry The metric registry. 33 | * @param ostr The output stream used for printing the values. 34 | * @param rate_unit The conversion unit user for the rate metrics. 35 | */ 36 | ConsoleReporter(MetricRegistryPtr registry, 37 | std::ostream& ostr, 38 | boost::chrono::milliseconds rate_unit = boost::chrono::seconds(1)); 39 | virtual ~ConsoleReporter(); 40 | 41 | /** 42 | * Reports all the metrics from the registry periodically to the graphite server. 43 | * @param gauge_map all of the gauges in the registry 44 | * @param counter_map all of the counters in the registry 45 | * @param histogram_map all of the histograms in the registry 46 | * @param meter_map all of the meters in the registry 47 | * @param timer_map all of the timers in the registry 48 | */ 49 | virtual void report(core::CounterMap counter_map, 50 | core::HistogramMap histogram_map, 51 | core::MeteredMap meter_map, 52 | core::TimerMap timer_map, 53 | core::GaugeMap gauge_map); 54 | 55 | private: 56 | void printWithBanner(const std::string& s, char sep); 57 | 58 | void printGauge(const core::GaugeMap::mapped_type& metric); 59 | 60 | void printCounter(const core::CounterMap::mapped_type& metric); 61 | 62 | void printHistogram(const core::HistogramMap::mapped_type& metric); 63 | 64 | void printTimer(const core::TimerMap::mapped_type& metric); 65 | 66 | void printMeter(const core::MeteredMap::mapped_type& meter); 67 | 68 | static const size_t CONSOLE_WIDTH = 80; 69 | 70 | std::ostream& ostr_; 71 | 72 | }; 73 | 74 | } /* namespace core */ 75 | } /* namespace cppmetrics */ 76 | #endif /* CONSOLER_REPORTER_H_ */ 77 | -------------------------------------------------------------------------------- /src/cppmetrics/core/counter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * counter.h 11 | * 12 | * Created on: Jun 5, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef COUNTER_H_ 17 | #define COUNTER_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "cppmetrics/core/metric.h" 24 | 25 | namespace cppmetrics { 26 | namespace core { 27 | 28 | /** 29 | * An incrementing and decrementing counter metric. 30 | * thread-safety: thread safe 31 | */ 32 | class Counter: public Metric { 33 | public: 34 | 35 | /** 36 | * Constructor 37 | * @param n Initialize the counter with a value of \c n. 38 | */ 39 | Counter(boost::int64_t n = 0) : 40 | count_(n) { 41 | } 42 | 43 | virtual ~Counter() { 44 | } 45 | 46 | /** 47 | * @return the current value of the counter. 48 | */ 49 | boost::int64_t getCount() const { 50 | return count_; 51 | } 52 | 53 | /** 54 | * @param n reset the counter to the value \c n. 55 | */ 56 | void setCount(boost::int64_t n) { 57 | count_ = n; 58 | } 59 | 60 | /** 61 | * @param n increment the counter by \c n 62 | */ 63 | void increment(boost::int64_t n = 1) { 64 | count_ += n; 65 | } 66 | 67 | /** 68 | * @param n decrement the counter by \c n 69 | */ 70 | void decrement(boost::int64_t n = 1) { 71 | count_ -= n; 72 | } 73 | 74 | /** 75 | * Clears the counter, same as calling setCount(0) ; 76 | */ 77 | void clear() { 78 | setCount(0); 79 | } 80 | private: 81 | boost::atomic count_; 82 | }; 83 | 84 | typedef boost::shared_ptr CounterPtr; 85 | 86 | } /* namespace core */ 87 | } /* namespace cppmetrics */ 88 | #endif /* COUNTER_H_ */ 89 | -------------------------------------------------------------------------------- /src/cppmetrics/core/ewma.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * ewma.cpp 11 | * 12 | * Created on: Jun 4, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include "cppmetrics/core/ewma.h" 18 | 19 | namespace cppmetrics { 20 | namespace core { 21 | namespace internal { 22 | 23 | const int EWMA::INTERVAL_IN_SEC = 5; 24 | const int EWMA::ONE_MINUTE = 1; 25 | const int EWMA::FIVE_MINUTES = 5; 26 | const int EWMA::FIFTEEN_MINUTES = 15; 27 | // The following constants are calculated using the formulas used in computing linux load averages as described 28 | // in http://www.perfdynamics.com/Papers/la1.pdf 29 | const double EWMA::M1_ALPHA = 1 30 | - std::exp(static_cast(-(EWMA::INTERVAL_IN_SEC)) / (60 * EWMA::ONE_MINUTE)); 31 | const double EWMA::M5_ALPHA = 1 32 | - std::exp(static_cast(-(EWMA::INTERVAL_IN_SEC)) / (60 * EWMA::FIVE_MINUTES)); 33 | const double EWMA::M15_ALPHA = 1 34 | - std::exp(static_cast(-(EWMA::INTERVAL_IN_SEC)) / (60 * EWMA::FIFTEEN_MINUTES)); 35 | 36 | EWMA::EWMA(double alpha, boost::chrono::nanoseconds interval) : 37 | uncounted_(0), alpha_(alpha), interval_nanos_(interval.count()) { 38 | initialized_ = false; 39 | ewma_ = 0.0; 40 | } 41 | 42 | EWMA::EWMA(const EWMA &other) : 43 | uncounted_(other.uncounted_.load()), 44 | alpha_(other.alpha_), 45 | interval_nanos_(other.interval_nanos_) { 46 | initialized_ = other.initialized_.load(); 47 | ewma_ = other.ewma_.load(); 48 | } 49 | 50 | EWMA::~EWMA() { 51 | } 52 | 53 | void EWMA::update(boost::uint64_t n) { 54 | uncounted_ += n; 55 | } 56 | 57 | // Uses the EWMA calculation described here: 58 | // http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average 59 | // EMAlatest = EMAprevious + alpha * (RATEtoday - EMAprevious) 60 | void EWMA::tick() { 61 | const boost::uint64_t count = uncounted_.exchange(0); 62 | const double instant_rate = static_cast(count) / interval_nanos_; 63 | if (initialized_) { 64 | // This does an atomic fetch and add. 65 | // TODO: Add a AtomicDouble class. 66 | double cur_ewma = ewma_; 67 | const double new_rate = cur_ewma + (alpha_ * (instant_rate - cur_ewma)); 68 | ewma_.compare_exchange_strong(cur_ewma, new_rate); 69 | } else { 70 | ewma_ = instant_rate; 71 | initialized_ = true; 72 | } 73 | } 74 | 75 | double EWMA::getRate(boost::chrono::nanoseconds duration) const { 76 | return ewma_ * duration.count(); 77 | } 78 | 79 | } /* namespace internal */ 80 | } /* namespace core */ 81 | } /* namespace cppmetrics */ 82 | 83 | -------------------------------------------------------------------------------- /src/cppmetrics/core/ewma.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * ewma.h 11 | * 12 | * Created on: Jun 4, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef EWMA_H_ 17 | #define EWMA_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | namespace cppmetrics { 24 | namespace core { 25 | namespace internal { 26 | 27 | /** 28 | * An exponentially-weighted moving average. 29 | * describe in detail http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average 30 | * not thread-safe. 31 | */ 32 | class EWMA { 33 | public: 34 | /** 35 | * Creates a new EWMA which is equivalent to the UNIX one minute load average and which expects 36 | * to be ticked every 5 seconds. 37 | * @return a one-minute EWMA 38 | */ 39 | static EWMA oneMinuteEWMA() { 40 | return EWMA(M1_ALPHA, boost::chrono::seconds(INTERVAL_IN_SEC)); 41 | } 42 | 43 | /** 44 | * Creates a new EWMA which is equivalent to the UNIX five minute load average and which expects 45 | * to be ticked every 5 seconds. 46 | * @return a five-minute EWMA 47 | */ 48 | static EWMA fiveMinuteEWMA() { 49 | return EWMA(M5_ALPHA, boost::chrono::seconds(INTERVAL_IN_SEC)); 50 | } 51 | 52 | /** 53 | * Creates a new EWMA which is equivalent to the UNIX fifteen minute load average and which expects 54 | * to be ticked every 5 seconds. 55 | * @return a five-minute EWMA 56 | */ 57 | static EWMA fifteenMinuteEWMA() { 58 | return EWMA(M15_ALPHA, boost::chrono::seconds(INTERVAL_IN_SEC)); 59 | } 60 | 61 | /** 62 | * Create a new EWMA with a specific smoothing constant. 63 | * @param alpha the smoothing constant 64 | * @param interval the expected tick interval 65 | */ 66 | EWMA(double alpha, boost::chrono::nanoseconds interval); 67 | EWMA(const EWMA &other); 68 | ~EWMA(); 69 | 70 | /** 71 | * Update the moving average with a new value. 72 | * @param n the new value 73 | */ 74 | void update(boost::uint64_t n); 75 | 76 | /** 77 | * Mark the passage of time and decay the current rate accordingly. 78 | */ 79 | void tick(); 80 | 81 | /** 82 | * Returns the rate in the given units of time. 83 | * @param rate_unit the unit of time 84 | * @return the rate 85 | */ 86 | double getRate(boost::chrono::nanoseconds rate_unit = 87 | boost::chrono::seconds(1)) const; 88 | private: 89 | 90 | static const int INTERVAL_IN_SEC; 91 | static const int ONE_MINUTE; 92 | static const int FIVE_MINUTES; 93 | static const int FIFTEEN_MINUTES; 94 | static const double M1_ALPHA; 95 | static const double M5_ALPHA; 96 | static const double M15_ALPHA; 97 | 98 | boost::atomic initialized_; 99 | boost::atomic ewma_; 100 | boost::atomic uncounted_; 101 | const double alpha_; 102 | const boost::uint64_t interval_nanos_; 103 | }; 104 | 105 | } /* namespace internal */ 106 | } /* namespace core */ 107 | } /* namespace cppmetrics */ 108 | 109 | #endif /* EWMA_H_ */ 110 | -------------------------------------------------------------------------------- /src/cppmetrics/core/exp_decay_sample.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * exp_decay_sample.cpp 11 | * 12 | * Created on: Jun 5, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include "cppmetrics/core/exp_decay_sample.h" 18 | #include "cppmetrics/core/utils.h" 19 | 20 | namespace cppmetrics { 21 | namespace core { 22 | 23 | const double ExpDecaySample::DEFAULT_ALPHA = 0.015; 24 | const Clock::duration ExpDecaySample::RESCALE_THRESHOLD( 25 | boost::chrono::hours(1)); 26 | 27 | ExpDecaySample::ExpDecaySample(boost::uint32_t reservoir_size, double alpha) : 28 | alpha_(alpha), reservoir_size_(reservoir_size), count_(0) { 29 | clear(); 30 | rng_.seed(get_millis_from_epoch()); 31 | } 32 | 33 | ExpDecaySample::~ExpDecaySample() { 34 | } 35 | 36 | void ExpDecaySample::clear() { 37 | boost::lock_guard lock(mutex_); 38 | values_.clear(); 39 | count_ = 0; 40 | start_time_ = Clock::now(); 41 | next_scale_time_ = start_time_ + RESCALE_THRESHOLD; 42 | } 43 | 44 | boost::uint64_t ExpDecaySample::size() const { 45 | return std::min(reservoir_size_, count_.load()); 46 | } 47 | 48 | void ExpDecaySample::update(boost::int64_t value) { 49 | update(value, Clock::now()); 50 | } 51 | 52 | void ExpDecaySample::update(boost::int64_t value, 53 | const Clock::time_point& timestamp) { 54 | boost::lock_guard rlock(mutex_); 55 | rescaleIfNeeded(timestamp); 56 | boost::random::uniform_real_distribution<> dist(0, 1); 57 | boost::chrono::seconds dur = boost::chrono::duration_cast< 58 | boost::chrono::seconds>(timestamp - start_time_); 59 | double priority = 0.0; 60 | do { 61 | priority = std::exp(alpha_ * dur.count()) / dist(rng_); 62 | } while (std::isnan(priority)); 63 | 64 | boost::uint64_t count = ++count_; 65 | if (count <= reservoir_size_) { 66 | values_[priority] = value; 67 | } else { 68 | Double2Int64Map::iterator first_itt(values_.begin()); 69 | double first = first_itt->first; 70 | if (first < priority 71 | && values_.insert(std::make_pair(priority, value)).second) { 72 | values_.erase(first_itt); 73 | } 74 | } 75 | } 76 | 77 | void ExpDecaySample::rescaleIfNeeded(const Clock::time_point& now) { 78 | if (next_scale_time_ < now) { 79 | Clock::time_point prevStartTime = start_time_; 80 | next_scale_time_ = now + RESCALE_THRESHOLD; 81 | prevStartTime = start_time_; 82 | start_time_ = now; 83 | rescale(prevStartTime); 84 | } 85 | } 86 | 87 | void ExpDecaySample::rescale(const Clock::time_point& prevStartTime) { 88 | Double2Int64Map old_values; 89 | std::swap(values_, old_values); 90 | BOOST_FOREACH (const Double2Int64Map::value_type& kv, old_values) { 91 | boost::chrono::seconds dur = boost::chrono::duration_cast< 92 | boost::chrono::seconds>(start_time_ - prevStartTime); 93 | double key = kv.first * std::exp(-alpha_ * dur.count()); 94 | values_[key] = kv.second; 95 | } 96 | count_ = values_.size(); 97 | } 98 | 99 | SnapshotPtr ExpDecaySample::getSnapshot() const { 100 | ValueVector vals; 101 | vals.reserve(values_.size()); 102 | boost::lock_guard rlock(mutex_); 103 | BOOST_FOREACH (const Double2Int64Map::value_type& kv, values_) { 104 | vals.push_back(kv.second); 105 | } 106 | return SnapshotPtr(new Snapshot(vals)); 107 | } 108 | 109 | } /* namespace core */ 110 | } /* namespace cppmetrics */ 111 | -------------------------------------------------------------------------------- /src/cppmetrics/core/exp_decay_sample.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * exp_decay_sample.h 11 | * 12 | * Created on: Jun 5, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef EXP_DECAY_SAMPLE_H_ 17 | #define EXP_DECAY_SAMPLE_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "cppmetrics/core/types.h" 28 | #include "cppmetrics/core/sample.h" 29 | 30 | namespace cppmetrics { 31 | namespace core { 32 | 33 | /** 34 | * An exponentially-decaying random reservoir of {@code long}s. Uses Cormode et al's 35 | * forward-decaying priority reservoir sampling method to produce a statistically representative 36 | * sampling reservoir, exponentially biased towards newer entries. 37 | */ 38 | class ExpDecaySample: public Sample { 39 | public: 40 | 41 | /** 42 | * Creates a new {@link ExpDecaySample} of the given size and alpha factor. 43 | * @param size the number of samples to keep in the sampling reservoir 44 | * @param alpha the exponential decay factor; the higher this is, the more biased the reservoir 45 | * will be towards newer values 46 | */ 47 | ExpDecaySample(boost::uint32_t size = 1024, double alpha = DEFAULT_ALPHA); 48 | virtual ~ExpDecaySample(); 49 | 50 | virtual void clear(); 51 | 52 | /** 53 | * Returns the number of values recorded. 54 | * @return the number of values recorded 55 | */ 56 | virtual boost::uint64_t size() const; 57 | 58 | /** 59 | * Adds a new recorded value to the reservoir. 60 | * @param value a new recorded value 61 | */ 62 | virtual void update(boost::int64_t value); 63 | 64 | /** 65 | * Adds an old value with a fixed timestamp to the reservoir. 66 | * @param value the value to be added 67 | * @param timestamp the epoch timestamp of {@code value} in seconds 68 | */ 69 | virtual void update(boost::int64_t value, 70 | const Clock::time_point& timestamp); 71 | 72 | /** 73 | * Returns a snapshot of the reservoir's values. 74 | * @return a snapshot of the reservoir's values 75 | */ 76 | virtual SnapshotPtr getSnapshot() const; 77 | 78 | private: 79 | static const double DEFAULT_ALPHA; 80 | static const Clock::duration RESCALE_THRESHOLD; 81 | 82 | void rescaleIfNeeded(const Clock::time_point& when); 83 | void rescale(const Clock::time_point& old_start_time); 84 | 85 | const double alpha_; 86 | const boost::uint64_t reservoir_size_; 87 | boost::atomic count_; 88 | 89 | mutable boost::mutex mutex_; 90 | Clock::time_point start_time_; 91 | Clock::time_point next_scale_time_; 92 | 93 | typedef std::map Double2Int64Map; 94 | Double2Int64Map values_; 95 | mutable boost::mt11213b rng_; 96 | }; 97 | 98 | } /* namespace core */ 99 | } /* namespace cppmetrics */ 100 | #endif /* EXP_DECAY_SAMPLE_H_ */ 101 | -------------------------------------------------------------------------------- /src/cppmetrics/core/gauge.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * gauge.h 11 | * 12 | * Created on: Jun 9, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef GAUGE_H_ 17 | #define GAUGE_H_ 18 | 19 | #include 20 | #include 21 | #include "cppmetrics/core/metric.h" 22 | 23 | namespace cppmetrics { 24 | namespace core { 25 | 26 | /** 27 | * A gauge metric is an instantaneous reading of a particular value. Used typically 28 | * to instrument a queue size, backlog etc. 29 | * 30 | */ 31 | class Gauge: public Metric { 32 | public: 33 | virtual ~Gauge() { 34 | } 35 | 36 | /** 37 | * @return the current value of the guage. 38 | */ 39 | virtual boost::int64_t getValue() = 0; 40 | }; 41 | 42 | typedef boost::shared_ptr GaugePtr; 43 | 44 | } /* namespace core */ 45 | } /* namespace cppmetrics */ 46 | #endif /* GAUGE_H_ */ 47 | -------------------------------------------------------------------------------- /src/cppmetrics/core/histogram.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * histogram.cpp 11 | * 12 | * Created on: Jun 5, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include "cppmetrics/core/uniform_sample.h" 17 | #include "cppmetrics/core/exp_decay_sample.h" 18 | #include "cppmetrics/core/histogram.h" 19 | 20 | namespace cppmetrics { 21 | namespace core { 22 | 23 | Histogram::Histogram(SampleType sample_type) { 24 | if (sample_type == kUniform) { 25 | sample_.reset(new UniformSample()); 26 | } else if (sample_type == kBiased) { 27 | sample_.reset(new ExpDecaySample()); 28 | } else { 29 | throw std::invalid_argument("invalid sample_type."); 30 | } 31 | clear(); 32 | } 33 | 34 | Histogram::~Histogram() { 35 | } 36 | 37 | void Histogram::clear() { 38 | count_ = 0; 39 | sample_->clear(); 40 | } 41 | 42 | boost::uint64_t Histogram::getCount() const { 43 | return count_; 44 | } 45 | 46 | SnapshotPtr Histogram::getSnapshot() const { 47 | return sample_->getSnapshot(); 48 | } 49 | 50 | void Histogram::update(boost::int64_t value) { 51 | ++count_; 52 | sample_->update(value); 53 | } 54 | 55 | } /* namespace core */ 56 | } /* namespace cppmetrics */ 57 | -------------------------------------------------------------------------------- /src/cppmetrics/core/histogram.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * histogram.h 11 | * 12 | * Created on: Jun 5, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef HISTOGRAM_H_ 17 | #define HISTOGRAM_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "cppmetrics/core/metric.h" 25 | #include "cppmetrics/core/sampling.h" 26 | #include "cppmetrics/core/sample.h" 27 | 28 | namespace cppmetrics { 29 | namespace core { 30 | 31 | /** 32 | * A metric which calculates the distribution of a value. 33 | * Thread-safe. 34 | */ 35 | class Histogram: public Metric, Sampling { 36 | public: 37 | /** 38 | * Creates a new histogram based on the sample type. 39 | * @param sample_type the sample to use internally. 40 | * @see SamplingInterface for different types of samples. 41 | */ 42 | Histogram(SampleType sample_type = kBiased); 43 | virtual ~Histogram(); 44 | 45 | /** 46 | * @return the current snapshot based on the sample. 47 | */ 48 | virtual SnapshotPtr getSnapshot() const; 49 | 50 | /** 51 | * Adds a recorded value. 52 | * @param value The length of the value. 53 | */ 54 | void update(boost::int64_t value); 55 | 56 | /** 57 | * @return The number of values recorded until now. 58 | */ 59 | boost::uint64_t getCount() const; 60 | 61 | /** 62 | * Clears the underlying sample. 63 | */ 64 | void clear(); 65 | 66 | /**< The Maximum sample size at any given time. */ 67 | static const boost::uint64_t DEFAULT_SAMPLE_SIZE; 68 | private: 69 | static const double DEFAULT_ALPHA; 70 | 71 | boost::scoped_ptr sample_; /**< The underlying sample implementation. */ 72 | boost::atomic count_; /**< The number of samples. */ 73 | }; 74 | 75 | typedef boost::shared_ptr HistogramPtr; 76 | 77 | } /* namespace core */ 78 | } /* namespace cppmetrics */ 79 | #endif /* HISTOGRAM_H_ */ 80 | -------------------------------------------------------------------------------- /src/cppmetrics/core/meter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * meter.cpp 11 | * 12 | * Created on: Jun 4, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include "cppmetrics/core/meter.h" 17 | #include "cppmetrics/core/ewma.h" 18 | #include "cppmetrics/core/types.h" 19 | #include "cppmetrics/core/utils.h" 20 | 21 | namespace cppmetrics { 22 | namespace core { 23 | 24 | static const uint64_t TICK_INTERVAL = 25 | Clock::duration(boost::chrono::seconds(5)).count(); 26 | 27 | class Meter::Impl { 28 | public: 29 | Impl(boost::chrono::nanoseconds rate_unit); 30 | ~Impl(); 31 | boost::uint64_t getCount() const; 32 | double getFifteenMinuteRate(); 33 | double getFiveMinuteRate(); 34 | double getOneMinuteRate(); 35 | double getMeanRate(); 36 | void mark(boost::uint64_t n); 37 | 38 | private: 39 | const boost::chrono::nanoseconds rate_unit_; 40 | boost::atomic count_; 41 | const Clock::time_point start_time_; 42 | boost::atomic last_tick_; 43 | internal::EWMA m1_rate_; 44 | internal::EWMA m5_rate_; 45 | internal::EWMA m15_rate_; 46 | 47 | void tick(); 48 | void tickIfNecessary(); 49 | }; 50 | 51 | Meter::Impl::Impl(boost::chrono::nanoseconds rate_unit) : 52 | rate_unit_(rate_unit), 53 | count_(0), 54 | start_time_(Clock::now()), 55 | last_tick_( 56 | boost::chrono::duration_cast( 57 | start_time_.time_since_epoch()).count()), 58 | m1_rate_(internal::EWMA::oneMinuteEWMA()), 59 | m5_rate_(internal::EWMA::fiveMinuteEWMA()), 60 | m15_rate_(internal::EWMA::fifteenMinuteEWMA()) { 61 | } 62 | 63 | Meter::Impl::~Impl() { 64 | } 65 | 66 | boost::uint64_t Meter::Impl::getCount() const { 67 | return count_; 68 | } 69 | 70 | double Meter::Impl::getFifteenMinuteRate() { 71 | tickIfNecessary(); 72 | return m15_rate_.getRate(); 73 | } 74 | 75 | double Meter::Impl::getFiveMinuteRate() { 76 | tickIfNecessary(); 77 | return m5_rate_.getRate(); 78 | } 79 | 80 | double Meter::Impl::getOneMinuteRate() { 81 | tickIfNecessary(); 82 | return m1_rate_.getRate(); 83 | } 84 | 85 | double Meter::Impl::getMeanRate() { 86 | boost::uint64_t c = count_; 87 | if (c > 0) { 88 | boost::chrono::nanoseconds elapsed = boost::chrono::duration_cast< 89 | boost::chrono::nanoseconds>(Clock::now() - start_time_); 90 | return static_cast(c * rate_unit_.count()) / elapsed.count(); 91 | } 92 | return 0.0; 93 | } 94 | 95 | void Meter::Impl::mark(boost::uint64_t n) { 96 | tickIfNecessary(); 97 | count_ += n; 98 | m1_rate_.update(n); 99 | m5_rate_.update(n); 100 | m15_rate_.update(n); 101 | } 102 | 103 | void Meter::Impl::tick() { 104 | m1_rate_.tick(); 105 | m5_rate_.tick(); 106 | m15_rate_.tick(); 107 | } 108 | 109 | void Meter::Impl::tickIfNecessary() { 110 | boost::uint64_t old_tick = last_tick_; 111 | boost::uint64_t cur_tick = 112 | boost::chrono::duration_cast( 113 | Clock::now().time_since_epoch()).count(); 114 | boost::uint64_t age = cur_tick - old_tick; 115 | if (age > TICK_INTERVAL) { 116 | boost::uint64_t new_tick = cur_tick - age % TICK_INTERVAL; 117 | if (last_tick_.compare_exchange_strong(old_tick, new_tick)) { 118 | boost::uint64_t required_ticks = age / TICK_INTERVAL; 119 | for (boost::uint64_t i = 0; i < required_ticks; i++) { 120 | tick(); 121 | } 122 | } 123 | } 124 | } 125 | 126 | Meter::Meter(boost::chrono::nanoseconds rate_unit) : 127 | impl_(new Meter::Impl(rate_unit)) { 128 | } 129 | 130 | Meter::~Meter() { 131 | 132 | } 133 | 134 | boost::uint64_t Meter::getCount() const { 135 | return impl_->getCount(); 136 | } 137 | 138 | double Meter::getFifteenMinuteRate() { 139 | return impl_->getFifteenMinuteRate(); 140 | } 141 | 142 | double Meter::getFiveMinuteRate() { 143 | return impl_->getFiveMinuteRate(); 144 | } 145 | 146 | double Meter::getOneMinuteRate() { 147 | return impl_->getOneMinuteRate(); 148 | } 149 | 150 | double Meter::getMeanRate() { 151 | return impl_->getMeanRate(); 152 | } 153 | 154 | void Meter::mark(boost::uint64_t n) { 155 | impl_->mark(n); 156 | } 157 | 158 | } /* namespace core */ 159 | } /* namespace cppmetrics */ 160 | -------------------------------------------------------------------------------- /src/cppmetrics/core/meter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * meter.h 11 | * 12 | * Created on: Jun 4, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef METER_H_ 17 | #define METER_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "cppmetrics/core/metered.h" 24 | 25 | namespace cppmetrics { 26 | namespace core { 27 | 28 | /** 29 | * A meter metric which measures mean throughput and one-, five-, and fifteen-minute 30 | * exponentially-weighted moving average throughputs. 31 | */ 32 | class Meter: public Metered { 33 | public: 34 | /** 35 | * Creates a meter with the specified rate unit. 36 | * @param rate_unit The rate unit in nano seconds. 37 | */ 38 | Meter(boost::chrono::nanoseconds rate_unit = boost::chrono::seconds(1)); 39 | 40 | virtual ~Meter(); 41 | 42 | /** 43 | * @returns the number of events that have been marked. 44 | */ 45 | virtual boost::uint64_t getCount() const; 46 | 47 | /** 48 | * @return the fifteen-minute exponentially-weighted moving average rate at which events have 49 | * occurred since the meter was created. 50 | */ 51 | virtual double getFifteenMinuteRate(); 52 | 53 | /** 54 | * @return the five-minute exponentially-weighted moving average rate at which events have 55 | * occurred since the meter was created. 56 | */ 57 | virtual double getFiveMinuteRate(); 58 | 59 | /** 60 | * @return the one-minute exponentially-weighted moving average rate at which events have 61 | * occurred since the meter was created. 62 | */ 63 | virtual double getOneMinuteRate(); 64 | 65 | /** 66 | * @return the mean rate at which events have occurred since the meter was created. 67 | */ 68 | virtual double getMeanRate(); 69 | 70 | /** 71 | * Mark the occurrence of a given number of events. 72 | * @param n the number of events with the default being 1. 73 | */ 74 | void mark(boost::uint64_t n = 1); 75 | 76 | private: 77 | class Impl; 78 | boost::scoped_ptr impl_; 79 | }; 80 | 81 | typedef boost::shared_ptr MeterPtr; 82 | 83 | } /* namespace core */ 84 | } /* namespace cppmetrics */ 85 | #endif /* METER_H_ */ 86 | -------------------------------------------------------------------------------- /src/cppmetrics/core/metered.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * metered.h 11 | * 12 | * Created on: Jun 4, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef METERED_H_ 17 | #define METERED_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "cppmetrics/core/metric.h" 24 | 25 | namespace cppmetrics { 26 | namespace core { 27 | 28 | /** 29 | * Interface for objects which maintains mean and exponentially-weighted rate. 30 | */ 31 | class Metered: public Metric { 32 | public: 33 | virtual ~Metered() { 34 | } 35 | /** 36 | * @returns the number of events that have been marked. 37 | */ 38 | virtual boost::uint64_t getCount() const = 0; 39 | /** 40 | * @return the fifteen-minute exponentially-weighted moving average rate at which events have 41 | * occurred since the meter was created. 42 | */ 43 | virtual double getFifteenMinuteRate() = 0; 44 | /** 45 | * @return the fifteen-minute exponentially-weighted moving average rate at which events have 46 | * occurred since the meter was created. 47 | */ 48 | virtual double getFiveMinuteRate() = 0; 49 | /** 50 | * @return the fifteen-minute exponentially-weighted moving average rate at which events have 51 | * occurred since the meter was created. 52 | */ 53 | virtual double getOneMinuteRate() = 0; 54 | /** 55 | * @return the average rate at which events have occurred since the meter was created. 56 | */ 57 | virtual double getMeanRate() = 0; 58 | }; 59 | 60 | typedef boost::shared_ptr MeteredPtr; 61 | 62 | } /* namespace core */ 63 | } /* namespace cppmetrics */ 64 | #endif /* METERED_H_ */ 65 | -------------------------------------------------------------------------------- /src/cppmetrics/core/metric.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * metric.h 11 | * 12 | * Created on: Jun 4, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef METRIC_H_ 17 | #define METRIC_H_ 18 | 19 | #include 20 | 21 | namespace cppmetrics { 22 | namespace core { 23 | 24 | /** 25 | * The base class for all metrics types. 26 | */ 27 | class Metric { 28 | public: 29 | virtual ~Metric() = 0; 30 | }; 31 | 32 | inline Metric::~Metric() { 33 | } 34 | 35 | typedef boost::shared_ptr MetricPtr; 36 | 37 | } /* namespace core */ 38 | } /* namespace cppmetrics */ 39 | #endif /* METRIC_H_ */ 40 | -------------------------------------------------------------------------------- /src/cppmetrics/core/metric_registry.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * metric_registry.cpp 11 | * 12 | * Created on: Jun 9, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include "cppmetrics/core/metric_registry.h" 21 | 22 | namespace cppmetrics { 23 | namespace core { 24 | 25 | class MetricRegistry::Impl { 26 | public: 27 | Impl(); 28 | ~Impl(); 29 | 30 | bool addGauge(const std::string& name, GaugePtr metric); 31 | bool removeMetric(const std::string& name); 32 | 33 | CounterPtr counter(const std::string& name); 34 | HistogramPtr histogram(const std::string& name); 35 | MeterPtr meter(const std::string& name); 36 | TimerPtr timer(const std::string& name); 37 | 38 | CounterMap getCounters() const; 39 | HistogramMap getHistograms() const; 40 | MeteredMap getMeters() const; 41 | TimerMap getTimers() const; 42 | GaugeMap getGauges() const; 43 | 44 | size_t count() const; 45 | private: 46 | // Old C++98 style enum. 47 | enum MetricType { 48 | GaugeType = 0, 49 | CounterType, 50 | HistogramType, 51 | MeterType, 52 | TimerType, 53 | TotalTypes 54 | }; 55 | 56 | mutable boost::shared_mutex metrics_mutex_; /**< mutex that protects both MetricSets and metric_names. */ 57 | // We should use a lock-free concurrent map implementation outside of boost. 58 | typedef boost::unordered_map MetricSet; 59 | MetricSet metric_set_[TotalTypes]; 60 | typedef std::set StringSet; 61 | StringSet metric_names_; 62 | 63 | template 64 | bool isInstanceOf(const MetricPtr& metric_ptr) const; 65 | 66 | bool addMetric(MetricSet& metric_set, 67 | const std::string& name, 68 | MetricPtr metric); 69 | 70 | MetricPtr buildMetric(MetricType metric_type) const; 71 | MetricPtr getOrAdd(MetricType metric_type, const std::string& name); 72 | 73 | template 74 | std::map > getMetrics(const MetricSet& metric_set) const; 75 | }; 76 | 77 | MetricRegistry::Impl::Impl() { 78 | 79 | } 80 | 81 | MetricRegistry::Impl::~Impl() { 82 | 83 | } 84 | 85 | size_t MetricRegistry::Impl::count() const { 86 | boost::shared_lock read_lock(metrics_mutex_); 87 | return metric_names_.size(); 88 | } 89 | 90 | // RTTI is a performance overhead, should probably replace it in future. 91 | template 92 | bool MetricRegistry::Impl::isInstanceOf(const MetricPtr& metric_ptr) const { 93 | boost::shared_ptr stored_metric( 94 | boost::dynamic_pointer_cast(metric_ptr)); 95 | return (stored_metric.get() != NULL); 96 | } 97 | 98 | MetricPtr MetricRegistry::Impl::buildMetric(MetricType metric_type) const { 99 | MetricPtr metric_ptr; 100 | switch (metric_type) { 101 | case CounterType: 102 | return boost::make_shared(); 103 | case HistogramType: 104 | return boost::make_shared(); 105 | case MeterType: 106 | return boost::make_shared(); 107 | case TimerType: 108 | return boost::make_shared(); 109 | default: 110 | throw std::invalid_argument("Unknown or invalid metric type."); 111 | }; 112 | } 113 | 114 | bool MetricRegistry::Impl::addMetric(MetricSet& metric_set, 115 | const std::string& name, 116 | MetricPtr new_metric) { 117 | StringSet::iterator s_itt(metric_names_.find(name)); 118 | if (s_itt == metric_names_.end()) { 119 | metric_names_.insert(name); 120 | return metric_set.insert(std::make_pair(name, new_metric)).second; 121 | } 122 | throw std::invalid_argument( 123 | name + " already exists as a different metric."); 124 | } 125 | 126 | MetricPtr MetricRegistry::Impl::getOrAdd(MetricType metric_type, 127 | const std::string& name) { 128 | boost::unique_lock wlock(metrics_mutex_); 129 | MetricSet& metric_set(metric_set_[metric_type]); 130 | MetricSet::iterator itt(metric_set.find(name)); 131 | if (itt != metric_set.end()) { 132 | return itt->second; 133 | } else { 134 | MetricPtr new_metric(buildMetric(metric_type)); 135 | addMetric(metric_set, name, new_metric); 136 | return new_metric; 137 | } 138 | } 139 | 140 | bool MetricRegistry::Impl::addGauge(const std::string& name, GaugePtr gauge) { 141 | boost::unique_lock wlock(metrics_mutex_); 142 | return addMetric(metric_set_[GaugeType], name, gauge); 143 | } 144 | 145 | CounterPtr MetricRegistry::Impl::counter(const std::string& name) { 146 | MetricPtr metric_ptr(getOrAdd(CounterType, name)); 147 | return boost::static_pointer_cast(metric_ptr); 148 | } 149 | 150 | HistogramPtr MetricRegistry::Impl::histogram(const std::string& name) { 151 | MetricPtr metric_ptr(getOrAdd(HistogramType, name)); 152 | return boost::static_pointer_cast(metric_ptr); 153 | } 154 | 155 | MeterPtr MetricRegistry::Impl::meter(const std::string& name) { 156 | MetricPtr metric_ptr(getOrAdd(MeterType, name)); 157 | return boost::static_pointer_cast(metric_ptr); 158 | } 159 | 160 | TimerPtr MetricRegistry::Impl::timer(const std::string& name) { 161 | MetricPtr metric_ptr(getOrAdd(TimerType, name)); 162 | return boost::static_pointer_cast(metric_ptr); 163 | } 164 | 165 | template 166 | std::map > 167 | MetricRegistry::Impl::getMetrics(const MetricSet& metric_set) const { 168 | std::map > ret_set; 169 | boost::shared_lock rlock(metrics_mutex_); 170 | BOOST_FOREACH (const MetricSet::value_type& kv, metric_set) { 171 | ret_set[kv.first] = boost::static_pointer_cast(kv.second); 172 | } 173 | return ret_set; 174 | } 175 | 176 | CounterMap MetricRegistry::Impl::getCounters() const { 177 | return getMetrics(metric_set_[CounterType]); 178 | } 179 | 180 | HistogramMap MetricRegistry::Impl::getHistograms() const { 181 | return getMetrics(metric_set_[HistogramType]); 182 | } 183 | 184 | MeteredMap MetricRegistry::Impl::getMeters() const { 185 | return getMetrics(metric_set_[MeterType]); 186 | } 187 | 188 | TimerMap MetricRegistry::Impl::getTimers() const { 189 | return getMetrics(metric_set_[TimerType]); 190 | } 191 | 192 | GaugeMap MetricRegistry::Impl::getGauges() const { 193 | return getMetrics(metric_set_[GaugeType]); 194 | } 195 | 196 | bool MetricRegistry::Impl::removeMetric(const std::string& name) { 197 | boost::unique_lock wlock(metrics_mutex_); 198 | StringSet::iterator s_itt(metric_names_.find(name)); 199 | if (s_itt != metric_names_.end()) { 200 | for (size_t i = 0; i < TotalTypes; ++i) { 201 | if (metric_set_[i].erase(name) > 0) { 202 | break; 203 | } 204 | } 205 | metric_names_.erase(s_itt); 206 | return true; 207 | } 208 | return false; 209 | } 210 | 211 | // <=================Implementation end============> 212 | 213 | MetricRegistryPtr MetricRegistry::DEFAULT_REGISTRY() { 214 | static MetricRegistryPtr g_metric_registry(new MetricRegistry()); 215 | return g_metric_registry; 216 | } 217 | 218 | MetricRegistry::MetricRegistry() : 219 | impl_(new MetricRegistry::Impl()) { 220 | } 221 | 222 | MetricRegistry::~MetricRegistry() { 223 | } 224 | 225 | CounterPtr MetricRegistry::counter(const std::string& name) { 226 | return impl_->counter(name); 227 | } 228 | 229 | HistogramPtr MetricRegistry::histogram(const std::string& name) { 230 | return impl_->histogram(name); 231 | } 232 | 233 | MeterPtr MetricRegistry::meter(const std::string& name) { 234 | return impl_->meter(name); 235 | } 236 | 237 | TimerPtr MetricRegistry::timer(const std::string& name) { 238 | return impl_->timer(name); 239 | } 240 | 241 | CounterMap MetricRegistry::getCounters() const { 242 | return impl_->getCounters(); 243 | } 244 | 245 | HistogramMap MetricRegistry::getHistograms() const { 246 | return impl_->getHistograms(); 247 | } 248 | 249 | MeteredMap MetricRegistry::getMeters() const { 250 | return impl_->getMeters(); 251 | } 252 | 253 | TimerMap MetricRegistry::getTimers() const { 254 | return impl_->getTimers(); 255 | } 256 | 257 | GaugeMap MetricRegistry::getGauges() const { 258 | return impl_->getGauges(); 259 | } 260 | 261 | size_t MetricRegistry::count() const { 262 | return impl_->count(); 263 | } 264 | 265 | bool MetricRegistry::addGauge(const std::string& name, GaugePtr metric) { 266 | return impl_->addGauge(name, metric); 267 | } 268 | 269 | bool MetricRegistry::removeMetric(const std::string& name) { 270 | return impl_->removeMetric(name); 271 | } 272 | 273 | } /* namespace core */ 274 | } /* namespace cppmetrics */ 275 | -------------------------------------------------------------------------------- /src/cppmetrics/core/metric_registry.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * metric_registry.h 11 | * 12 | * Created on: Jun 9, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef METRIC_REGISTRY_H_ 17 | #define METRIC_REGISTRY_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "cppmetrics/core/counter.h" 25 | #include "cppmetrics/core/gauge.h" 26 | #include "cppmetrics/core/histogram.h" 27 | #include "cppmetrics/core/meter.h" 28 | #include "cppmetrics/core/timer.h" 29 | 30 | namespace cppmetrics { 31 | namespace core { 32 | 33 | typedef std::map CounterMap; 34 | typedef std::map HistogramMap; 35 | typedef std::map MeteredMap; 36 | typedef std::map TimerMap; 37 | typedef std::map GaugeMap; 38 | 39 | class MetricRegistry; 40 | typedef boost::shared_ptr MetricRegistryPtr; 41 | /** 42 | * The thread-safe registry class for all metrics. 43 | */ 44 | class MetricRegistry: boost::noncopyable { 45 | public: 46 | 47 | /** 48 | * Singleton factory method for the Metric registry. 49 | * @return The default singleton metric registry 50 | */ 51 | static MetricRegistryPtr DEFAULT_REGISTRY(); 52 | 53 | /** 54 | * Creates a new registry. 55 | */ 56 | MetricRegistry(); 57 | 58 | ~MetricRegistry(); 59 | 60 | /** 61 | * Adds a gauge with the given name to the registry. 62 | * @param name The name of the gauge metric. 63 | * @param metric A subclass object of the Gauge. 64 | * @return True on creation, false if the gauge is already present. 65 | * @throws std::invalid_argument exception if a metric of different type with the same name is already present. 66 | */ 67 | bool addGauge(const std::string& name, GaugePtr metric); 68 | 69 | /** 70 | * Removes the metric with the given name from the registry. 71 | * @param name The name of the metric 72 | * @return True on success, false if the metric with the name is not present. 73 | */ 74 | bool removeMetric(const std::string& name); 75 | 76 | /** 77 | * Gets a {@link Counter} from the registry with the given name if present otherwise creates and adds a new 78 | * {@link Counter} and returns the newly added one. 79 | * @param name The name of the Counter. 80 | * @return shared_ptr to the Counter object. 81 | * @throws std::invalid_argument if a metric with the same name but different type exists in the registry. 82 | */ 83 | CounterPtr counter(const std::string& name); 84 | 85 | /** 86 | * Gets a {@link Histogram} from the registry with the given name if present otherwise creates and adds a new 87 | * {@link Histogram} and returns the newly added one. 88 | * @param name The name of the Histogram. 89 | * @return shared_ptr to the Histogram ojbect. 90 | * @throws std::invalid_argument if a metric with the same name but different type exists in the registry. 91 | */ 92 | HistogramPtr histogram(const std::string& name); 93 | 94 | /** 95 | * Gets a {@link Meter} from the registry with the given name if present otherwise creates and adds a new 96 | * {@link Meter} and returns the newly added one. 97 | * @param name The name of the Meter. 98 | * @return shared_ptr to the Meter ojbect. 99 | * @throws std::invalid_argument if a metric with the same name but different type exists in the registry. 100 | */ 101 | MeterPtr meter(const std::string& name); 102 | 103 | /** 104 | * Gets a {@link Timer} from the registry with the given name if present otherwise creates and adds a new 105 | * {@link Timer} and returns the newly added one. 106 | * @param name The name of the Timer. 107 | * @return shared_ptr to the Timer ojbect. 108 | * @throws std::invalid_argument if a metric with the same name but different type exists in the registry. 109 | */ 110 | TimerPtr timer(const std::string& name); 111 | 112 | /** 113 | * Returns all the counters and their names currently in the registry. 114 | * @return all the counters in the registry. 115 | */ 116 | CounterMap getCounters() const; 117 | 118 | /** 119 | * Returns all the histograms and their names currently in the registry. 120 | * @return all the histograms in the registry. 121 | */ 122 | HistogramMap getHistograms() const; 123 | 124 | /** 125 | * Returns all the meters and their names currently in the registry. 126 | * @return all the meters in the registry. 127 | */ 128 | MeteredMap getMeters() const; 129 | 130 | /** 131 | * Returns all the timers and their names currently in the registry. 132 | * @return all the timers in the registry. 133 | */ 134 | TimerMap getTimers() const; 135 | 136 | /** 137 | * Returns all the gauges and their names currently in the registry. 138 | * @return all the gauges in the registry. 139 | */ 140 | GaugeMap getGauges() const; 141 | 142 | /** 143 | * Gets the total number of metrics in the registry. 144 | * @return the total metrics count. 145 | */ 146 | size_t count() const; 147 | 148 | private: 149 | class Impl; 150 | boost::scoped_ptr impl_; /**< The pimpl pointer */ 151 | }; 152 | 153 | } /* namespace core */ 154 | } /* namespace cppmetrics */ 155 | #endif /* METRIC_REGISTRY_H_ */ 156 | -------------------------------------------------------------------------------- /src/cppmetrics/core/reporter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * reporter.h 11 | * 12 | * Created on: Jun 10, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef REPORTER_H_ 17 | #define REPORTER_H_ 18 | 19 | namespace cppmetrics { 20 | namespace core { 21 | 22 | /** 23 | * The interface for all the reporter sub classes. 24 | */ 25 | class Reporter { 26 | public: 27 | virtual ~Reporter() { 28 | } 29 | 30 | /** 31 | * reports the metrics. 32 | */ 33 | virtual void report() = 0; 34 | }; 35 | 36 | } /* namespace core */ 37 | } /* namespace cppmetrics */ 38 | #endif /* REPORTER_H_ */ 39 | -------------------------------------------------------------------------------- /src/cppmetrics/core/sample.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * sample.h 11 | * 12 | * Created on: Jun 5, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef SAMPLE_H_ 17 | #define SAMPLE_H_ 18 | 19 | #include "cppmetrics/core/snapshot.h" 20 | 21 | namespace cppmetrics { 22 | namespace core { 23 | 24 | /** 25 | * A statistically representative sample of a data stream. 26 | */ 27 | class Sample { 28 | public: 29 | virtual ~Sample() { 30 | } 31 | 32 | /** 33 | * Clears the values in the sample. 34 | */ 35 | virtual void clear() = 0; 36 | 37 | /** 38 | * Returns the number of values recorded. 39 | * @return the number of values recorded 40 | */ 41 | virtual boost::uint64_t size() const = 0; 42 | 43 | /** 44 | * Adds a new recorded value to the sample. 45 | * @param value a new recorded value 46 | */ 47 | virtual void update(boost::int64_t value) = 0; 48 | 49 | /** 50 | * Returns a snapshot of the sample's values. 51 | * @return a snapshot of the sample's values 52 | */ 53 | virtual SnapshotPtr getSnapshot() const = 0; 54 | }; 55 | 56 | } /* namespace core */ 57 | } /* namespace cppmetrics */ 58 | #endif /* SAMPLE_H_ */ 59 | -------------------------------------------------------------------------------- /src/cppmetrics/core/sampling.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * sampling.h 11 | * 12 | * Created on: Jun 5, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef SAMPLING_H_ 17 | #define SAMPLING_H_ 18 | 19 | #include "cppmetrics/core/snapshot.h" 20 | 21 | namespace cppmetrics { 22 | namespace core { 23 | 24 | /** 25 | * The interface for all classes that sample values. 26 | */ 27 | class Sampling { 28 | public: 29 | enum SampleType { 30 | kUniform, kBiased 31 | }; 32 | virtual ~Sampling() { 33 | } 34 | 35 | /** 36 | * Returns the snapshot of values in the sample. 37 | * @return the snapshot of values in the sample. 38 | */ 39 | virtual SnapshotPtr getSnapshot() const = 0; 40 | }; 41 | 42 | } /* namespace core */ 43 | } /* namespace cppmetrics */ 44 | #endif /* SAMPLING_H_ */ 45 | -------------------------------------------------------------------------------- /src/cppmetrics/core/scheduled_reporter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * scheduled_reporter.cpp 11 | * 12 | * Created on: Jun 10, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include "cppmetrics/core/scheduled_reporter.h" 18 | 19 | namespace cppmetrics { 20 | namespace core { 21 | 22 | ScheduledReporter::ScheduledReporter(MetricRegistryPtr registry, 23 | boost::chrono::milliseconds rate_unit) : 24 | running_(false), 25 | metric_registry_(registry), 26 | scheduled_executor_(1), 27 | rate_factor_( 28 | boost::chrono::milliseconds(1000).count() 29 | / rate_unit.count()), 30 | duration_factor_( 31 | static_cast(1.0) 32 | / boost::chrono::duration_cast< 33 | boost::chrono::nanoseconds>( 34 | boost::chrono::milliseconds(1)).count()) { 35 | 36 | } 37 | 38 | ScheduledReporter::~ScheduledReporter() { 39 | stop(); 40 | } 41 | 42 | void ScheduledReporter::report() { 43 | CounterMap counter_map(metric_registry_->getCounters()); 44 | HistogramMap histogram_map(metric_registry_->getHistograms()); 45 | MeteredMap meter_map(metric_registry_->getMeters()); 46 | TimerMap timer_map(metric_registry_->getTimers()); 47 | GaugeMap gauge_map(metric_registry_->getGauges()); 48 | report(counter_map, histogram_map, meter_map, timer_map, gauge_map); 49 | } 50 | 51 | void ScheduledReporter::start(boost::chrono::milliseconds period) { 52 | if (!running_) { 53 | running_ = true; 54 | scheduled_executor_.scheduleAtFixedDelay( 55 | boost::bind(&ScheduledReporter::report, this), period); 56 | } 57 | } 58 | 59 | void ScheduledReporter::stop() { 60 | if (running_) { 61 | running_ = false; 62 | scheduled_executor_.shutdown(); 63 | } 64 | } 65 | 66 | std::string ScheduledReporter::rateUnitInSec() const { 67 | std::ostringstream ostrstr; 68 | ostrstr << rate_factor_; 69 | ostrstr << " Seconds"; 70 | return ostrstr.str(); 71 | } 72 | 73 | double ScheduledReporter::convertDurationUnit(double duration) const { 74 | return duration * duration_factor_; 75 | } 76 | 77 | double ScheduledReporter::convertRateUnit(double rate) const { 78 | return rate * rate_factor_; 79 | } 80 | 81 | } /* namespace core */ 82 | } /* namespace cppmetrics */ 83 | -------------------------------------------------------------------------------- /src/cppmetrics/core/scheduled_reporter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * scheduled_reporter.h 11 | * 12 | * Created on: Jun 10, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef SCHEDULED_REPORTER_H_ 17 | #define SCHEDULED_REPORTER_H_ 18 | 19 | #include "reporter.h" 20 | #include "cppmetrics/concurrent/simple_scheduled_thread_pool_executor.h" 21 | #include "cppmetrics/core/metric_registry.h" 22 | 23 | namespace cppmetrics { 24 | namespace core { 25 | 26 | /** 27 | * The abstract base class for all scheduled reporters (i.e., reporters which process a registry's 28 | * metrics periodically). 29 | */ 30 | class ScheduledReporter: public Reporter { 31 | public: 32 | virtual ~ScheduledReporter(); 33 | 34 | /** 35 | * Report the current values of all metrics in the registry. 36 | */ 37 | virtual void report(); 38 | 39 | /** 40 | * Called periodically by the polling thread. Subclasses should report all the given metrics. 41 | * @param gauge_map all of the gauges in the registry 42 | * @param counter_map all of the counters in the registry 43 | * @param histogram_map all of the histograms in the registry 44 | * @param meter_map all of the meters in the registry 45 | * @param timer_map all of the timers in the registry 46 | */ 47 | virtual void report(CounterMap counter_map, 48 | HistogramMap histogram_map, 49 | MeteredMap meter_map, 50 | TimerMap timer_map, 51 | GaugeMap gauge_map) = 0; 52 | 53 | /** 54 | * Starts a background thread which polls and published the metrics from the registry periodically at the given 55 | * interval. 56 | * @param period the amount of time between polls in milliseconds. 57 | */ 58 | virtual void start(boost::chrono::milliseconds period); 59 | 60 | /** 61 | * Shuts down the background thread that polls/publishes the metrics from the registry. 62 | */ 63 | virtual void stop(); 64 | 65 | protected: 66 | 67 | /** 68 | * Creates a new {@link ScheduledReporter} instance. 69 | * @param registry the {@link MetricRegistry} shared_ptr containing the metrics this 70 | * reporter will report 71 | * @param rate_unit a unit of time used for publishing the rate metrics like meter. 72 | */ 73 | ScheduledReporter(MetricRegistryPtr registry, 74 | boost::chrono::milliseconds rate_unit); 75 | 76 | /** 77 | * Converts the duration value to the milliseconds (from nanoseconds). 78 | * @param duration_value The duration value from a metric like timer. 79 | * @return The converted duration value in terms number of millis. 80 | */ 81 | double convertDurationUnit(double duration_value) const; 82 | 83 | /** 84 | * Converts the rate value based on the unit of duration. 85 | * @param rate_value The duration value from a metric like meter. 86 | * @return The converted rate value. 87 | */ 88 | double convertRateUnit(double rate_value) const; 89 | 90 | /** 91 | * 92 | * @returns the Rate unit in seconds in string format. 93 | */ 94 | std::string rateUnitInSec() const; 95 | 96 | private: 97 | bool running_; 98 | MetricRegistryPtr metric_registry_; 99 | concurrent::SimpleScheduledThreadPoolExecutor scheduled_executor_; 100 | double rate_factor_; 101 | double duration_factor_; 102 | }; 103 | 104 | } /* namespace core */ 105 | } /* namespace cppmetrics */ 106 | #endif /* SCHEDULED_REPORTER_H_ */ 107 | -------------------------------------------------------------------------------- /src/cppmetrics/core/snapshot.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * snapshot.cpp 11 | * 12 | * Created on: Jun 5, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "cppmetrics/core/snapshot.h" 22 | 23 | namespace cppmetrics { 24 | namespace core { 25 | 26 | static const double MEDIAN_Q = 0.5; 27 | static const double P75_Q = 0.75; 28 | static const double P95_Q = 0.95; 29 | static const double P98_Q = 0.98; 30 | static const double P99_Q = 0.99; 31 | static const double P999_Q = 0.999; 32 | 33 | Snapshot::Snapshot(const ValueVector& values) : 34 | values_(values) { 35 | std::sort(values_.begin(), values_.end()); 36 | } 37 | 38 | Snapshot::~Snapshot() { 39 | } 40 | 41 | std::size_t Snapshot::size() const { 42 | return values_.size(); 43 | } 44 | 45 | double Snapshot::getValue(double quantile) const { 46 | if (quantile < 0.0 || quantile > 1.0) { 47 | throw std::invalid_argument("quantile is not in [0..1]"); 48 | } 49 | 50 | if (values_.empty()) { 51 | return 0.0; 52 | } 53 | 54 | const double pos = quantile * (values_.size() + 1); 55 | 56 | if (pos < 1) { 57 | return values_.front(); 58 | } 59 | 60 | if (pos >= values_.size()) { 61 | return values_.back(); 62 | } 63 | 64 | const size_t pos_index = static_cast(pos); 65 | double lower = values_[pos_index - 1]; 66 | double upper = values_[pos_index]; 67 | return lower + (pos - std::floor(pos)) * (upper - lower); 68 | } 69 | 70 | double Snapshot::getMedian() const { 71 | return getValue(MEDIAN_Q); 72 | } 73 | 74 | double Snapshot::get75thPercentile() const { 75 | return getValue(P75_Q); 76 | } 77 | 78 | double Snapshot::get95thPercentile() const { 79 | return getValue(P95_Q); 80 | } 81 | 82 | double Snapshot::get98thPercentile() const { 83 | return getValue(P98_Q); 84 | } 85 | 86 | double Snapshot::get99thPercentile() const { 87 | return getValue(P99_Q); 88 | } 89 | 90 | double Snapshot::get999thPercentile() const { 91 | return getValue(P999_Q); 92 | } 93 | 94 | ValueVector::value_type Snapshot::getMin() const { 95 | return (values_.empty() ? 0.0 : values_.front()); 96 | } 97 | 98 | ValueVector::value_type Snapshot::getMax() const { 99 | return (values_.empty() ? 0.0 : values_.back()); 100 | } 101 | 102 | double Snapshot::getMean() const { 103 | if (values_.empty()) { 104 | return 0.0; 105 | } 106 | 107 | ValueVector::value_type mean(0); 108 | BOOST_FOREACH(ValueVector::value_type d, values_) { 109 | mean += d; 110 | } 111 | return static_cast(mean) / values_.size(); 112 | } 113 | 114 | double Snapshot::getStdDev() const { 115 | const size_t values_size(values_.size()); 116 | if (values_size <= 1) { 117 | return 0.0; 118 | } 119 | 120 | double mean_value = getMean(); 121 | double sum = 0; 122 | 123 | BOOST_FOREACH(ValueVector::value_type value, values_) { 124 | double diff = static_cast(value) - mean_value; 125 | sum += diff * diff; 126 | } 127 | 128 | double variance = sum / (values_size - 1); 129 | return std::sqrt(variance); 130 | } 131 | 132 | const ValueVector& Snapshot::getValues() const { 133 | return values_; 134 | } 135 | 136 | } /* namespace core */ 137 | } /* namespace cppmetrics */ 138 | -------------------------------------------------------------------------------- /src/cppmetrics/core/snapshot.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * snapshot.h 11 | * 12 | * Created on: Jun 5, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef SNAPSHOT_H_ 17 | #define SNAPSHOT_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | namespace cppmetrics { 25 | namespace core { 26 | 27 | typedef std::vector ValueVector; 28 | 29 | /** 30 | * A statistical snapshot of a {@link Sample}. 31 | */ 32 | class Snapshot { 33 | public: 34 | /** 35 | * Create a new {@link Snapshot} with the given values. 36 | * @param values an unordered set of values in the reservoir 37 | */ 38 | Snapshot(const ValueVector& values); 39 | ~Snapshot(); 40 | 41 | /** 42 | * Returns the number of values in the snapshot. 43 | * @return the number of values 44 | */ 45 | size_t size() const; 46 | 47 | /** 48 | * Returns the lowest value in the snapshot. 49 | * @return the lowest value 50 | */ 51 | ValueVector::value_type getMin() const; 52 | 53 | /** 54 | * Returns the highest value in the snapshot. 55 | * @return the highest value 56 | */ 57 | ValueVector::value_type getMax() const; 58 | 59 | /** 60 | * Returns the arithmetic mean of the values in the snapshot. 61 | * @return the arithmetic mean 62 | */ 63 | double getMean() const; 64 | 65 | /** 66 | * Returns the standard deviation of the values in the snapshot. 67 | * @return the standard deviation value 68 | */ 69 | double getStdDev() const; 70 | 71 | /** 72 | * Returns all the values in the snapshot. 73 | * @return All the values in the snapshot. 74 | */ 75 | const ValueVector& getValues() const; 76 | 77 | /** 78 | * Returns the value at the given quantile. 79 | * @param quantile a given quantile, in {@code [0..1]} 80 | * @return the value in the distribution at {@code quantile} 81 | */ 82 | double getValue(double quantile) const; 83 | 84 | /** 85 | * Returns the median value in the distribution. 86 | * @return the median value 87 | */ 88 | double getMedian() const; 89 | 90 | /** 91 | * Returns the value at the 75th percentile in the distribution. 92 | * @return the value at the 75th percentile 93 | */ 94 | double get75thPercentile() const; 95 | 96 | /** 97 | * Returns the value at the 95th percentile in the distribution. 98 | * @return the value at the 95th percentile 99 | */ 100 | double get95thPercentile() const; 101 | 102 | /** 103 | * Returns the value at the 98th percentile in the distribution. 104 | * @return the value at the 98th percentile 105 | */ 106 | double get98thPercentile() const; 107 | 108 | /** 109 | * Returns the value at the 99th percentile in the distribution. 110 | * @return the value at the 99th percentile 111 | */ 112 | double get99thPercentile() const; 113 | 114 | /** 115 | * Returns the value at the 999th percentile in the distribution. 116 | * @return the value at the 999th percentile 117 | */ 118 | double get999thPercentile() const; 119 | private: 120 | ValueVector values_; 121 | }; 122 | 123 | typedef boost::shared_ptr SnapshotPtr; 124 | 125 | } /* namespace core */ 126 | } /* namespace cppmetrics */ 127 | 128 | #endif /* SNAPSHOT_H_ */ 129 | -------------------------------------------------------------------------------- /src/cppmetrics/core/timer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * timer.cpp 11 | * 12 | * Created on: Jun 5, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include "cppmetrics/core/timer.h" 17 | 18 | namespace cppmetrics { 19 | namespace core { 20 | 21 | Timer::Timer() : 22 | histogram_(Sampling::kBiased) { 23 | } 24 | 25 | Timer::~Timer() { 26 | } 27 | 28 | boost::uint64_t Timer::getCount() const { 29 | return histogram_.getCount(); 30 | } 31 | 32 | double Timer::getFifteenMinuteRate() { 33 | return meter_.getFifteenMinuteRate(); 34 | } 35 | 36 | double Timer::getFiveMinuteRate() { 37 | return meter_.getFiveMinuteRate(); 38 | } 39 | 40 | double Timer::getOneMinuteRate() { 41 | return meter_.getOneMinuteRate(); 42 | } 43 | 44 | double Timer::getMeanRate() { 45 | return meter_.getMeanRate(); 46 | } 47 | 48 | void Timer::clear() { 49 | histogram_.clear(); 50 | } 51 | 52 | void Timer::update(boost::chrono::nanoseconds duration) { 53 | boost::int64_t count = duration.count(); 54 | if (count >= 0) { 55 | histogram_.update(count); 56 | meter_.mark(); 57 | } 58 | } 59 | 60 | SnapshotPtr Timer::getSnapshot() const { 61 | return histogram_.getSnapshot(); 62 | } 63 | 64 | void Timer::time(boost::function func) { 65 | TimerContext timer_context(*this); 66 | func(); 67 | } 68 | 69 | } /* namespace core */ 70 | } /* namespace cppmetrics */ 71 | -------------------------------------------------------------------------------- /src/cppmetrics/core/timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * timer.h 11 | * 12 | * Created on: Jun 5, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef TIMER_H_ 17 | #define TIMER_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "cppmetrics/core/metered.h" 27 | #include "cppmetrics/core/metric.h" 28 | #include "cppmetrics/core/sampling.h" 29 | #include "cppmetrics/core/timer_context.h" 30 | #include "cppmetrics/core/meter.h" 31 | #include "cppmetrics/core/histogram.h" 32 | 33 | namespace cppmetrics { 34 | namespace core { 35 | 36 | /** 37 | * A timer metric which aggregates timing durations and provides duration statistics, plus 38 | * throughput statistics via {@link Meter} and {@link Histogram}. 39 | */ 40 | class Timer: public Metered, Sampling { 41 | public: 42 | /** 43 | * Creates a new {@link Timer} using an {@link ExpDecaySample}. 44 | */ 45 | Timer(); 46 | virtual ~Timer(); 47 | 48 | /** 49 | * @returns the number of events that have been measured. 50 | */ 51 | virtual boost::uint64_t getCount() const; 52 | 53 | /** 54 | * @return the fifteen-minute exponentially-weighted moving average rate at which events have 55 | * occurred since the timer was created. 56 | */ 57 | virtual double getFifteenMinuteRate(); 58 | 59 | /** 60 | * @return the five-minute exponentially-weighted moving average rate at which events have 61 | * occurred since the timer was created. 62 | */ 63 | virtual double getFiveMinuteRate(); 64 | 65 | /** 66 | * @return the one-minute exponentially-weighted moving average rate at which events have 67 | * occurred since the timer was created. 68 | */ 69 | virtual double getOneMinuteRate(); 70 | 71 | /** 72 | * @return the average rate at which events have occurred since the meter was created. 73 | */ 74 | virtual double getMeanRate(); 75 | 76 | /** 77 | * @return the current snapshot based on the sample. 78 | */ 79 | virtual SnapshotPtr getSnapshot() const; 80 | 81 | /** 82 | * Clears the underlying metrics. 83 | */ 84 | void clear(); 85 | 86 | /** 87 | * Adds a recorded duration. 88 | * @param duration the length of the duration in nanos. 89 | */ 90 | void update(boost::chrono::nanoseconds duration); 91 | 92 | /** 93 | * Creates a new TimerContext instance that measures the duration and updates the 94 | * duration before the instance goes out of scope. 95 | * @return The TimerContext object. 96 | * @note The TimerContextPtr should not be shared. 97 | */ 98 | TimerContextPtr timerContextPtr() { 99 | return boost::shared_ptr(new TimerContext(*this)); 100 | } 101 | 102 | /** 103 | * Times the duration of a function that will be executed internally and updates the duration. 104 | * @param The fn to be timed. 105 | */ 106 | void time(boost::function fn); 107 | 108 | private: 109 | Meter meter_; /**< The underlying meter object */ 110 | Histogram histogram_; /**< The underlying histogram object */ 111 | }; 112 | 113 | typedef boost::shared_ptr TimerPtr; 114 | 115 | } /* namespace core */ 116 | } /* namespace cppmetrics */ 117 | #endif /* TIMER_H_ */ 118 | -------------------------------------------------------------------------------- /src/cppmetrics/core/timer_context.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * timer_context.cpp 11 | * 12 | * Created on: Jun 5, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include "cppmetrics/core/timer_context.h" 17 | #include "cppmetrics/core/timer.h" 18 | 19 | namespace cppmetrics { 20 | namespace core { 21 | 22 | TimerContext::TimerContext(Timer& timer) : 23 | timer_(timer) { 24 | reset(); 25 | } 26 | 27 | TimerContext::~TimerContext() { 28 | stop(); 29 | } 30 | 31 | void TimerContext::reset() { 32 | active_ = true; 33 | start_time_ = Clock::now(); 34 | } 35 | 36 | boost::chrono::nanoseconds TimerContext::stop() { 37 | if (active_) { 38 | boost::chrono::nanoseconds dur = Clock::now() - start_time_; 39 | timer_.update(dur); 40 | active_ = false; 41 | return dur; 42 | } 43 | return boost::chrono::nanoseconds(0); 44 | } 45 | 46 | } /* namespace core */ 47 | } /* namespace cppmetrics */ 48 | -------------------------------------------------------------------------------- /src/cppmetrics/core/timer_context.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * timer_context.h 11 | * 12 | * Created on: Jun 5, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef TIMER_CONTEXT_H_ 17 | #define TIMER_CONTEXT_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include "cppmetrics/core/types.h" 23 | 24 | namespace cppmetrics { 25 | namespace core { 26 | 27 | class Timer; 28 | 29 | /** 30 | * Class that actually measures the wallclock time. 31 | */ 32 | class TimerContext { 33 | public: 34 | 35 | /** 36 | * Creates a TimerContext. 37 | * @param timer The parent timer metric. 38 | */ 39 | TimerContext(Timer& timer); 40 | 41 | ~TimerContext(); 42 | 43 | /** 44 | * Resets the underlying clock. 45 | */ 46 | void reset(); 47 | 48 | /** 49 | * Stops recording the elapsed time and updates the timer. 50 | * @return the elapsed time in nanoseconds 51 | */ 52 | boost::chrono::nanoseconds stop(); 53 | private: 54 | 55 | TimerContext& operator=(const TimerContext&); 56 | 57 | Clock::time_point start_time_; ///< The start time on instantitation */ 58 | Timer& timer_; ///< The parent timer object. */ 59 | bool active_; ///< Whether the timer is active or not */ 60 | }; 61 | 62 | typedef boost::shared_ptr TimerContextPtr; 63 | 64 | } /* namespace cppmetrics */ 65 | } /* namespace core */ 66 | #endif /* TIMER_CONTEXT_H_ */ 67 | -------------------------------------------------------------------------------- /src/cppmetrics/core/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * types.h 11 | * 12 | * Created on: Jun 4, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef TYPES_H_ 17 | #define TYPES_H_ 18 | 19 | #include 20 | namespace cppmetrics { 21 | namespace core { 22 | typedef boost::chrono::high_resolution_clock Clock; 23 | } 24 | } 25 | 26 | #endif /* TYPES_H_ */ 27 | -------------------------------------------------------------------------------- /src/cppmetrics/core/uniform_sample.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * uniform_sample.cpp 11 | * 12 | * Created on: Jun 5, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include "cppmetrics/core/utils.h" 17 | #include "cppmetrics/core/uniform_sample.h" 18 | 19 | namespace cppmetrics { 20 | namespace core { 21 | 22 | const boost::uint64_t UniformSample::DEFAULT_SAMPLE_SIZE = 1028; 23 | UniformSample::UniformSample(boost::uint32_t reservoir_size) : 24 | reservoir_size_(reservoir_size), count_(0), values_(reservoir_size, 0) { 25 | rng_.seed(get_millis_from_epoch()); 26 | } 27 | 28 | UniformSample::~UniformSample() { 29 | } 30 | 31 | void UniformSample::clear() { 32 | for (size_t i = 0; i < reservoir_size_; ++i) { 33 | values_[i] = 0; 34 | } 35 | count_ = 0; 36 | } 37 | 38 | boost::uint64_t UniformSample::size() const { 39 | boost::uint64_t size = values_.size(); 40 | boost::uint64_t count = count_; 41 | return std::min(count, size); 42 | } 43 | 44 | boost::uint64_t UniformSample::getRandom(boost::uint64_t count) const { 45 | boost::random::uniform_int_distribution<> uniform(0, count - 1); 46 | return uniform(rng_); 47 | } 48 | 49 | void UniformSample::update(boost::int64_t value) { 50 | boost::uint64_t count = ++count_; 51 | boost::lock_guard lock(mutex_); 52 | size_t size = values_.size(); 53 | if (count <= size) { 54 | values_[count - 1] = value; 55 | } else { 56 | boost::uint64_t rand = getRandom(count); 57 | if (rand < size) { 58 | values_[rand] = value; 59 | } 60 | } 61 | } 62 | 63 | SnapshotPtr UniformSample::getSnapshot() const { 64 | boost::lock_guard lock(mutex_); 65 | Int64Vector::const_iterator begin_itr(values_.begin()); 66 | Int64Vector::const_iterator end_itr(values_.begin()); 67 | std::advance(end_itr, size()); 68 | return SnapshotPtr(new Snapshot(ValueVector(begin_itr, end_itr))); 69 | } 70 | 71 | } /* namespace core */ 72 | } /* namespace cppmetrics */ 73 | -------------------------------------------------------------------------------- /src/cppmetrics/core/uniform_sample.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * uniform_sample.h 11 | * 12 | * Created on: Jun 5, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef UNIFORM_SAMPLE_H_ 17 | #define UNIFORM_SAMPLE_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "cppmetrics/core/sample.h" 27 | 28 | namespace cppmetrics { 29 | namespace core { 30 | 31 | /** 32 | * A random sampling reservoir of a stream of {@code long}s. Uses Vitter's Algorithm R to produce a 33 | * statistically representative sample. 34 | */ 35 | class UniformSample: public Sample { 36 | public: 37 | 38 | /** 39 | * Creates a new {@link UniformReservoir}. 40 | * @param size the number of samples to keep in the sampling reservoir 41 | */ 42 | UniformSample(boost::uint32_t reservoirSize = DEFAULT_SAMPLE_SIZE); 43 | virtual ~UniformSample(); 44 | 45 | /** 46 | * Clears the values in the sample. 47 | */ 48 | virtual void clear(); 49 | 50 | /** 51 | * Returns the number of values recorded. 52 | * @return the number of values recorded 53 | */ 54 | virtual boost::uint64_t size() const; 55 | 56 | /** 57 | * Adds a new recorded value to the sample. 58 | * @param value a new recorded value 59 | */ 60 | virtual void update(boost::int64_t value); 61 | 62 | /** 63 | * Returns a snapshot of the sample's values. 64 | * @return a snapshot of the sample's values 65 | */ 66 | virtual SnapshotPtr getSnapshot() const; 67 | 68 | /**< The Maximum sample size at any given time. */ 69 | static const boost::uint64_t DEFAULT_SAMPLE_SIZE; 70 | private: 71 | boost::uint64_t getRandom(boost::uint64_t count) const; 72 | const boost::uint64_t reservoir_size_; 73 | boost::atomic count_; 74 | typedef std::vector Int64Vector; 75 | Int64Vector values_; 76 | mutable boost::mt11213b rng_; 77 | mutable boost::mutex mutex_; 78 | }; 79 | 80 | } /* namespace core */ 81 | } /* namespace cppmetrics */ 82 | #endif /* UNIFORM_SAMPLE_H_ */ 83 | -------------------------------------------------------------------------------- /src/cppmetrics/core/utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * utils.h 11 | * 12 | * Created on: Jun 12, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef UTILS_H_ 17 | #define UTILS_H_ 18 | 19 | #include 20 | #include 21 | #include "cppmetrics/core/types.h" 22 | 23 | namespace cppmetrics { 24 | namespace core { 25 | 26 | inline boost::posix_time::time_duration get_duration_from_epoch() { 27 | boost::posix_time::ptime time_t_epoch(boost::gregorian::date(1970, 1, 1)); 28 | boost::posix_time::ptime now = 29 | boost::posix_time::microsec_clock::local_time(); 30 | return (now - time_t_epoch); 31 | } 32 | 33 | inline boost::uint64_t get_millis_from_epoch() { 34 | return get_duration_from_epoch().total_milliseconds(); 35 | } 36 | 37 | inline boost::uint64_t get_seconds_from_epoch() { 38 | return get_duration_from_epoch().total_seconds(); 39 | } 40 | 41 | inline std::string utc_timestamp(const std::locale& current_locale) { 42 | std::ostringstream ss; 43 | // assumes std::cout's locale has been set appropriately for the entire app 44 | boost::posix_time::time_facet* t_facet(new boost::posix_time::time_facet()); 45 | t_facet->time_duration_format("%d-%M-%y %H:%M:%S%F %Q"); 46 | ss.imbue(std::locale(current_locale, t_facet)); 47 | ss << boost::posix_time::microsec_clock::universal_time(); 48 | return ss.str(); 49 | } 50 | 51 | } 52 | } 53 | 54 | #endif /* UTILS_H_ */ 55 | -------------------------------------------------------------------------------- /src/cppmetrics/cppmetrics.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * cppmetrics.h" 11 | * 12 | * Created on: Jun 30, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef CPPMETRICS_H_ 17 | #define CPPMETRICS_H_ 18 | 19 | // Global header that includes all the public headers. 20 | 21 | #include "cppmetrics/concurrent/simple_thread_pool_executor.h" 22 | #include "cppmetrics/concurrent/simple_scheduled_thread_pool_executor.h" 23 | #include "cppmetrics/core/counter.h" 24 | #include "cppmetrics/core/histogram.h" 25 | #include "cppmetrics/core/gauge.h" 26 | #include "cppmetrics/core/meter.h" 27 | #include "cppmetrics/core/metered.h" 28 | #include "cppmetrics/core/metric.h" 29 | #include "cppmetrics/core/metric_registry.h" 30 | #include "cppmetrics/core/reporter.h" 31 | #include "cppmetrics/core/scheduled_reporter.h" 32 | #include "cppmetrics/core/timer.h" 33 | #include "cppmetrics/core/exp_decay_sample.h" 34 | #include "cppmetrics/core/sample.h" 35 | #include "cppmetrics/core/snapshot.h" 36 | #include "cppmetrics/core/uniform_sample.h" 37 | #include "cppmetrics/core/sampling.h" 38 | #include "cppmetrics/core/types.h" 39 | #include "cppmetrics/graphite/graphite_sender.h" 40 | #include "cppmetrics/graphite/graphite_sender_tcp.h" 41 | #include "cppmetrics/graphite/graphite_reporter.h" 42 | #include "cppmetrics/core/console_reporter.h" 43 | 44 | #endif /* CPPMETRICS_H_ */ 45 | -------------------------------------------------------------------------------- /src/cppmetrics/graphite/graphite_reporter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * graphite_reporter.cpp 11 | * 12 | * Created on: Jun 12, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include "cppmetrics/core/utils.h" 20 | #include "cppmetrics/graphite/graphite_reporter.h" 21 | 22 | namespace cppmetrics { 23 | namespace graphite { 24 | 25 | GraphiteReporter::GraphiteReporter(core::MetricRegistryPtr registry, 26 | GraphiteSenderPtr sender, 27 | std::string prefix, 28 | boost::chrono::milliseconds rate_unit) : 29 | ScheduledReporter(registry, rate_unit), sender_(sender), prefix_(prefix) { 30 | 31 | } 32 | 33 | GraphiteReporter::~GraphiteReporter() { 34 | // TODO Auto-generated destructor stub 35 | } 36 | 37 | template 38 | std::string GraphiteReporter::format(T o) { 39 | return boost::lexical_cast(o); 40 | } 41 | 42 | void GraphiteReporter::report(core::CounterMap counter_map, 43 | core::HistogramMap histogram_map, 44 | core::MeteredMap meter_map, 45 | core::TimerMap timer_map, 46 | core::GaugeMap gauge_map) { 47 | 48 | boost::uint64_t timestamp = core::get_seconds_from_epoch(); 49 | 50 | try { 51 | sender_->connect(); 52 | 53 | BOOST_FOREACH(const core::CounterMap::value_type& kv, counter_map) { 54 | reportCounter(kv.first, kv.second, timestamp); 55 | } 56 | 57 | BOOST_FOREACH(const core::HistogramMap::value_type& kv, histogram_map) { 58 | reportHistogram(kv.first, kv.second, timestamp); 59 | } 60 | 61 | BOOST_FOREACH(const core::MeteredMap::value_type& kv, meter_map) { 62 | reportMeter(kv.first, kv.second, timestamp); 63 | } 64 | 65 | BOOST_FOREACH(const core::TimerMap::value_type& kv, timer_map) { 66 | reportTimer(kv.first, kv.second, timestamp); 67 | } 68 | 69 | BOOST_FOREACH(const core::GaugeMap::value_type& kv, gauge_map) { 70 | reportGauge(kv.first, kv.second, timestamp); 71 | } 72 | sender_->close(); 73 | } 74 | catch (const std::exception& e) { 75 | LOG(ERROR)<< "Exception in graphite reporting: " << e.what(); 76 | sender_->close(); 77 | } 78 | } 79 | 80 | void GraphiteReporter::reportTimer(const std::string& name, 81 | core::TimerPtr timer, 82 | boost::uint64_t timestamp) { 83 | core::SnapshotPtr snapshot = timer->getSnapshot(); 84 | 85 | sender_->send(prefix(name, "getMax"), 86 | format(convertDurationUnit(snapshot->getMax())), timestamp); 87 | sender_->send(prefix(name, "mean"), 88 | format(convertDurationUnit(snapshot->getMean())), timestamp); 89 | sender_->send(prefix(name, "min"), 90 | format(convertDurationUnit(snapshot->getMin())), timestamp); 91 | sender_->send(prefix(name, "stddev"), 92 | format(convertDurationUnit(snapshot->getStdDev())), timestamp); 93 | sender_->send(prefix(name, "p50"), 94 | format(convertDurationUnit(snapshot->getMedian())), timestamp); 95 | sender_->send(prefix(name, "p75"), 96 | format(convertDurationUnit(snapshot->get75thPercentile())), 97 | timestamp); 98 | sender_->send(prefix(name, "p95"), 99 | format(convertDurationUnit(snapshot->get95thPercentile())), 100 | timestamp); 101 | sender_->send(prefix(name, "p98"), 102 | format(convertDurationUnit(snapshot->get98thPercentile())), 103 | timestamp); 104 | sender_->send(prefix(name, "p99"), 105 | format(convertDurationUnit(snapshot->get99thPercentile())), 106 | timestamp); 107 | sender_->send(prefix(name, "p999"), 108 | format(convertDurationUnit(snapshot->get999thPercentile())), 109 | timestamp); 110 | 111 | reportMeter(name, boost::static_pointer_cast(timer), 112 | timestamp); 113 | } 114 | 115 | void GraphiteReporter::reportMeter(const std::string& name, 116 | core::MeteredPtr meter, 117 | boost::uint64_t timestamp) { 118 | 119 | sender_->send(prefix(name, "count"), format(meter->getCount()), timestamp); 120 | sender_->send(prefix(name, "m1_rate"), 121 | format(convertRateUnit(meter->getOneMinuteRate())), timestamp); 122 | sender_->send(prefix(name, "m5_rate"), 123 | format(convertRateUnit(meter->getFiveMinuteRate())), timestamp); 124 | sender_->send(prefix(name, "m15_rate"), 125 | format(convertRateUnit(meter->getFifteenMinuteRate())), timestamp); 126 | sender_->send(prefix(name, "mean_rate"), 127 | format(convertRateUnit(meter->getMeanRate())), timestamp); 128 | } 129 | 130 | void GraphiteReporter::reportHistogram(const std::string& name, 131 | core::HistogramPtr histogram, 132 | boost::uint64_t timestamp) { 133 | core::SnapshotPtr snapshot = histogram->getSnapshot(); 134 | 135 | sender_->send(prefix(name, "count"), format(histogram->getCount()), 136 | timestamp); 137 | sender_->send(prefix(name, "getMax"), format(snapshot->getMax()), 138 | timestamp); 139 | sender_->send(prefix(name, "mean"), format(snapshot->getMean()), timestamp); 140 | sender_->send(prefix(name, "min"), format(snapshot->getMin()), timestamp); 141 | sender_->send(prefix(name, "stddev"), format(snapshot->getStdDev()), 142 | timestamp); 143 | sender_->send(prefix(name, "p50"), format(snapshot->getMedian()), 144 | timestamp); 145 | sender_->send(prefix(name, "p75"), format(snapshot->get75thPercentile()), 146 | timestamp); 147 | sender_->send(prefix(name, "p95"), format(snapshot->get95thPercentile()), 148 | timestamp); 149 | sender_->send(prefix(name, "p98"), format(snapshot->get98thPercentile()), 150 | timestamp); 151 | sender_->send(prefix(name, "p99"), format(snapshot->get99thPercentile()), 152 | timestamp); 153 | sender_->send(prefix(name, "p999"), format(snapshot->get999thPercentile()), 154 | timestamp); 155 | } 156 | 157 | void GraphiteReporter::reportCounter(const std::string& name, 158 | core::CounterPtr counter, 159 | boost::uint64_t timestamp) { 160 | sender_->send(prefix(name, "count"), format(counter->getCount()), 161 | timestamp); 162 | } 163 | 164 | void GraphiteReporter::reportGauge(const std::string& name, 165 | core::GaugePtr gauge, 166 | boost::uint64_t timestamp) { 167 | const std::string value = format(gauge->getValue()); 168 | sender_->send(prefix(name), value, timestamp); 169 | } 170 | 171 | std::string GraphiteReporter::prefix(const std::string& name, 172 | const char* extra) { 173 | std::string result(prefix_ + '.' + name); 174 | return extra ? (result + '.' + extra) : result; 175 | } 176 | 177 | } /* namespace graphite */ 178 | } /* namespace cppmetrics */ 179 | -------------------------------------------------------------------------------- /src/cppmetrics/graphite/graphite_reporter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * graphite_reporter.h 11 | * 12 | * Created on: Jun 12, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef GRAPHITE_REPORTER_H_ 17 | #define GRAPHITE_REPORTER_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include "cppmetrics/core/scheduled_reporter.h" 23 | #include "cppmetrics/graphite/graphite_sender.h" 24 | 25 | namespace cppmetrics { 26 | namespace graphite { 27 | 28 | /** 29 | * A reporter which publishes metric values to a Graphite server. 30 | * @see Graphite - Scalable Realtime Graphing 31 | */ 32 | class GraphiteReporter: public core::ScheduledReporter, boost::noncopyable { 33 | public: 34 | /** 35 | * Creates a {@link GraphiteReporter} instance. Uses the given registry, metricname prefix. 36 | * @param registry The metric registry. 37 | * @param graphite_sender The graphite server sender. 38 | * @param prefix The prefix thats added to all the metric names in the registry before posting to graphite. 39 | * @param rateUnit The conversion unit user for the rate metrics. 40 | * @param durationUnit The conversion unit used for the duration metrics. 41 | */ 42 | GraphiteReporter(core::MetricRegistryPtr registry, 43 | GraphiteSenderPtr graphite_sender, 44 | std::string prefix, 45 | boost::chrono::milliseconds rateUnit = boost::chrono::seconds(1)); 46 | virtual ~GraphiteReporter(); 47 | 48 | /** 49 | * Reports all the metrics from the registry periodically to the graphite server. 50 | * @param gauge_map all of the gauges in the registry 51 | * @param counter_map all of the counters in the registry 52 | * @param histogram_map all of the histograms in the registry 53 | * @param meter_map all of the meters in the registry 54 | * @param timer_map all of the timers in the registry 55 | */ 56 | virtual void report(core::CounterMap counter_map, 57 | core::HistogramMap histogram_map, 58 | core::MeteredMap meter_map, 59 | core::TimerMap timer_map, 60 | core::GaugeMap gauge_map); 61 | private: 62 | 63 | std::string prefix(const std::string& name, const char* extra = NULL); 64 | 65 | template std::string format(T o); 66 | 67 | void reportTimer(const std::string& name, 68 | core::TimerPtr timer, 69 | boost::uint64_t timestamp); 70 | 71 | void reportMeter(const std::string& name, 72 | core::MeteredPtr meter, 73 | boost::uint64_t timestamp); 74 | 75 | void reportHistogram(const std::string& name, 76 | core::HistogramPtr histogram, 77 | boost::uint64_t timestamp); 78 | 79 | void reportCounter(const std::string& name, 80 | core::CounterPtr counter, 81 | boost::uint64_t timestamp); 82 | 83 | void reportGauge(const std::string& name, 84 | core::GaugePtr gauge, 85 | boost::uint64_t timestamp); 86 | 87 | core::MetricRegistryPtr registry_; 88 | GraphiteSenderPtr sender_; 89 | std::string prefix_; 90 | boost::chrono::milliseconds rate_unit_; 91 | boost::chrono::milliseconds duration_unit_; 92 | }; 93 | 94 | } /* namespace graphite */ 95 | } /* namespace cppmetrics */ 96 | #endif /* GRAPHITE_REPORTER_H_ */ 97 | -------------------------------------------------------------------------------- /src/cppmetrics/graphite/graphite_sender.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * graphite_sender.h 11 | * 12 | * Created on: Jun 11, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef GRAPHITE_SENDER_H_ 17 | #define GRAPHITE_SENDER_H_ 18 | 19 | #include 20 | 21 | namespace cppmetrics { 22 | namespace graphite { 23 | 24 | /** 25 | * Interface to all graphite senders using different protocols like TCP UDP and AMQP etc. 26 | */ 27 | class GraphiteSender { 28 | public: 29 | virtual ~GraphiteSender() { 30 | } 31 | 32 | /** 33 | * Connects to the graphite sender 34 | * @return True on success, false otherwise. 35 | * @throws boost::system_error if there is a problem. 36 | */ 37 | virtual void connect() = 0; 38 | 39 | /** 40 | * Posts the metric name, value and timestamp to the graphite server. 41 | * @param name The name of the metric 42 | * @param value The value of the metric 43 | * @param timestamp The timestamp of the metric. 44 | * @return True on success false otherwise. 45 | * @throws boost::system_error if there is a problem. 46 | */ 47 | virtual void send(const std::string& name, 48 | const std::string& value, 49 | boost::uint64_t timestamp) = 0; 50 | 51 | /** 52 | * Closes the connection. 53 | */ 54 | virtual void close() = 0; 55 | }; 56 | 57 | typedef boost::shared_ptr GraphiteSenderPtr; 58 | 59 | } /* namespace graphite */ 60 | } /* namespace cppmetrics */ 61 | #endif /* GRAPHITE_SENDER_H_ */ 62 | -------------------------------------------------------------------------------- /src/cppmetrics/graphite/graphite_sender_tcp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * graphite_sender_tcp.cpp 11 | * 12 | * Created on: Jun 16, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include 18 | #include "cppmetrics/graphite/graphite_sender_tcp.h" 19 | 20 | namespace cppmetrics { 21 | namespace graphite { 22 | 23 | GraphiteSenderTCP::GraphiteSenderTCP(const std::string& host, 24 | boost::uint32_t port) : 25 | connected_(false), 26 | host_(host), 27 | port_(boost::lexical_cast(port)) { 28 | } 29 | 30 | GraphiteSenderTCP::~GraphiteSenderTCP() { 31 | } 32 | 33 | void GraphiteSenderTCP::connect() { 34 | io_service_.reset(new boost::asio::io_service()); 35 | 36 | boost::asio::ip::tcp::resolver resolver(*io_service_); 37 | boost::asio::ip::tcp::resolver::query query(host_, port_); 38 | boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); 39 | 40 | socket_.reset(new boost::asio::ip::tcp::socket(*io_service_)); 41 | boost::system::error_code ec; 42 | boost::asio::connect(*socket_, iterator, ec); 43 | connected_ = !ec; 44 | if (!connected_) { 45 | throw std::runtime_error("Connect() error, reason: " + ec.message()); 46 | } 47 | } 48 | 49 | void GraphiteSenderTCP::send(const std::string& name, 50 | const std::string& value, 51 | boost::uint64_t timestamp) { 52 | if (!connected_) { 53 | throw std::runtime_error("Graphite server connection not established."); 54 | } 55 | std::ostringstream ostr; 56 | ostr << name << ' ' << value << ' ' << timestamp << std::endl; 57 | std::string graphite_str(ostr.str()); 58 | boost::asio::write(*socket_, 59 | boost::asio::buffer(graphite_str, graphite_str.size())); 60 | } 61 | 62 | void GraphiteSenderTCP::close() { 63 | connected_ = false; 64 | socket_.reset(); 65 | io_service_.reset(); 66 | } 67 | 68 | } /* namespace graphite */ 69 | } /* namespace cppmetrics */ 70 | -------------------------------------------------------------------------------- /src/cppmetrics/graphite/graphite_sender_tcp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * graphite_sender_tcp.h 11 | * 12 | * Created on: Jun 16, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #ifndef GRAPHITE_SENDER_TCP_H_ 17 | #define GRAPHITE_SENDER_TCP_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include "cppmetrics/graphite/graphite_sender.h" 23 | 24 | namespace cppmetrics { 25 | namespace graphite { 26 | 27 | /** 28 | * Graphite TCP sender. 29 | */ 30 | class GraphiteSenderTCP: public GraphiteSender { 31 | public: 32 | 33 | /** 34 | * Creates a new sender with the given params. 35 | * @param host The graphite server host. 36 | * @param port The graphite server port. 37 | */ 38 | GraphiteSenderTCP(const std::string& host, boost::uint32_t port); 39 | virtual ~GraphiteSenderTCP(); 40 | 41 | /** 42 | * Connects to the graphite sender over TCP. 43 | * @return True on success, false otherwise. 44 | * @throws std::runtime_error if there is a problem. 45 | */ 46 | virtual void connect(); 47 | 48 | /** 49 | * Posts the metric name, value and timestamp to the graphite server. 50 | * @param name The name of the metric 51 | * @param value The value of the metric 52 | * @param timestamp The timestamp of the metric. 53 | * @return True on success false otherwise. 54 | * @throws std::runtime_error if there is a problem. 55 | */ 56 | virtual void send(const std::string& name, 57 | const std::string& value, 58 | boost::uint64_t timestamp); 59 | 60 | /** 61 | * Closes the TCP connection. 62 | */ 63 | virtual void close(); 64 | 65 | private: 66 | bool connected_; 67 | std::string host_; 68 | std::string port_; 69 | 70 | boost::scoped_ptr io_service_; 71 | boost::scoped_ptr socket_; 72 | }; 73 | 74 | } /* namespace graphite */ 75 | } /* namespace cppmetrics */ 76 | #endif /* GRAPHITE_SENDER_TCP_H_ */ 77 | -------------------------------------------------------------------------------- /test/cppmetrics/concurrent/test_simple_scheduled_thread_pool_executor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * test_simple_scheduled_thread_pool_executor.cpp 11 | * 12 | * Created on: Jun 11, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include "cppmetrics/concurrent/simple_scheduled_thread_pool_executor.h" 18 | 19 | namespace cppmetrics { 20 | namespace concurrent { 21 | 22 | namespace { 23 | 24 | void timer_handler(boost::atomic& counter) { 25 | ++counter; 26 | boost::this_thread::sleep(boost::posix_time::milliseconds(100)); 27 | } 28 | } 29 | 30 | TEST(simplescheduledthreadpoolexecutor, fixedDelayTest) { 31 | SimpleScheduledThreadPoolExecutor sstpe(3); 32 | 33 | ASSERT_FALSE(sstpe.isShutdown()); 34 | 35 | boost::atomic counter; 36 | counter = 0UL; 37 | boost::function timer_task( 38 | boost::bind(timer_handler, boost::ref(counter))); 39 | sstpe.scheduleAtFixedDelay(timer_task, boost::chrono::milliseconds(100)); 40 | boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); 41 | // As there is a sleep of 100ms in the timertask, it gets invoked only at every 200ms. 42 | ASSERT_LE((size_t )4, counter); 43 | ASSERT_GE((size_t )6, counter); 44 | 45 | ASSERT_FALSE(sstpe.isShutdown()); 46 | sstpe.shutdown(); 47 | ASSERT_TRUE(sstpe.isShutdown()); 48 | } 49 | 50 | TEST(simplescheduledthreadpoolexecutor, fixedRateTest) { 51 | SimpleScheduledThreadPoolExecutor sstpe(3); 52 | 53 | ASSERT_FALSE(sstpe.isShutdown()); 54 | 55 | boost::atomic counter; 56 | counter = 0UL; 57 | boost::function timer_task( 58 | boost::bind(timer_handler, boost::ref(counter))); 59 | sstpe.scheduleAtFixedRate(timer_task, boost::chrono::milliseconds(100)); 60 | boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); 61 | ASSERT_LE((size_t )9, counter); 62 | ASSERT_GE((size_t )10, counter); 63 | 64 | ASSERT_FALSE(sstpe.isShutdown()); 65 | sstpe.shutdown(); 66 | ASSERT_TRUE(sstpe.isShutdown()); 67 | } 68 | 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /test/cppmetrics/concurrent/test_simple_thread_pool_executor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * test_simple_thread_pool_executor.cpp 11 | * 12 | * Created on: Jun 26, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include "cppmetrics/concurrent/simple_thread_pool_executor.h" 18 | 19 | namespace cppmetrics { 20 | namespace concurrent { 21 | 22 | namespace { 23 | void increment_counter(size_t& counter) { 24 | ++counter; 25 | } 26 | } 27 | 28 | TEST(simplethreadpoolexecutor, functionaltest) { 29 | SimpleThreadPoolExecutor thread_pool_executor(2); 30 | 31 | ASSERT_FALSE(thread_pool_executor.isShutdown()); 32 | size_t counter = 0; 33 | boost::function task( 34 | boost::bind(increment_counter, boost::ref(counter))); 35 | thread_pool_executor.execute(task); 36 | // Give up a timeslice. 37 | boost::this_thread::sleep(boost::posix_time::milliseconds(20)); 38 | ASSERT_EQ((size_t )1, counter); 39 | ASSERT_FALSE(thread_pool_executor.isShutdown()); 40 | thread_pool_executor.shutdownNow(); 41 | ASSERT_TRUE(thread_pool_executor.isShutdown()); 42 | } 43 | 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /test/cppmetrics/core/test_console_reporter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * test_console_reporter.cpp 11 | * 12 | * Created on: Jul 2, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "cppmetrics/core/console_reporter.h" 22 | 23 | namespace cppmetrics { 24 | namespace core { 25 | 26 | namespace { 27 | 28 | class TestGauge: public Gauge { 29 | public: 30 | virtual boost::int64_t getValue() { 31 | return 100; 32 | } 33 | }; 34 | 35 | } 36 | 37 | TEST(consolereporter, gaugetest) { 38 | 39 | MetricRegistryPtr metric_registry(new MetricRegistry()); 40 | metric_registry->addGauge("new.gauge", GaugePtr(new TestGauge())); 41 | ConsoleReporter console_reporter(metric_registry, std::cout); 42 | console_reporter.start(boost::chrono::milliseconds(1000)); 43 | boost::this_thread::sleep(boost::posix_time::milliseconds(10 * 1000)); 44 | } 45 | 46 | TEST(consolereporter, timerContextTest) { 47 | 48 | MetricRegistryPtr metric_registry(new MetricRegistry()); 49 | boost::mt11213b rng; 50 | ConsoleReporter console_reporter(metric_registry, std::cout); 51 | console_reporter.start(boost::chrono::milliseconds(1000)); 52 | for (size_t i = 0; i < 100; ++i) { 53 | boost::random::uniform_int_distribution<> uniform(10, 30); 54 | size_t sleep_time = uniform(rng); 55 | TimerContextPtr time_context( 56 | metric_registry->timer("test.timer")->timerContextPtr()); 57 | boost::this_thread::sleep(boost::posix_time::milliseconds(sleep_time)); 58 | } 59 | boost::this_thread::sleep(boost::posix_time::milliseconds(10 * 1000)); 60 | } 61 | 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /test/cppmetrics/core/test_counter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * test_counter.cpp 11 | * 12 | * Created on: Jun 24, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include "cppmetrics/core/counter.h" 18 | 19 | namespace cppmetrics { 20 | namespace core { 21 | 22 | TEST(counter, functionaltest) { 23 | 24 | Counter counter; 25 | ASSERT_EQ(0, counter.getCount()); 26 | 27 | counter.increment(); 28 | ASSERT_EQ(1, counter.getCount()); 29 | 30 | counter.increment(5); 31 | ASSERT_EQ(6, counter.getCount()); 32 | 33 | counter.increment(3); 34 | ASSERT_EQ(9, counter.getCount()); 35 | 36 | counter.decrement(4); 37 | ASSERT_EQ(5, counter.getCount()); 38 | 39 | counter.decrement(); 40 | ASSERT_EQ(4, counter.getCount()); 41 | 42 | counter.setCount(3); 43 | ASSERT_EQ(3, counter.getCount()); 44 | 45 | counter.clear(); 46 | ASSERT_EQ(0, counter.getCount()); 47 | 48 | counter.decrement(12); 49 | ASSERT_EQ(-12, counter.getCount()); 50 | } 51 | 52 | } 53 | } 54 | 55 | -------------------------------------------------------------------------------- /test/cppmetrics/core/test_ewma.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * test_ewma.cpp 11 | * 12 | * Created on: Jun 24, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include "cppmetrics/core/ewma.h" 18 | 19 | namespace cppmetrics { 20 | namespace core { 21 | namespace internal { 22 | 23 | namespace { 24 | void elapse_minute(EWMA& ewma) { 25 | for (int i = 0; i < 12; i++) { 26 | ewma.tick(); 27 | } 28 | } 29 | } 30 | 31 | TEST(ewma, oneMinuteTestWithValueOf3) { 32 | 33 | EWMA ewma = EWMA::oneMinuteEWMA(); 34 | ewma.update(3); 35 | ewma.tick(); 36 | ASSERT_NEAR(0.6, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 37 | elapse_minute(ewma); 38 | ASSERT_NEAR(0.22072766, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 39 | 40 | elapse_minute(ewma); 41 | ASSERT_NEAR(0.08120117, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 42 | 43 | elapse_minute(ewma); 44 | ASSERT_NEAR(0.02987224, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 45 | 46 | elapse_minute(ewma); 47 | ASSERT_NEAR(0.01098938, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 48 | 49 | elapse_minute(ewma); 50 | ASSERT_NEAR(0.00404277, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 51 | 52 | elapse_minute(ewma); 53 | ASSERT_NEAR(0.00148725, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 54 | 55 | elapse_minute(ewma); 56 | ASSERT_NEAR(0.00054713, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 57 | 58 | elapse_minute(ewma); 59 | ASSERT_NEAR(0.00020128, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 60 | 61 | elapse_minute(ewma); 62 | ASSERT_NEAR(0.00007405, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 63 | 64 | elapse_minute(ewma); 65 | ASSERT_NEAR(0.00002724, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 66 | 67 | elapse_minute(ewma); 68 | ASSERT_NEAR(0.00001002, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 69 | 70 | elapse_minute(ewma); 71 | ASSERT_NEAR(0.00000369, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 72 | 73 | elapse_minute(ewma); 74 | ASSERT_NEAR(0.00000136, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 75 | 76 | elapse_minute(ewma); 77 | ASSERT_NEAR(0.00000050, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 78 | 79 | elapse_minute(ewma); 80 | ASSERT_NEAR(0.00000018, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 81 | } 82 | 83 | TEST(ewma, FiveMinuteTestWithValueOf3) { 84 | EWMA ewma = EWMA::fiveMinuteEWMA(); 85 | ewma.update(3); 86 | ewma.tick(); 87 | 88 | ASSERT_NEAR(0.6, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 89 | 90 | elapse_minute(ewma); 91 | ASSERT_NEAR(0.49123845, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 92 | 93 | elapse_minute(ewma); 94 | ASSERT_NEAR(0.40219203, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 95 | 96 | elapse_minute(ewma); 97 | ASSERT_NEAR(0.32928698, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 98 | 99 | elapse_minute(ewma); 100 | ASSERT_NEAR(0.26959738, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 101 | 102 | elapse_minute(ewma); 103 | ASSERT_NEAR(0.22072766, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 104 | 105 | elapse_minute(ewma); 106 | ASSERT_NEAR(0.18071653, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 107 | 108 | elapse_minute(ewma); 109 | ASSERT_NEAR(0.14795818, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 110 | 111 | elapse_minute(ewma); 112 | ASSERT_NEAR(0.12113791, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 113 | 114 | elapse_minute(ewma); 115 | ASSERT_NEAR(0.09917933, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 116 | 117 | elapse_minute(ewma); 118 | ASSERT_NEAR(0.08120117, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 119 | 120 | elapse_minute(ewma); 121 | ASSERT_NEAR(0.06648190, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 122 | 123 | elapse_minute(ewma); 124 | ASSERT_NEAR(0.05443077, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 125 | 126 | elapse_minute(ewma); 127 | ASSERT_NEAR(0.04456415, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 128 | 129 | elapse_minute(ewma); 130 | ASSERT_NEAR(0.03648604, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 131 | 132 | elapse_minute(ewma); 133 | ASSERT_NEAR(0.02987224, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 134 | } 135 | 136 | TEST(ewma, FifteenMinuteTestWithValueOf3) { 137 | EWMA ewma = EWMA::fifteenMinuteEWMA(); 138 | ewma.update(3); 139 | ewma.tick(); 140 | 141 | ASSERT_NEAR(0.6, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 142 | 143 | elapse_minute(ewma); 144 | ASSERT_NEAR(0.56130419, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 145 | 146 | elapse_minute(ewma); 147 | ASSERT_NEAR(0.52510399, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 148 | 149 | elapse_minute(ewma); 150 | ASSERT_NEAR(0.49123845, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 151 | 152 | elapse_minute(ewma); 153 | ASSERT_NEAR(0.45955700, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 154 | 155 | elapse_minute(ewma); 156 | ASSERT_NEAR(0.42991879, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 157 | 158 | elapse_minute(ewma); 159 | ASSERT_NEAR(0.40219203, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 160 | 161 | elapse_minute(ewma); 162 | ASSERT_NEAR(0.37625345, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 163 | 164 | elapse_minute(ewma); 165 | ASSERT_NEAR(0.35198773, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 166 | 167 | elapse_minute(ewma); 168 | ASSERT_NEAR(0.32928698, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 169 | 170 | elapse_minute(ewma); 171 | ASSERT_NEAR(0.30805027, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 172 | 173 | elapse_minute(ewma); 174 | ASSERT_NEAR(0.28818318, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 175 | 176 | elapse_minute(ewma); 177 | ASSERT_NEAR(0.26959738, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 178 | 179 | elapse_minute(ewma); 180 | ASSERT_NEAR(0.25221023, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 181 | 182 | elapse_minute(ewma); 183 | ASSERT_NEAR(0.23594443, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 184 | 185 | elapse_minute(ewma); 186 | ASSERT_NEAR(0.22072766, ewma.getRate(boost::chrono::seconds(1)), 0.000001); 187 | } 188 | 189 | } 190 | } 191 | } 192 | 193 | -------------------------------------------------------------------------------- /test/cppmetrics/core/test_exp_decay_sample.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * test_exp_decay_sample.cpp 11 | * 12 | * Created on: Jun 24, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include 18 | #include "cppmetrics/core/exp_decay_sample.h" 19 | 20 | namespace cppmetrics { 21 | namespace core { 22 | 23 | namespace { 24 | void assert_all_values_between(SnapshotPtr snapshot, double min, double max) { 25 | BOOST_FOREACH (double value, snapshot->getValues()) { 26 | ASSERT_GT(max, value); 27 | ASSERT_LE(min, value); 28 | } 29 | } 30 | } 31 | 32 | TEST(expdecaysample, sampleSizeOf100OutOf1000ElementsTest) { 33 | ExpDecaySample exp_decay_sample(100, 0.99); 34 | for (int i = 0; i < 1000; i++) { 35 | exp_decay_sample.update(i); 36 | } 37 | 38 | ASSERT_EQ((size_t)100, exp_decay_sample.size()); 39 | SnapshotPtr snapshot = exp_decay_sample.getSnapshot(); 40 | 41 | ASSERT_EQ((size_t)100, snapshot->size()); 42 | assert_all_values_between(snapshot, 0, 1000); 43 | } 44 | 45 | TEST(expdecaysample, aHeavilyBiasedSampleOf100OutOf1000Elements) { 46 | ExpDecaySample exp_decay_sample(1000, 0.01); 47 | for (int i = 0; i < 100; i++) { 48 | exp_decay_sample.update(i); 49 | } 50 | 51 | ASSERT_EQ((size_t)100, exp_decay_sample.size()); 52 | SnapshotPtr snapshot = exp_decay_sample.getSnapshot(); 53 | 54 | ASSERT_EQ((size_t)100, snapshot->size()); 55 | assert_all_values_between(snapshot, 0, 100); 56 | } 57 | 58 | TEST(expdecaySample, longPeriodsOfInactivityShouldNotCorruptSamplingState) { 59 | ExpDecaySample exp_decay_sample(10, 0.015); 60 | Clock::time_point cur_time_point(Clock::now()); 61 | for (int i = 0; i < 1000; i++) { 62 | exp_decay_sample.update(1000 + i, cur_time_point); 63 | cur_time_point += boost::chrono::milliseconds(100); 64 | } 65 | 66 | ASSERT_EQ((size_t)10, exp_decay_sample.size()); 67 | SnapshotPtr snapshot = exp_decay_sample.getSnapshot(); 68 | assert_all_values_between(snapshot, 1000, 2000); 69 | 70 | // wait for 15 hours and add another value. 71 | // this should trigger a rescale. Note that the number of samples will be reduced to 2 72 | // because of the very small scaling factor that will make all existing priorities equal to 73 | // zero after rescale. 74 | cur_time_point += boost::chrono::hours(15); 75 | exp_decay_sample.update(2000, cur_time_point); 76 | snapshot = exp_decay_sample.getSnapshot(); 77 | 78 | ASSERT_EQ((size_t)2, snapshot->size()); 79 | assert_all_values_between(snapshot, 1000, 3000); 80 | 81 | // add 1000 values at a rate of 10 values/second 82 | for (int i = 0; i < 1000; i++) { 83 | exp_decay_sample.update(3000 + i, cur_time_point); 84 | cur_time_point += boost::chrono::milliseconds(100); 85 | } 86 | snapshot = exp_decay_sample.getSnapshot(); 87 | ASSERT_EQ((size_t)10, snapshot->size()); 88 | assert_all_values_between(snapshot, 3000, 4000); 89 | } 90 | 91 | } 92 | } 93 | 94 | -------------------------------------------------------------------------------- /test/cppmetrics/core/test_histogram.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * test_histogram.cpp 11 | * 12 | * Created on: Jun 24, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include "cppmetrics/core/histogram.h" 18 | 19 | namespace cppmetrics { 20 | namespace core { 21 | 22 | TEST(histogram, updatesTheCountOnUpdatesTest) { 23 | Histogram histogram; 24 | ASSERT_EQ((size_t )0, histogram.getCount()); 25 | ASSERT_EQ((size_t )0, histogram.getSnapshot()->size()); 26 | 27 | histogram.update(1); 28 | ASSERT_EQ((size_t )1, histogram.getCount()); 29 | ASSERT_EQ((size_t )1, histogram.getSnapshot()->size()); 30 | 31 | const size_t update_count = 4096; 32 | for (size_t i = 0; i < update_count; ++i) { 33 | histogram.update(i); 34 | } 35 | 36 | const size_t max_sample_size = 1024; 37 | ASSERT_EQ(update_count + 1, histogram.getCount()); 38 | ASSERT_EQ(max_sample_size, histogram.getSnapshot()->size()); 39 | } 40 | 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /test/cppmetrics/core/test_meter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * test_meter.cpp 11 | * 12 | * Created on: Jun 24, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | 17 | #include 18 | #include "cppmetrics/core/meter.h" 19 | 20 | namespace cppmetrics { 21 | namespace core { 22 | 23 | TEST(meter, functionaltest) { 24 | 25 | Meter meter; 26 | 27 | ASSERT_EQ((size_t)0, meter.getCount()); 28 | ASSERT_NEAR(0.0, meter.getMeanRate(), 0.001); 29 | ASSERT_NEAR(0.0, meter.getOneMinuteRate(), 0.001); 30 | ASSERT_NEAR(0.0, meter.getFiveMinuteRate(), 0.001); 31 | ASSERT_NEAR(0.0, meter.getFifteenMinuteRate(), 0.001); 32 | /* 33 | // TODO: Have to use gmock here. 34 | meter.mark(); 35 | meter.mark(2); 36 | 37 | ASSERT_NEAR(0.3, meter.getMeanRate(), 0.001); 38 | ASSERT_NEAR(0.1840, meter.getOneMinuteRate(), 0.001); 39 | ASSERT_NEAR(0.1966, meter.getFiveMinuteRate(), 0.001); 40 | ASSERT_NEAR(0.1988, meter.getFifteenMinuteRate(), 0.001); 41 | */ 42 | } 43 | 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /test/cppmetrics/core/test_metric_registry.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * test_metric_registry.cpp 11 | * 12 | * Created on: Jun 25, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include "cppmetrics/core/metric_registry.h" 18 | 19 | namespace cppmetrics { 20 | namespace core { 21 | 22 | namespace { 23 | 24 | class FakeGauge: public Gauge { 25 | public: 26 | virtual ~FakeGauge() { 27 | } 28 | ; 29 | virtual boost::int64_t getValue() { 30 | return 10; 31 | } 32 | }; 33 | 34 | } 35 | 36 | TEST(metricregistry, initialTest) { 37 | MetricRegistry metric_registry; 38 | ASSERT_EQ((size_t )0, metric_registry.count()); 39 | ASSERT_EQ((size_t )0, metric_registry.getCounters().size()); 40 | ASSERT_EQ((size_t )0, metric_registry.getGauges().size()); 41 | ASSERT_EQ((size_t )0, metric_registry.getHistograms().size()); 42 | ASSERT_EQ((size_t )0, metric_registry.getMeters().size()); 43 | ASSERT_EQ((size_t )0, metric_registry.getTimers().size()); 44 | 45 | ASSERT_FALSE(metric_registry.removeMetric("random_metric_name")); 46 | } 47 | 48 | TEST(metricregistry, counterTest) { 49 | MetricRegistry metric_registry; 50 | 51 | const std::string counter1("counter1"); 52 | const std::string counter2("counter2"); 53 | 54 | // Create a counter 55 | CounterPtr counter_ptr1(metric_registry.counter(counter1)); 56 | ASSERT_TRUE(counter_ptr1.get() != NULL); 57 | 58 | // Fetch already created counter. 59 | CounterPtr counter_ptr2(metric_registry.counter(counter1)); 60 | ASSERT_TRUE(counter_ptr1.get() == counter_ptr2.get()); 61 | 62 | // Cannot add a new metric type with existing type. 63 | ASSERT_THROW(metric_registry.histogram(counter1), std::invalid_argument); 64 | 65 | // Create another counter 66 | CounterPtr counter_ptr3(metric_registry.counter(counter2)); 67 | ASSERT_TRUE(counter_ptr3.get() != NULL); 68 | ASSERT_TRUE(counter_ptr1.get() != counter_ptr3.get()); 69 | 70 | CounterMap counters(metric_registry.getCounters()); 71 | ASSERT_EQ((size_t )2, counters.size()); 72 | ASSERT_STREQ(counter1.c_str(), counters.begin()->first.c_str()); 73 | ASSERT_STREQ(counter2.c_str(), counters.rbegin()->first.c_str()); 74 | 75 | ASSERT_TRUE(metric_registry.removeMetric(counter2)); 76 | counters = metric_registry.getCounters(); 77 | ASSERT_EQ((size_t )1, counters.size()); 78 | ASSERT_STREQ(counter1.c_str(), counters.begin()->first.c_str()); 79 | } 80 | 81 | TEST(metricregistry, gaugeTest) { 82 | MetricRegistry metric_registry; 83 | 84 | const std::string gauge1("gauge1"); 85 | const std::string gauge2("gauge2"); 86 | 87 | // Create a gauge 88 | GaugePtr gauge_ptr1(new FakeGauge()); 89 | ASSERT_TRUE(metric_registry.addGauge(gauge1, gauge_ptr1)); 90 | 91 | // Create another gauge 92 | GaugePtr gauge_ptr2(new FakeGauge()); 93 | // Cannot add a new gauge with same name. 94 | ASSERT_THROW(metric_registry.addGauge(gauge1, gauge_ptr2), 95 | std::invalid_argument); 96 | // Try creating a different metric with the same name. 97 | ASSERT_THROW(metric_registry.counter(gauge1), std::invalid_argument); 98 | 99 | // add a new gauge with different name. 100 | ASSERT_TRUE(metric_registry.addGauge(gauge2, gauge_ptr2)); 101 | GaugeMap gauges(metric_registry.getGauges()); 102 | ASSERT_EQ((size_t )2, gauges.size()); 103 | ASSERT_STREQ(gauge1.c_str(), gauges.begin()->first.c_str()); 104 | ASSERT_STREQ(gauge2.c_str(), gauges.rbegin()->first.c_str()); 105 | 106 | ASSERT_TRUE(metric_registry.removeMetric(gauge1)); 107 | ASSERT_FALSE(metric_registry.removeMetric(gauge1)); 108 | gauges = metric_registry.getGauges(); 109 | ASSERT_EQ((size_t )1, gauges.size()); 110 | ASSERT_STREQ(gauge2.c_str(), gauges.begin()->first.c_str()); 111 | } 112 | 113 | TEST(metricregistry, histogramTest) { 114 | MetricRegistry metric_registry; 115 | 116 | const std::string histogram1("histogram1"); 117 | const std::string histogram2("histogram2"); 118 | 119 | // Create a histogram 120 | HistogramPtr histogram_ptr1(metric_registry.histogram(histogram1)); 121 | ASSERT_TRUE(histogram_ptr1.get() != NULL); 122 | 123 | // Fetch already created histogram. 124 | HistogramPtr histogram_ptr2(metric_registry.histogram(histogram1)); 125 | ASSERT_TRUE(histogram_ptr1.get() == histogram_ptr2.get()); 126 | 127 | // Cannot add a new metric type with existing type. 128 | ASSERT_THROW(metric_registry.counter(histogram1), std::invalid_argument); 129 | 130 | // Create another histogram 131 | HistogramPtr histogram_ptr3(metric_registry.histogram(histogram2)); 132 | ASSERT_TRUE(histogram_ptr3.get() != NULL); 133 | ASSERT_TRUE(histogram_ptr1.get() != histogram_ptr3.get()); 134 | 135 | HistogramMap histograms(metric_registry.getHistograms()); 136 | ASSERT_EQ((size_t )2, histograms.size()); 137 | ASSERT_STREQ(histogram1.c_str(), histograms.begin()->first.c_str()); 138 | ASSERT_STREQ(histogram2.c_str(), histograms.rbegin()->first.c_str()); 139 | 140 | ASSERT_TRUE(metric_registry.removeMetric(histogram2)); 141 | histograms = metric_registry.getHistograms(); 142 | ASSERT_EQ((size_t )1, histograms.size()); 143 | ASSERT_STREQ(histogram1.c_str(), histograms.begin()->first.c_str()); 144 | } 145 | 146 | TEST(metricregistry, meterTest) { 147 | MetricRegistry metric_registry; 148 | 149 | const std::string meter1("meter1"); 150 | const std::string meter2("meter2"); 151 | 152 | // Create a meter 153 | MeterPtr meter_ptr1(metric_registry.meter(meter1)); 154 | ASSERT_TRUE(meter_ptr1.get() != NULL); 155 | 156 | // Fetch already created meter. 157 | MeterPtr meter_ptr2(metric_registry.meter(meter1)); 158 | ASSERT_TRUE(meter_ptr1.get() == meter_ptr2.get()); 159 | 160 | // Cannot add a new metric type with existing type. 161 | ASSERT_THROW(metric_registry.counter(meter1), std::invalid_argument); 162 | 163 | // Create another meter 164 | MeterPtr meter_ptr3(metric_registry.meter(meter2)); 165 | ASSERT_TRUE(meter_ptr3.get() != NULL); 166 | ASSERT_TRUE(meter_ptr1.get() != meter_ptr3.get()); 167 | 168 | MeteredMap meters(metric_registry.getMeters()); 169 | ASSERT_EQ((size_t )2, meters.size()); 170 | ASSERT_STREQ(meter1.c_str(), meters.begin()->first.c_str()); 171 | ASSERT_STREQ(meter2.c_str(), meters.rbegin()->first.c_str()); 172 | 173 | ASSERT_TRUE(metric_registry.removeMetric(meter2)); 174 | meters = metric_registry.getMeters(); 175 | ASSERT_EQ((size_t )1, meters.size()); 176 | ASSERT_STREQ(meter1.c_str(), meters.begin()->first.c_str()); 177 | } 178 | 179 | TEST(metricregistry, timerTest) { 180 | MetricRegistry metric_registry; 181 | 182 | const std::string timer1("timer1"); 183 | const std::string timer2("timer2"); 184 | 185 | // Create a timer 186 | TimerPtr timer_ptr1(metric_registry.timer(timer1)); 187 | ASSERT_TRUE(timer_ptr1.get() != NULL); 188 | 189 | // Fetch already created timer. 190 | TimerPtr timer_ptr2(metric_registry.timer(timer1)); 191 | ASSERT_TRUE(timer_ptr1.get() == timer_ptr2.get()); 192 | 193 | // Cannot add a new metric type with existing type. 194 | ASSERT_THROW(metric_registry.counter(timer1), std::invalid_argument); 195 | 196 | // Create another timer 197 | TimerPtr timer_ptr3(metric_registry.timer(timer2)); 198 | ASSERT_TRUE(timer_ptr3.get() != NULL); 199 | ASSERT_TRUE(timer_ptr1.get() != timer_ptr3.get()); 200 | 201 | TimerMap timers(metric_registry.getTimers()); 202 | ASSERT_EQ((size_t )2, timers.size()); 203 | ASSERT_STREQ(timer1.c_str(), timers.begin()->first.c_str()); 204 | ASSERT_STREQ(timer2.c_str(), timers.rbegin()->first.c_str()); 205 | 206 | ASSERT_TRUE(metric_registry.removeMetric(timer2)); 207 | timers = metric_registry.getTimers(); 208 | ASSERT_EQ((size_t )1, timers.size()); 209 | ASSERT_STREQ(timer1.c_str(), timers.begin()->first.c_str()); 210 | } 211 | 212 | } 213 | } 214 | 215 | -------------------------------------------------------------------------------- /test/cppmetrics/core/test_scheduled_reporter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * test_scheduled_reporter.cpp 11 | * 12 | * Created on: Jun 25, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include 18 | #include "cppmetrics/core/scheduled_reporter.h" 19 | 20 | namespace cppmetrics { 21 | namespace core { 22 | 23 | namespace { 24 | 25 | class StubScheduledReporter: public ScheduledReporter { 26 | public: 27 | StubScheduledReporter(MetricRegistryPtr registry, boost::chrono::milliseconds rate_unit) : 28 | ScheduledReporter(registry, rate_unit), 29 | invocation_count_(0) { 30 | last_time_ = Clock::now(); 31 | } 32 | 33 | virtual ~StubScheduledReporter() { 34 | } 35 | 36 | size_t invocation_count() const { 37 | return invocation_count_; 38 | } 39 | 40 | virtual void report(CounterMap counter_map, 41 | HistogramMap histogram_map, 42 | MeteredMap meter_map, 43 | TimerMap timer_map, 44 | GaugeMap gauge_map) { 45 | ++invocation_count_; 46 | boost::chrono::milliseconds invocation_period( 47 | boost::chrono::duration_cast(Clock::now() - last_time_)); 48 | std::cout << invocation_count_ << " Invocation period(in millis): " << invocation_period.count() 49 | << std::endl; 50 | last_time_ = Clock::now(); 51 | } 52 | 53 | private: 54 | size_t invocation_count_; 55 | Clock::time_point last_time_; 56 | }; 57 | 58 | } 59 | 60 | TEST(scheduledreporter, test) { 61 | StubScheduledReporter scheduled_reporter(MetricRegistry::DEFAULT_REGISTRY(), 62 | boost::chrono::milliseconds(1)); 63 | scheduled_reporter.start(boost::chrono::milliseconds(100)); 64 | boost::this_thread::sleep(boost::posix_time::seconds(1)); 65 | scheduled_reporter.stop(); 66 | ASSERT_LE((size_t)9, scheduled_reporter.invocation_count()); 67 | ASSERT_GE((size_t)11, scheduled_reporter.invocation_count()); 68 | } 69 | 70 | } 71 | } 72 | 73 | 74 | -------------------------------------------------------------------------------- /test/cppmetrics/core/test_snapshot.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * test_snapshot.cpp 11 | * 12 | * Created on: Jun 25, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include "cppmetrics/core/snapshot.h" 18 | 19 | namespace cppmetrics { 20 | namespace core { 21 | 22 | TEST(snapshot, zeroSampleTest) { 23 | const ValueVector samples; 24 | Snapshot snapshot(samples); 25 | ASSERT_EQ(0, snapshot.getMin()); 26 | ASSERT_EQ(0, snapshot.getMax()); 27 | ASSERT_NEAR(0.0, snapshot.getMean(), 0.000001); 28 | ASSERT_NEAR(0.0, snapshot.getStdDev(), 0.0001); 29 | } 30 | 31 | TEST(snapshot, oneSampleTest) { 32 | const ValueVector::value_type values_array[] = { 1 }; 33 | const size_t element_count(sizeof(values_array) / sizeof(values_array[0])); 34 | const ValueVector values(values_array, values_array + element_count); 35 | Snapshot snapshot(values); 36 | ASSERT_EQ(1, snapshot.getMin()); 37 | ASSERT_EQ(1, snapshot.getMax()); 38 | ASSERT_NEAR(1.0, snapshot.getMean(), 0.000001); 39 | ASSERT_NEAR(0.0, snapshot.getStdDev(), 0.0001); 40 | } 41 | 42 | TEST(snapshot, minMaxMedianPercentileWithFiveSamplesTest) { 43 | 44 | const ValueVector::value_type values_array[] = { 5, 1, 2, 3, 4 }; 45 | const size_t element_count(sizeof(values_array) / sizeof(values_array[0])); 46 | const ValueVector values(values_array, values_array + element_count); 47 | Snapshot snapshot(values); 48 | 49 | ASSERT_EQ(element_count, snapshot.size()); 50 | 51 | ValueVector expected_values(values); 52 | std::sort(expected_values.begin(), expected_values.end()); 53 | ASSERT_EQ(expected_values, snapshot.getValues()); 54 | 55 | ASSERT_NEAR(1.0, snapshot.getValue(0.0), 0.1); 56 | ASSERT_NEAR(5.0, snapshot.getValue(1.0), 0.1); 57 | ASSERT_NEAR(3.0, snapshot.getMedian(), 0.1); 58 | ASSERT_NEAR(4.5, snapshot.get75thPercentile(), 0.1); 59 | ASSERT_NEAR(5.0, snapshot.get95thPercentile(), 0.1); 60 | ASSERT_NEAR(5.0, snapshot.get98thPercentile(), 0.1); 61 | ASSERT_NEAR(5.0, snapshot.get99thPercentile(), 0.1); 62 | ASSERT_NEAR(5.0, snapshot.get99thPercentile(), 0.1); 63 | ASSERT_EQ(1, snapshot.getMin()); 64 | ASSERT_EQ(5, snapshot.getMax()); 65 | ASSERT_NEAR(3.0, snapshot.getMean(), 0.000001); 66 | ASSERT_NEAR(1.5811, snapshot.getStdDev(), 0.0001); 67 | 68 | } 69 | 70 | } 71 | } 72 | 73 | -------------------------------------------------------------------------------- /test/cppmetrics/core/test_timer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * test_timer.cpp 11 | * 12 | * Created on: Jun 25, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "cppmetrics/core/timer.h" 22 | 23 | namespace cppmetrics { 24 | namespace core { 25 | 26 | TEST(timer, initialTest) { 27 | Timer timer; 28 | ASSERT_EQ((boost::uint64_t )0, timer.getCount()); 29 | ASSERT_NEAR(0.0, timer.getMeanRate(), 0.000001); 30 | ASSERT_NEAR(0.0, timer.getOneMinuteRate(), 0.000001); 31 | ASSERT_NEAR(0.0, timer.getFiveMinuteRate(), 0.000001); 32 | ASSERT_NEAR(0.0, timer.getFifteenMinuteRate(), 0.000001); 33 | 34 | timer.update(boost::chrono::seconds(1)); 35 | ASSERT_EQ((boost::uint64_t )1, timer.getCount()); 36 | } 37 | 38 | TEST(timer, timerContextTest) { 39 | Timer timer; 40 | boost::mt11213b rng; 41 | for (size_t i = 0; i < 100; ++i) { 42 | boost::random::uniform_int_distribution<> uniform(10, 30); 43 | size_t sleep_time = uniform(rng); 44 | TimerContextPtr time_context(timer.timerContextPtr()); 45 | boost::this_thread::sleep(boost::posix_time::milliseconds(sleep_time)); 46 | } 47 | ASSERT_EQ((boost::uint64_t )100, timer.getCount()); 48 | SnapshotPtr snapshot = timer.getSnapshot(); 49 | // On jenkins builds, when there is lot of load, the duration of the sleep 50 | // in the timerContextTest takes more than the 20 ns. This is to eliminate 51 | // the periodic test failures during CI. 52 | 53 | std::cout << " count = " << timer.getCount() << std::endl; 54 | std::cout << " mean rate = " << (timer.getMeanRate()) 55 | << " calls per 1 sec" << std::endl; 56 | std::cout << " 1-minute rate = " << (timer.getOneMinuteRate()) 57 | << " calls per 1 sec" << std::endl; 58 | std::cout << " 5-minute rate = " << (timer.getFiveMinuteRate()) 59 | << " calls per 1 sec" << std::endl; 60 | std::cout << " 15-minute rate = " << (timer.getFifteenMinuteRate()) 61 | << " calls per 1 sec" << std::endl; 62 | std::cout << " min = " << (snapshot->getMin()) << " ns " 63 | << std::endl; 64 | std::cout << " max = " << (snapshot->getMax()) << " ns " 65 | << std::endl; 66 | std::cout << " mean = " << (snapshot->getMean()) << " ns " 67 | << std::endl; 68 | std::cout << " stddev = " << (snapshot->getStdDev()) << " ns " 69 | << std::endl; 70 | std::cout << " median = " << (snapshot->getMedian()) << " ns " 71 | << std::endl; 72 | std::cout << " 75% <= " << (snapshot->get75thPercentile()) 73 | << " ns " << std::endl; 74 | std::cout << " 95% <= " << (snapshot->get95thPercentile()) 75 | << " ns " << std::endl; 76 | std::cout << " 98% <= " << (snapshot->get98thPercentile()) 77 | << " ns " << std::endl; 78 | std::cout << " 99% <= " << (snapshot->get99thPercentile()) 79 | << " ns " << std::endl; 80 | std::cout << " 99.9% <= " << (snapshot->get999thPercentile()) 81 | << " ns " << std::endl; 82 | ASSERT_LE(25, static_cast(timer.getMeanRate())); 83 | ASSERT_GE(55, static_cast(timer.getMeanRate())); 84 | ASSERT_LE( 85 | boost::chrono::duration_cast( 86 | boost::chrono::milliseconds(8)).count(), 87 | static_cast(snapshot->getMin())); 88 | ASSERT_GE( 89 | boost::chrono::duration_cast( 90 | boost::chrono::milliseconds(45)).count(), 91 | static_cast(snapshot->getMax())); 92 | } 93 | 94 | } 95 | } 96 | 97 | -------------------------------------------------------------------------------- /test/cppmetrics/core/test_uniform_sample.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * test_uniform_sample.cpp 11 | * 12 | * Created on: Jun 26, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include 18 | #include "cppmetrics/core/uniform_sample.h" 19 | 20 | namespace cppmetrics { 21 | namespace core { 22 | 23 | TEST(uniformsample, simpletest) { 24 | 25 | UniformSample uniform_sample(100); 26 | 27 | for (boost::uint64_t i = 0; i < 1000; i++) { 28 | uniform_sample.update(i); 29 | } 30 | SnapshotPtr snapshot = uniform_sample.getSnapshot(); 31 | ASSERT_EQ((size_t )100, uniform_sample.size()); 32 | ASSERT_EQ((size_t )100, snapshot->size()); 33 | BOOST_FOREACH(ValueVector::value_type i, snapshot->getValues()) { 34 | ASSERT_LE(0, i); 35 | ASSERT_GT(1000, i); 36 | } 37 | } 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test/cppmetrics/graphite/test_graphite_reporter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * test_graphite_reporter.cpp 11 | * 12 | * Created on: Jun 26, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include 18 | #include "cppmetrics/graphite/graphite_reporter.h" 19 | 20 | namespace cppmetrics { 21 | namespace graphite { 22 | 23 | static const std::string PREFIX("Prefix"); 24 | static const std::string GAUGE_NAME("Gauge"); 25 | static const boost::int64_t GAUGE_VALUE(100); 26 | 27 | 28 | static const std::string COUNTER_NAME("Counter"); 29 | static const boost::uint64_t COUNTER_VALUE(100); 30 | 31 | 32 | namespace { 33 | 34 | 35 | class FakeGauge : public core::Gauge { 36 | public: 37 | virtual ~FakeGauge() {} 38 | virtual boost::int64_t getValue() { 39 | return GAUGE_VALUE; 40 | } 41 | }; 42 | 43 | 44 | // TODO: use gmock here instead. 45 | class FakeGraphiteSender : public GraphiteSender { 46 | public: 47 | enum MetricType {Counter, Gauge, Histogram, Meter, Timer}; 48 | FakeGraphiteSender(MetricType metric_type) : metric_type_(metric_type) {} 49 | 50 | virtual ~FakeGraphiteSender() { 51 | verifyMethodCallOrder(); 52 | }; 53 | 54 | virtual void connect() { 55 | method_called_[Connect] = true; 56 | } 57 | 58 | virtual void send(const std::string& name, const std::string& value, 59 | boost::uint64_t timestamp) { 60 | ASSERT_TRUE(method_called_[Connect]); 61 | method_called_[Send] = true; 62 | switch (metric_type_) { 63 | case Counter: 64 | sendCounter(name, value, timestamp); 65 | break; 66 | case Gauge: 67 | sendGauge(name, value, timestamp); 68 | break; 69 | case Histogram: 70 | sendHistogram(name, value, timestamp); 71 | break; 72 | case Meter: 73 | sendMeter(name, value, timestamp); 74 | break; 75 | case Timer: 76 | sendTimer(name, value, timestamp); 77 | break; 78 | default: 79 | ASSERT_EQ(2, 1); 80 | } 81 | } 82 | 83 | virtual void close() { 84 | ASSERT_TRUE(method_called_[Connect]); 85 | ASSERT_TRUE(method_called_[Send]); 86 | method_called_[Close] = true; 87 | } 88 | 89 | private: 90 | enum METHOD { Connect = 0, Send, Close, TotalMethods}; 91 | bool method_called_[TotalMethods]; 92 | 93 | MetricType metric_type_; 94 | 95 | void verifyMethodCallOrder() { 96 | ASSERT_TRUE(method_called_[Connect]); 97 | ASSERT_TRUE(method_called_[Send]); 98 | ASSERT_TRUE(method_called_[Close]); 99 | } 100 | 101 | void sendGauge(const std::string& name, const std::string& actual_value, 102 | boost::uint64_t timestamp) { 103 | std::string expected_value(boost::lexical_cast(GAUGE_VALUE)); 104 | ASSERT_STREQ(std::string(PREFIX + '.' + GAUGE_NAME).c_str(), name.c_str()); 105 | ASSERT_STREQ(expected_value.c_str(), actual_value.c_str()); 106 | } 107 | 108 | void sendCounter(const std::string& name, const std::string& actual_value, 109 | boost::uint64_t timestamp) { 110 | std::string expected_value(boost::lexical_cast(COUNTER_VALUE)); 111 | ASSERT_STREQ(std::string(PREFIX + '.' + COUNTER_NAME + ".count").c_str(), name.c_str()); 112 | ASSERT_STREQ(expected_value.c_str(), actual_value.c_str()); 113 | } 114 | 115 | void sendHistogram(const std::string& name, const std::string& value, 116 | boost::uint64_t timestamp) { 117 | 118 | } 119 | 120 | void sendMeter(const std::string& name, const std::string& value, 121 | boost::uint64_t timestamp) { 122 | 123 | } 124 | 125 | void sendTimer(const std::string& name, const std::string& value, 126 | boost::uint64_t timestamp) { 127 | 128 | } 129 | }; 130 | 131 | } 132 | 133 | TEST(graphitereporter, gaugetest) { 134 | core::MetricRegistryPtr metric_registry(new core::MetricRegistry()); 135 | GraphiteSenderPtr graphite_sender(new FakeGraphiteSender(FakeGraphiteSender::Gauge)); 136 | 137 | core::GaugePtr gauge_ptr(new FakeGauge()); 138 | metric_registry->addGauge(GAUGE_NAME, gauge_ptr); 139 | 140 | GraphiteReporter graphite_reporter(metric_registry, 141 | graphite_sender, PREFIX, 142 | boost::chrono::seconds(1)); 143 | 144 | graphite_reporter.start(boost::chrono::milliseconds(100)); 145 | boost::this_thread::sleep(boost::posix_time::milliseconds(150)); 146 | graphite_reporter.stop(); 147 | } 148 | 149 | TEST(graphitereporter, countertest) { 150 | core::MetricRegistryPtr metric_registry(new core::MetricRegistry()); 151 | GraphiteSenderPtr graphite_sender(new FakeGraphiteSender(FakeGraphiteSender::Counter)); 152 | 153 | 154 | core::CounterPtr counter_ptr(metric_registry->counter(COUNTER_NAME)); 155 | counter_ptr->increment(COUNTER_VALUE); 156 | 157 | GraphiteReporter graphite_reporter(metric_registry, 158 | graphite_sender, PREFIX, 159 | boost::chrono::seconds(1)); 160 | 161 | graphite_reporter.start(boost::chrono::milliseconds(100)); 162 | boost::this_thread::sleep(boost::posix_time::milliseconds(150)); 163 | graphite_reporter.stop(); 164 | } 165 | 166 | } 167 | } 168 | 169 | 170 | -------------------------------------------------------------------------------- /test/cppmetrics/graphite/test_graphite_sender_tcp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2014 NeuStar, Inc. All rights reserved. 3 | * NeuStar, the Neustar logo and related names and logos are registered 4 | * trademarks, service marks or tradenames of NeuStar, Inc. All other 5 | * product names, company names, marks, logos and symbols may be trademarks 6 | * of their respective owners. 7 | */ 8 | 9 | /* 10 | * test_graphite_sender_tcp.cpp 11 | * 12 | * Created on: Aug 1, 2014 13 | * Author: vpoliboy 14 | */ 15 | 16 | #include 17 | #include "cppmetrics/graphite/graphite_sender_tcp.h" 18 | 19 | namespace cppmetrics { 20 | namespace graphite { 21 | 22 | TEST(graphiteSenderTCP, connectionFailuresTest) { 23 | GraphiteSenderTCP graphite_sender_tcp("localhost", 3483); 24 | ASSERT_THROW(graphite_sender_tcp.connect(), std::runtime_error); 25 | } 26 | 27 | } 28 | } 29 | 30 | --------------------------------------------------------------------------------