ha/service-mgmt/sm-common/src/sm_node_stats.c

446 lines
14 KiB
C

//
// Copyright (c) 2014 Wind River Systems, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
#include "sm_node_stats.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "sm_limits.h"
#include "sm_types.h"
#include "sm_debug.h"
#define SM_NODE_STATS_PROC_STAT "/proc/stat"
#define SM_NODE_STATS_PROC_MEMINFO "/proc/meminfo"
#define SM_NODE_STATS_PROC_DISKSTATS "/proc/diskstats"
#define SM_NODE_STATS_PROC_NET_DEV "/proc/net/dev"
static long _user_hz = 0;
// ****************************************************************************
// Node Statistics - Get CPU
// =========================
SmErrorT sm_node_stats_get_cpu( const char cpu_name[], SmNodeCpuStatsT* stats )
{
char line[512];
FILE* fp;
memset( stats, 0, sizeof(SmNodeCpuStatsT) );
if( 0 == _user_hz )
{
DPRINTFE( "User hertz is not defined." );
return( SM_FAILED );
}
if( '\0' == cpu_name[0] )
{
snprintf( stats->cpu_name, sizeof(stats->cpu_name), "all" );
} else {
snprintf( stats->cpu_name, sizeof(stats->cpu_name), "%s", cpu_name );
}
fp = fopen( SM_NODE_STATS_PROC_STAT, "r" );
if( NULL == fp )
{
DPRINTFE( "Failed to get cpu statistics from %s.",
SM_NODE_STATS_PROC_STAT );
return( SM_NOT_FOUND );
}
while( NULL != fgets( line, sizeof(line), fp ) )
{
if((( '\0' == cpu_name[0] )&&( 0 == strncmp( line, "cpu ", 4 ) ))||
( 0 == strncmp( line, cpu_name, 4 ) ))
{
sscanf( line+5, "%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
&(stats->user_cpu_usage),
&(stats->nice_cpu_usage),
&(stats->system_cpu_usage),
&(stats->idle_task_cpu_usage),
&(stats->iowait_cpu_usage),
&(stats->irq_cpu_usage),
&(stats->soft_irq_cpu_usage),
&(stats->steal_cpu_usage),
&(stats->guest_cpu_usage),
&(stats->guest_nice_cpu_usage) );
} else if( 0 == strncmp( line, "intr ", 5 ) ) {
sscanf( line+5, "%llu", &(stats->total_interrupts) );
} else if( 0 == strncmp( line, "ctxt ", 5 ) ) {
sscanf( line+5, "%llu", &(stats->total_context_switches) );
} else if( 0 == strncmp( line, "processes ", 10 ) ) {
sscanf( line+10, "%llu", &(stats->total_processes) );
} else if( 0 == strncmp( line, "procs_running ", 14 ) ) {
sscanf( line+14, "%llu", &(stats->processes_running) );
} else if( 0 == strncmp( line, "procs_blocked ", 14 ) ) {
sscanf( line+14, "%llu", &(stats->processes_blocked) );
} else if( 0 == strncmp( line, "btime ", 6 ) ) {
sscanf( line+6, "%llu", &(stats->boot_time_in_secs) );
}
}
fclose( fp );
return( SM_OKAY );
}
// ****************************************************************************
// ****************************************************************************
// Node Statistics - Get Memory
// ============================
SmErrorT sm_node_stats_get_memory( SmNodeMemStatsT* stats )
{
char line[512];
FILE* fp;
memset( stats, 0, sizeof(SmNodeMemStatsT) );
fp = fopen( SM_NODE_STATS_PROC_MEMINFO, "r" );
if( NULL == fp )
{
DPRINTFE( "Failed to get memory statistics from %s.",
SM_NODE_STATS_PROC_MEMINFO );
return( SM_NOT_FOUND );
}
while( NULL != fgets( line, sizeof(line), fp ) )
{
if( 0 == strncmp( line, "MemTotal:", 9 ) )
{
sscanf( line+9, "%lu", &(stats->total_memory_kB) );
} else if( 0 == strncmp( line, "MemFree:", 8 ) ) {
sscanf( line+8, "%lu", &(stats->free_memory_kB) );
} else if( 0 == strncmp( line, "Buffers:", 8 ) ) {
sscanf( line+8, "%lu", &(stats->buffers_kB) );
} else if( 0 == strncmp( line, "Cached:", 7 ) ) {
sscanf( line+7, "%lu", &(stats->cached_kB) );
} else if( 0 == strncmp( line, "SwapCached:", 11 ) ) {
sscanf( line+11, "%lu", &(stats->swap_cached_kB) );
} else if( 0 == strncmp( line, "SwapTotal:", 10 ) ) {
sscanf( line+10, "%lu", &(stats->swap_total_kB) );
} else if( 0 == strncmp( line, "SwapFree:", 9 ) ) {
sscanf( line+9, "%lu", &(stats->swap_free_kB) );
} else if( 0 == strncmp( line, "Active:", 7 ) ) {
sscanf( line+7, "%lu", &(stats->active_kB) );
} else if( 0 == strncmp( line, "Inactive:", 9 ) ) {
sscanf( line+9, "%lu", &(stats->inactive_kB) );
} else if( 0 == strncmp( line, "Dirty:", 6 ) ) {
sscanf( line+6, "%lu", &(stats->dirty_kB) );
} else if( 0 == strncmp( line, "HugePages_Total:", 16 ) ) {
sscanf( line+16, "%lu", &(stats->hugepages_total) );
} else if( 0 == strncmp( line, "HugePages_Free:", 15 ) ) {
sscanf( line+15, "%lu", &(stats->hugepages_free) );
} else if( 0 == strncmp( line, "Hugepagesize:", 13 ) ) {
sscanf( line+13, "%lu", &(stats->hugepage_size_kB) );
} else if( 0 == strncmp( line, "NFS_Unstable:", 13 ) ) {
sscanf( line+13, "%lu", &(stats->nfs_uncommited_kB) );
} else if( 0 == strncmp( line, "Committed_AS:", 13 ) ) {
sscanf( line+13, "%lu", &(stats->commited_memory_kB) );
}
}
fclose( fp );
return( SM_OKAY );
}
// ****************************************************************************
// ****************************************************************************
// Node Statistics - Get Disk
// ==========================
SmErrorT sm_node_stats_get_disk( const char dev_name[],
SmNodeDiskStatsT* stats )
{
int n_scanned;
char line[512];
FILE* fp;
memset( stats, 0, sizeof(SmNodeDiskStatsT) );
fp = fopen( SM_NODE_STATS_PROC_DISKSTATS, "r" );
if( NULL == fp )
{
DPRINTFE( "Failed to get disk statistics for %s from %s.",
dev_name, SM_NODE_STATS_PROC_DISKSTATS );
return( SM_NOT_FOUND );
}
while( NULL != fgets( line, sizeof(line), fp ) )
{
n_scanned = sscanf( line, "%u %u %s "
"%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
&(stats->major_num), &(stats->minor_num),
stats->dev_name,
&(stats->reads_completed),
&(stats->reads_merged),
&(stats->sectors_read),
&(stats->ms_spent_reading),
&(stats->writes_completed),
&(stats->writes_merged),
&(stats->sectors_written),
&(stats->ms_spent_writing),
&(stats->io_inprogress),
&(stats->ms_spent_io),
&(stats->weighted_ms_spent_io) );
if( 14 == n_scanned )
{
if( 0 == strcmp( dev_name, stats->dev_name ) )
{
DPRINTFD( "Disk (%s) stats read.", dev_name );
break;
}
}
memset( stats, 0, sizeof(SmNodeDiskStatsT) );
}
fclose( fp );
return( SM_OKAY );
}
// ****************************************************************************
// ****************************************************************************
// Node Statistics - Get Disk By Index
// ===================================
SmErrorT sm_node_stats_get_disk_by_index( unsigned int index,
SmNodeDiskStatsT* stats )
{
unsigned int current_index = 0;
int n_scanned;
char line[512];
FILE* fp;
memset( stats, 0, sizeof(SmNodeDiskStatsT) );
fp = fopen( SM_NODE_STATS_PROC_DISKSTATS, "r" );
if( NULL == fp )
{
DPRINTFE( "Failed to get disk statistics from %s.",
SM_NODE_STATS_PROC_DISKSTATS );
return( SM_NOT_FOUND );
}
while( NULL != fgets( line, sizeof(line), fp ) )
{
if( current_index == index )
{
n_scanned = sscanf( line, "%u %u %s "
"%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
&(stats->major_num), &(stats->minor_num),
stats->dev_name,
&(stats->reads_completed),
&(stats->reads_merged),
&(stats->sectors_read),
&(stats->ms_spent_reading),
&(stats->writes_completed),
&(stats->writes_merged),
&(stats->sectors_written),
&(stats->ms_spent_writing),
&(stats->io_inprogress),
&(stats->ms_spent_io),
&(stats->weighted_ms_spent_io) );
if( 14 == n_scanned )
{
break;
}
memset( stats, 0, sizeof(SmNodeDiskStatsT) );
}
++current_index;
}
fclose( fp );
return( SM_OKAY );
}
// ****************************************************************************
// ****************************************************************************
// Node Statistics - Get Network Device
// ====================================
SmErrorT sm_node_stats_get_netdev( const char dev_name[],
SmNodeNetDevStatsT* stats )
{
int stats_start = 0;
char line[512];
char if_name[512];
char dev_name_with_colon[512];
FILE* fp;
memset( stats, 0, sizeof(SmNodeNetDevStatsT) );
snprintf( stats->dev_name, sizeof(stats->dev_name), "%s", dev_name );
snprintf( dev_name_with_colon, sizeof(dev_name_with_colon), "%s:",
dev_name );
fp = fopen( SM_NODE_STATS_PROC_NET_DEV, "r" );
if( NULL == fp )
{
DPRINTFE( "Failed to get network device statistics for %s from %s.",
dev_name, SM_NODE_STATS_PROC_NET_DEV );
return( SM_NOT_FOUND );
}
while( NULL != fgets( line, sizeof(line), fp ) )
{
stats_start = strcspn( line, ":" );
sscanf( line, "%s:", if_name );
if( 0 == strncmp( if_name, dev_name_with_colon, strlen(if_name) ) )
{
sscanf( line+stats_start+2,
"%llu %llu %llu %llu %llu %llu %llu %llu "
"%llu %llu %llu %llu %llu %llu %llu %llu",
&(stats->rx_bytes),
&(stats->rx_packets),
&(stats->rx_errors),
&(stats->rx_dropped),
&(stats->rx_fifo_errors),
&(stats->rx_frame_errors),
&(stats->rx_compressed_packets),
&(stats->rx_multicast_frames),
&(stats->tx_bytes),
&(stats->tx_packets),
&(stats->tx_errors),
&(stats->tx_dropped),
&(stats->tx_fifo_errors),
&(stats->tx_collisions),
&(stats->tx_carrier_loss),
&(stats->tx_compressed_packets) );
}
}
fclose( fp );
return( SM_OKAY );
}
// ****************************************************************************
// ****************************************************************************
// Node Statistics - Get Process Status
// ====================================
SmErrorT sm_node_stats_get_process_status( int pid,
SmNodeProcessStatusT* status )
{
unsigned long long ms;
unsigned long long ns;
char filename[80];
char line[512];
FILE* fp;
memset( status, 0, sizeof(SmNodeProcessStatusT) );
// Process Stat Information
snprintf( filename, sizeof(filename), "/proc/%i/stat", pid );
fp = fopen( filename, "r" );
if( NULL == fp )
{
// Could be a short lived process.
DPRINTFD( "Failed to get process (%i) status.", pid );
return( SM_NOT_FOUND );
}
while( NULL != fgets( line, sizeof(line), fp ) )
{
sscanf( line, "%d %s %c %d %d",
&(status->pid), status->name, &(status->state),
&(status->ppid), &(status->pgrp) );
}
fclose( fp );
// Process Scheduler Information
snprintf( filename, sizeof(filename), "/proc/%i/sched", pid );
fp = fopen( filename, "r" );
if( NULL == fp )
{
// Could be a short lived process.
DPRINTFD( "Failed to get process (%i) status.", pid );
return( SM_NOT_FOUND );
}
while( NULL != fgets( line, sizeof(line), fp ) )
{
if( 0 == strncmp( "se.statistics.block_start", line, 25 ) )
{
sscanf( line, "se.statistics.block_start : %llu.%llu",
&ms, &ns );
status->block_start_ns = (ms * 1000000) + ns;
continue;
}
if( 0 == strncmp( "nr_switches", line, 11 ) )
{
sscanf( line, "nr_switches : %llu", &(status->nr_switches) );
continue;
}
if( 0 == strncmp( "nr_voluntary_switches", line, 21 ) )
{
sscanf( line, "nr_voluntary_switches : %llu",
&(status->nr_voluntary_switches) );
continue;
}
if( 0 == strncmp( "nr_involuntary_switches", line, 23 ) )
{
sscanf( line, "nr_involuntary_switches : %llu",
&(status->nr_involuntary_switches) );
continue;
}
}
fclose( fp );
return( SM_OKAY );
}
// ****************************************************************************
// ****************************************************************************
// Node Statistics - Initialize
// ============================
SmErrorT sm_node_stats_initialize( void )
{
_user_hz = sysconf(_SC_CLK_TCK);
return( SM_OKAY );
}
// ****************************************************************************
// ****************************************************************************
// Node Statistics - Finalize
// ==========================
SmErrorT sm_node_stats_finalize( void )
{
_user_hz = 0;
return( SM_OKAY );
}
// ****************************************************************************