collectd
简介
collectd是一个守护(daemon)进程,用来定期收集系统和应用程序的性能指标,同时提供了以不同的方式来存储这些指标值的机制。
collectd从各种来源收集指标,例如 操作系统,应用程序,日志文件和外部设备,并存储此信息或通过网络使其可用。 这些统计数据可用于监控系统、查找性能瓶颈(即性能分析)并预测未来的系统负载(即容量规划)等。
优点
- 它完全是由C语言编写,故性能很高,可移植性好,它允许运行在系统没有脚本语言支持或者cron daemon的系统上,比如嵌入式系统。同时,它包含优化以及处理成百上千种数据集的新特性。
- collectd包含有超过100多种插件。同时,collectd提供强大的网络特性,并且它能以多种方式进行扩充。
缺点
- 它本身不能生成图形。虽然它能写RRD文件,但是它不能从这些文件生成图形。
- 监控功能只能进行简单的门阀检测。
collectd官方文档地址https://collectd.org/index.shtml
collectd wiki地址https://collectd.org/wiki/index.php/Main_Page
下载、编译、安装
wget https://storage.googleapis.com/collectd-tarballs/collectd-5.7.2.tar.bz2
tar xf collectd-5.7.2.tar.bz2
cd collectd-5.7.2
./configure #编译
也可以在后面加入一些其他可选的选项如:
--prefix=/usr --sysconfdir=/etc -localstatedir=/var --libdir=/usr/lib --mandir=/usr/share/man --enable-all-plugins
make all install #安装
或者
直接执行命令进行安装
sudo apt-get install collectd
配置文件目录:
/etc/collectd/collectd.conf
启动文件目录:
/etc/init.d/collectd
日志文件目录:
/var/log/syslog
数据存储目录:
/var/lib/collectd/rrd/
若监控集群,则每台服务器都需要下载安装collectd并进行相应的配置。
配置
sudo vim /opt/collectd/etc/collectd.conf
需要监控系统什么项就开启相应的插件,一般有cpu,memory,processes,load,interface,disk,swap等。
一般只需修改network插件这一项:
网络插件可以将数据发送到collectd的远程实例中(例如:数据库,csv文件或缓存等介质中),或者接收从远程服务端发来的数据。
LoadPlugin network #去掉#就表示载入该插件
# # client setup:
Server "10.24.106.1" "25826" #该地址和端口是接收数据的服务器的地址和端口,例如:安装数据库(influxdb等)的服务器的地址和端口
# #若需传输加密数据,就配置这一小块部分
# SecurityLevel Encrypt
# Username "user"
# Password "secret"
# Interface "eth0"
# ResolveInterval 14400
#
# TimeToLive 128
#
# # server setup:
# Listen "ff18::efc0:4a42" "25826" #如配置这一部分,表示接收从其他collectd实例中发来的数据
#
# SecurityLevel Sign
# AuthFile "/etc/collectd/passwd"
# Interface "eth0"
#
# MaxPacketSize 1452
#
# # proxy setup (client and server as above):
# Forward true
#
# # statistics about the network plugin itself
# ReportStats false
#
# # "garbage collection"
# CacheFlush 1800
启动
执行命令sudo /etc/init.d/collectd start
或者 systemctl start collectd
并设置开机启动systemctl enable collectd
查看数据
若开启了rrdtool插件就可在/var/lib/collectd/rrd/
目录下看到相应的统计数据。
通过下面命令可以查看具体数据:
rrdtool fetch *.rrd AVERAGE
*.rrd表示任何以.rrd结尾的文件,rrdtool命令更详细的用法可以自行百度。
可以看到第一列为timestamp(时间戳),可以通过命令date -d @timestamp
把timestamp(以秒为单位)转换为和date
命令显示的相同的的时间格式,命令date +%s
用时间戳的形式表示时间。
主要插件介绍
- Plugin: CPU
可视化显示
指标释义
jiffies: 是一个单位,jiffies是内核中的一个全局变量,用来记录自系统启动一来产生的节拍数,在linux中,一个节拍大致可理解为操作系统进程调度的最小时间单位,不同linux内核可能值有不同,通常在1ms到10ms之间
user: 从系统启动开始累计到当前时刻,处于用户态的运行时间,不包含 nice值为负的进程。
nice: 从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间。
idle: 从系统启动开始累计到当前时刻,除I/O等待时间以外的其它等待时间。
wait-io: 从系统启动开始累计到当前时刻,I/O操作等待时间。
system: 从系统启动开始累计到当前时刻,处于内核态的运行时间。
softIRQ: 从系统启动开始累计到当前时刻,软中断时间。
IRQ:从系统启动开始累计到当前时刻,硬中断时间。
steal:运行在虚拟环境中其他操作系统所花费的时间。
- Plugin: interface
Interface插件收集关于流量(每秒八位字节),每秒的数据包和接口错误(一秒钟内)的信息。
rxpck/s:每秒钟接收的数据包
txpck/s:每秒钟发送的数据包
rxbyt/s:每秒钟接收的字节数
txbyt/s:每秒钟发送的字节数
- Plugin: processes
- Plugin: memory 收集系统的物理内存利用率
- Plugin: swap 收集swap空间的使用情况
Plugin: df 统计文件系统的使用信息
Plugin: irq 收集操作系统处理中断的数量
Plugin: disk 收集磁盘的性能统计信息
Plugin: load 收集系统负载信息,定义为队列中可运行任务的数量
在Linux中,系统相关数据可以通过命令cd /proc/
在该目录下查看。
自定义插件
python插件将python解释器嵌入到collectd中并且提供了collectd插件系统接口。
插件配置
LoadPlugin python #默认是关闭的,需要去掉#,载入插件
ModulePath "/path/to/your/python/modules" #可以使用多行ModulePath来导入更多的目录
LogTraces true #如果python脚本报错,是否要记录下来。如果设置为true,它将记录下和在python解释器中一样的所有报错。
Interactive true #这个选项将使module打开一个python解释器在终端显示读与写。
Import "spam" #导入spam这个模块
spam "wonderful" "lovely" #配置该Python模块所需要的参数
collectd提供了基本的方法用于注册自己插件的配置加载函数、数据读取函数和数据写函数。
函数 | 描述 |
---|---|
collectd.register_config() | 该方法实现对模块参数的读取 |
collectd.register_read() | 该方法进行数据的采集 |
collectd.register_write() | 该方法用于对数据的采集进行写处理 |
以上三个方法的参数中最重要的都是一个回调函数,分别用于读取配置文件、采集监控数据和处理获取的监控数据。
Python模块伪代码
Any Python module will start similar to:
import collectd
A very simple read function might look like:
def read(data=None): #定义一个read回调函数
```
实现对指标的数据采集
collectd有自己的类型,都存储在Types.db中
```
vl = collectd.Values(type='gauge') #gauge是collectd的内建数据类型,也可以在types.db中自定义数据类型
vl.plugin='python.spam'
vl.values = [random.random() * 100]
vl.dispatch() #发送获取的values,给write插件读取。
A very simple write function might look like:
def write(vl, data=None): #定义一个write回调函数
```
将获取到的数据按照要求插入自己的数据存储中
在这里直接打印输出
```
for i in vl.values:
print "%s (%s): %f" % (vl.plugin, vl.type, i)
To register those functions with collectd:
collectd.register_read(read) #注册回调函数read
collectd.register_write(write) #注册回调函数write
实例分析
首先在collectd.conf文件中配置Python插件如下:
ModulePath "/opt/collectd/lib/collectd"
Import "cpu_usage_plugin"
Interval 30
PluginName "cpu_usage"
HostName "demo_host"
Verbose false
模块cpu_usage_plugin.py内容如下:
#!/usr/bin/env python
import subprocess
import traceback
def get_cpu_usage():
cmd = "grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage}'"
result = run(cmd)
for line in result:
try:
usage = float(line)
return usage
except:
raise Exception("Failed to parse cpu usage")
def run(cmd):
try:
result = []
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, close_fds=True)
(stdout, stderr) = proc.communicate()
output = stdout.split("\n")
for line in output:
if line == '':
continue
result.append(line)
return result
except Exception as err:
raise Exception("failed to execute command: %s, reason: %s" % (' '.join(cmd), err.message))
class CPUStatMon(object):
def __init__(self):
self.plugin_name = "cpu_stat"
self.interval = 30
self.hostname = None
self.verbose_logging = False
def log_verbose(self, msg):
if not self.verbose_logging:
return
collectd.info('%s plugin [verbose]: %s' % (self.plugin_name, msg))
def configure_callback(self, conf):
for node in conf.children:
val = str(node.values[0])
if node.key == "HostName":
self.hostname = val
elif node.key == 'Interval':
self.interval = int(float(val))
elif node.key == 'Verbose':
self.verbose_logging = val in ['True', 'true']
elif node.key == 'PluginName':
self.plugin_name = val
else:
collectd.warning('[plugin] %s: unknown config key: %s' % (self.plugin_name, node.key))
def dispatch_value(self, plugin, host, type, type_instance, value):
self.log_verbose("Dispatching value plugin=%s, host=%s, type=%s, type_instance=%s, value=%s" %(plugin, host, type, type_instance, str(value)))
val = collectd.Values(type=type)
val.plugin = plugin
val.host = host
val.type_instance = type_instance
val.interval = self.interval
val.values = [value]
val.dispatch()
self.log_verbose("Dispatched value plugin=%s, host=%s, type=%s, type_instance=%s, value=%s" %(plugin, host, type, type_instance, str(value)))
def read_callback(self):
try:
usage = get_cpu_usage()
type = 'cpu_usage_percent'
type_instance = "used"
value = usage
self.dispatch_value(self.plugin_name, self.hostname, type, type_instance, value)
except Exception as exp:
self.log_verbose(traceback.print_exc())
self.log_verbose("plugin %s run into exception" % (self.plugin_name))
self.log_verbose(exp.message)
def write_callback(self,val):
pass #可以把数据写进数据库或文件中。
if __name__ == '__main__':
result = get_cpu_usage()
print result
else:
import collectd
cpu_status_mon = CPUStatMon()
collectd.register_config(cpu_status_mon.configure_callback)
collectd.register_read(cpu_status_mon.read_callback)
collectd.register_write(cpu_status_mon.write_callback)
END