Skip to content

[WIP] Add system and process metrics #218

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions instrumentation/process_metrics/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
cmake_minimum_required(VERSION 3.12)

project(opentelemetry-process-metrics)

add_definitions(-DHAVE_CONSOLE_LOG)

find_package(opentelemetry-cpp REQUIRED)
find_package(CURL REQUIRED)

option(WITH_EXAMPLE "Whether to build example code" ON)


include_directories(include)
if(UNIX AND NOT APPLE)
message("LINUX...")
add_library(opentelemetry_process_metrics src/linux/process_cpu_time.cc src/linux/process_metrics_linux_factory.cc src/test_lib.cc)
else()
message("SOMETHIG ELSE...")
add_library(opentelemetry_process_metrics src/noop/process_metrics_noop_factory.cc src/test_lib.cc)
endif()

if (WITH_EXAMPLE)
add_executable(metrics_example example/metrics_example.cc)
target_link_libraries(metrics_example opentelemetry_process_metrics opentelemetry-cpp::metrics
opentelemetry-cpp::resources opentelemetry_exporter_ostream_metrics)
endif()
118 changes: 118 additions & 0 deletions instrumentation/process_metrics/example/metrics_example.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# include "opentelemetry/exporters/ostream/metric_exporter.h"
# include "opentelemetry/metrics/provider.h"
# include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h"
# include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader.h"
# include "opentelemetry/sdk/metrics/meter.h"
# include "opentelemetry/sdk/metrics/meter_provider.h"

#include "../include/test_lib.h"

# include <memory>
# include <thread>

namespace metric_sdk = opentelemetry::sdk::metrics;
namespace nostd = opentelemetry::nostd;
namespace common = opentelemetry::common;
namespace exportermetrics = opentelemetry::exporter::metrics;
namespace metrics_api = opentelemetry::metrics;

namespace
{

void initMetrics()
{
std::cout << "\n LALIT->Init metrics\n";
std::unique_ptr<metric_sdk::PushMetricExporter> exporter{new exportermetrics::OStreamMetricExporter};

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

// Initialize and set the global MeterProvider
metric_sdk::PeriodicExportingMetricReaderOptions options;
options.export_interval_millis = std::chrono::milliseconds(1000);
options.export_timeout_millis = std::chrono::milliseconds(500);
std::unique_ptr<metric_sdk::MetricReader> reader{
new metric_sdk::PeriodicExportingMetricReader(std::move(exporter), options)};
auto provider = std::shared_ptr<metrics_api::MeterProvider>(new metric_sdk::MeterProvider());
auto p = std::static_pointer_cast<metric_sdk::MeterProvider>(provider);
p->AddMetricReader(std::move(reader));

#if 0
//process.cpu.time view
std::unique_ptr<metric_sdk::InstrumentSelector> observable_instrument_selector{
new metric_sdk::InstrumentSelector(metric_sdk::InstrumentType::kObservableCounter,
"process.cpu.time")};
std::unique_ptr<metric_sdk::MeterSelector> observable_meter_selector{
new metric_sdk::MeterSelector("process.cpu.time", "1.2.0", "schema")};
std::unique_ptr<metric_sdk::View> observable_sum_view{
new metric_sdk::View{"process.metrics", "des", metric_sdk::AggregationType::kSum}};
p->AddView(std::move(observable_instrument_selector), std::move(observable_meter_selector),
std::move(observable_sum_view));

#endif
metrics_api::Provider::SetMeterProvider(provider);
std::cout << "\n LALIT->Init metrics done\n";

}
} // namespace

int main(int argc, char **argv)
{
std::vector<std::string> args(argv + 1, argv + argc);
std::string example_type;
if (args.size() == 0) {
std::cout << "Options -- \n" ;
std::cout << "\t --process.cpu.time --process.cpu.utilization --process.memory.usage --process.memory.virtual\n" ;
std::cout << "\t --process.disk.io --process.network.io --process.threads --process.open.files --process.context.switches\n";
exit(1);
}
initMetrics();
for (auto &arg: args) {
if (arg == "--process.cpu.time") {
TestLib::create_process_cpu_time_observable_counter();
}
else if (arg == "--process.cpu.utilization")
{
TestLib::create_process_cpu_utilization_observable_gauge();
}
else if (arg == "--process.memory.usage")
{
TestLib::create_process_memory_usage_observable_gauge();
}
else if (arg == "--process.memory.virtual")
{
TestLib::create_process_memory_virtual_observable_gauge();
}
else if (arg == "--process.disk.io")
{
TestLib::create_process_disk_io_observable_gauge();
}
else if (arg == "--process.network.io")
{
TestLib::create_process_network_io_observable_gauge();
}
else if (arg == "--process.threads")
{
TestLib::create_process_threads_observable_gauge();
}
else if(arg == "--process.open.files")
{
TestLib::create_process_open_files_observable_gauge();
}
else if (arg == "--process.context.switches")
{
TestLib::create_process_context_switches_observable_gauge();
}
else {
std::cout << " Invalid command, exiting..";
std::cout << "\tOptions -- \n" ;
std::cout << "\t\t --process.cpu.time --process.cpu.utilization --process.memory.usage --process.memory.virtual" ;
std::cout << "\t\t --process.disk.io --process.network.io --process.threads --process.open.files --process.context.switches";
exit(1);
}
}

while(true){
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#pragma once

# include "opentelemetry/metrics/observer_result.h"


class ProcessMetricsFactory
{
public:
static void GetProcessCpuTime(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/);

static void GetProcessCpuUtilization(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/);

static void GetProcessMemoryUsage(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/);

static void GetProcessMemoryVirtual(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/);

static void GetProcessDiskIO(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/);

static void GetProcessNetworkIO(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/);

static void GetProcessThreads(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/);

static void GetProcessOpenFileDescriptors(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/);

static void GetProcessContextSwitches(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/);

};
30 changes: 30 additions & 0 deletions instrumentation/process_metrics/include/test_lib.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/metrics/async_instruments.h"
class TestLib
{
public:
static void create_process_cpu_time_observable_counter();
static void create_process_cpu_utilization_observable_gauge();
static void create_process_memory_usage_observable_gauge();
static void create_process_memory_virtual_observable_gauge();
static void create_process_disk_io_observable_gauge();
static void create_process_network_io_observable_gauge();
static void create_process_threads_observable_gauge();
static void create_process_open_files_observable_gauge();
static void create_process_context_switches_observable_gauge();
private:
static opentelemetry::nostd::shared_ptr<opentelemetry::metrics::ObservableInstrument> cpu_time_obserable_counter_;
static opentelemetry::nostd::shared_ptr<opentelemetry::metrics::ObservableInstrument> cpu_utilization_obserable_gauge_;
static opentelemetry::nostd::shared_ptr<opentelemetry::metrics::ObservableInstrument> memory_usage_obserable_gauge_;
static opentelemetry::nostd::shared_ptr<opentelemetry::metrics::ObservableInstrument> memory_virtual_obserable_gauge_;
static opentelemetry::nostd::shared_ptr<opentelemetry::metrics::ObservableInstrument> disk_io_obserable_gauge_;
static opentelemetry::nostd::shared_ptr<opentelemetry::metrics::ObservableInstrument> network_io_obserable_gauge_;
static opentelemetry::nostd::shared_ptr<opentelemetry::metrics::ObservableInstrument> threads_obserable_gauge_;
static opentelemetry::nostd::shared_ptr<opentelemetry::metrics::ObservableInstrument> open_files_obserable_gauge_;
static opentelemetry::nostd::shared_ptr<opentelemetry::metrics::ObservableInstrument> context_switches_obserable_gauge_;
};
50 changes: 50 additions & 0 deletions instrumentation/process_metrics/src/linux/process_cpu_time.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#ifdef __linux__
#include "process_cpu_time.h"
#include <unistd.h>
#include <thread>
#include <iostream>
#include <math.h>


long ProcessCpuTime::clock_ticks_per_sec_ = sysconf(_SC_CLK_TCK);

ProcessCpuTime::ProcessCpuTime()
: number_of_cpus_{std::thread::hardware_concurrency()}, last_clock_time_{std::chrono::high_resolution_clock::now()}
{
times(&start_time_);
last_cpu_time_ = start_time_;
}

long ProcessCpuTime::TotalElapsedTime()
{
times(&last_cpu_time_);
return ((last_cpu_time_.tms_utime + last_cpu_time_.tms_stime) - (start_time_.tms_utime + start_time_.tms_stime)) / clock_ticks_per_sec_;
}

double ProcessCpuTime::LastElapsedTime()
{
struct tms current_cpu_time;
times(&current_cpu_time);
auto elapsed_cpu_time = ((current_cpu_time.tms_utime + current_cpu_time.tms_stime) - (last_cpu_time_.tms_utime + last_cpu_time_.tms_stime)) / clock_ticks_per_sec_;
last_cpu_time_ = current_cpu_time;
return elapsed_cpu_time;
}

double ProcessCpuTime::CpuUtilization()
{
struct tms current_cpu_time;
times(&current_cpu_time);
auto current_clock_time = std::chrono::high_resolution_clock::now();
auto elapsed_cpu_time = ((current_cpu_time.tms_utime + current_cpu_time.tms_stime) - (last_cpu_time_.tms_utime + last_cpu_time_.tms_stime)) / clock_ticks_per_sec_;
auto elapsed_clock_time = std::chrono::duration_cast<std::chrono::seconds>(current_clock_time - last_clock_time_);
last_clock_time_ = current_clock_time;
double cpu_utlization = 0;
if (elapsed_clock_time.count() > 0)
cpu_utlization = elapsed_cpu_time/(elapsed_clock_time.count() * number_of_cpus_);
return cpu_utlization;
}

#endif
31 changes: 31 additions & 0 deletions instrumentation/process_metrics/src/linux/process_cpu_time.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#ifdef __linux__
#include <time.h>
#include <chrono>
#include <sys/times.h>

class ProcessCpuTime
{
public:
ProcessCpuTime();

// returns cpu time (user + system) from beginning
long TotalElapsedTime();

// returns cpu time (user + system) since last call to Last*Time()
double LastElapsedTime();

// returns cpu utilization
double CpuUtilization();

private:
static long clock_ticks_per_sec_;
struct tms start_time_;
mutable struct tms last_cpu_time_;
const unsigned int number_of_cpus_;
std::chrono::time_point<std::chrono::high_resolution_clock> last_clock_time_;
};

#endif
Loading