Commit f1304e87 by Amir Aharon

compile fixes and add cppmetrics 3party

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