Commit 411e248c authored by marcintao's avatar marcintao Committed by GitHub

Merge pull request #16 from obourdon/dynamic_metrics

Dynamic metrics
parents bc71735e 9d8c345e
......@@ -44,7 +44,7 @@ const (
// PluginName df collector plugin name
PluginName = "df"
// Version of plugin
Version = 2
Version = 3
nsVendor = "intel"
nsClass = "procfs"
......@@ -83,6 +83,7 @@ var (
"debugfs",
"securityfs",
"devpts",
"mqueue",
}
)
......@@ -106,24 +107,15 @@ func (p *dfCollector) setProcPath(cfg interface{}) error {
// GetMetricTypes returns list of available metric types
// It returns error in case retrieval was not successful
func (p *dfCollector) GetMetricTypes(cfg plugin.ConfigType) ([]plugin.MetricType, error) {
err := p.setProcPath(cfg)
if err != nil {
return nil, err
}
mts := []plugin.MetricType{}
dfms, err := p.stats.collect(p.proc_path)
if err != nil {
return mts, fmt.Errorf(fmt.Sprintf("Unable to get available metrics from df: %s", err))
for _, kind := range metricsKind {
mts = append(mts, plugin.MetricType{
Namespace_: core.NewNamespace(namespacePrefix...).
AddDynamicElement("filesystem", "name of filesystem").
AddStaticElement(kind),
Description_: "dynamic filesystem metric: " + kind,
})
}
for _, dfm := range dfms {
for _, kind := range metricsKind {
mt := plugin.MetricType{Namespace_: core.NewNamespace(makeNamespace(dfm, kind)...)}
mts = append(mts, mt)
}
}
return mts, nil
}
......@@ -136,63 +128,87 @@ func (p *dfCollector) CollectMetrics(mts []plugin.MetricType) ([]plugin.MetricTy
}
metrics := []plugin.MetricType{}
curTime := time.Now()
dfms, err := p.stats.collect(p.proc_path)
if err != nil {
return metrics, fmt.Errorf(fmt.Sprintf("Unable to collect metrics from df: %s", err))
}
for _, mt := range mts {
namespace := mt.Namespace().Strings()
if len(namespace) < 5 {
return nil, fmt.Errorf("Wrong namespace length %d", len(namespace))
for _, m := range mts {
ns := m.Namespace()
lns := len(ns)
if lns < 5 {
return nil, fmt.Errorf("Wrong namespace length %d", lns)
}
for _, dfm := range dfms {
if validateMetric(namespace[3:], dfm) {
kind := namespace[4]
if ns[lns-2].Value == "*" {
for _, dfm := range dfms {
kind := ns[lns-1].Value
ns1 := core.NewNamespace(createNamespace(dfm.MountPoint, kind)...)
ns1[len(ns1)-2].Name = ns[lns-2].Name
metric := plugin.MetricType{
Timestamp_: time.Now(),
Namespace_: mt.Namespace(),
}
switch kind {
case "space_free":
metric.Data_ = dfm.Available
case "space_reserved":
metric.Data_ = dfm.Blocks - (dfm.Used + dfm.Available)
case "space_used":
metric.Data_ = dfm.Used
case "space_percent_free":
metric.Data_ = 100 * float64(dfm.Available) / float64(dfm.Blocks)
case "space_percent_reserved":
metric.Data_ = 100 * float64(dfm.Blocks-(dfm.Used+dfm.Available)) / float64(dfm.Blocks)
case "space_percent_used":
metric.Data_ = 100 * float64(dfm.Used) / float64(dfm.Blocks)
case "device_name":
metric.Data_ = dfm.Filesystem
case "device_type":
metric.Data_ = dfm.FsType
case "inodes_free":
metric.Data_ = dfm.IFree
case "inodes_reserved":
metric.Data_ = dfm.Inodes - (dfm.IUsed + dfm.IFree)
case "inodes_used":
metric.Data_ = dfm.IUsed
case "inodes_percent_free":
metric.Data_ = 100 * float64(dfm.IFree) / float64(dfm.Inodes)
case "inodes_percent_reserved":
metric.Data_ = 100 * float64(dfm.Inodes-(dfm.IUsed+dfm.IFree)) / float64(dfm.Inodes)
case "inodes_percent_used":
metric.Data_ = 100 * float64(dfm.IUsed) / float64(dfm.Inodes)
Timestamp_: curTime,
Namespace_: ns1,
}
fillMetric(kind, dfm, &metric)
metrics = append(metrics, metric)
}
} else {
for _, dfm := range dfms {
if ns[lns-2].Value == dfm.MountPoint {
metric := plugin.MetricType{
Timestamp_: curTime,
Namespace_: ns,
}
kind := ns[lns-1].Value
fillMetric(kind, dfm, &metric)
metrics = append(metrics, metric)
}
}
}
}
return metrics, nil
}
// Function to fill metric with proper (computed) value
func fillMetric(kind string, dfm dfMetric, metric *plugin.MetricType) {
switch kind {
case "space_free":
metric.Data_ = dfm.Available
case "space_reserved":
metric.Data_ = dfm.Blocks - (dfm.Used + dfm.Available)
case "space_used":
metric.Data_ = dfm.Used
case "space_percent_free":
metric.Data_ = 100 * float64(dfm.Available) / float64(dfm.Blocks)
case "space_percent_reserved":
metric.Data_ = 100 * float64(dfm.Blocks-(dfm.Used+dfm.Available)) / float64(dfm.Blocks)
case "space_percent_used":
metric.Data_ = 100 * float64(dfm.Used) / float64(dfm.Blocks)
case "device_name":
metric.Data_ = dfm.Filesystem
case "device_type":
metric.Data_ = dfm.FsType
case "inodes_free":
metric.Data_ = dfm.IFree
case "inodes_reserved":
metric.Data_ = dfm.Inodes - (dfm.IUsed + dfm.IFree)
case "inodes_used":
metric.Data_ = dfm.IUsed
case "inodes_percent_free":
metric.Data_ = 100 * float64(dfm.IFree) / float64(dfm.Inodes)
case "inodes_percent_reserved":
metric.Data_ = 100 * float64(dfm.Inodes-(dfm.IUsed+dfm.IFree)) / float64(dfm.Inodes)
case "inodes_percent_used":
metric.Data_ = 100 * float64(dfm.IUsed) / float64(dfm.Inodes)
}
}
// createNamespace returns namespace slice of strings composed from: vendor, class, type and components of metric name
func createNamespace(elt string, name string) []string {
var suffix = []string{elt, name}
return append(namespacePrefix, suffix...)
}
// GetConfigPolicy returns config policy
// It returns error in case retrieval was not successful
func (p *dfCollector) GetConfigPolicy() (*cpolicy.ConfigPolicy, error) {
......@@ -238,6 +254,7 @@ type dfMetric struct {
Capacity float64
FsType string
MountPoint string
UnchangedMountPoint string
Inodes, IUsed, IFree uint64
IUse float64
}
......@@ -251,8 +268,10 @@ type dfStats struct{}
func (dfs *dfStats) collect(procPath string) ([]dfMetric, error) {
dfms := []dfMetric{}
fh, err := os.Open(path.Join(procPath, "1", "mountinfo"))
cpath := path.Join(procPath, "1", "mountinfo")
fh, err := os.Open(cpath)
if err != nil {
log.Error(fmt.Sprintf("Got error %#v", err))
return nil, err
}
defer fh.Close()
......@@ -278,6 +297,7 @@ func (dfs *dfStats) collect(procPath string) ([]dfMetric, error) {
var dfm dfMetric
dfm.Filesystem = rightFields[1]
dfm.FsType = rightFields[0]
dfm.UnchangedMountPoint = leftFields[4]
if leftFields[4] == "/" {
dfm.MountPoint = "rootfs"
} else {
......
......@@ -75,7 +75,6 @@ func (dfp *DfPluginSuite) SetupSuite() {
func (dfp *DfPluginSuite) TestGetMetricTypes() {
Convey("Given df plugin is initialized", dfp.T(), func() {
//dfPlg := NewDfCollector()
dfPlg := dfCollector{
stats: dfp.mockCollector,
}
......@@ -117,7 +116,6 @@ func (dfp *DfPluginSuite) TestGetMetricTypes() {
func (dfp *DfPluginSuite) TestCollectMetrics() {
Convey("Given df plugin is initialized", dfp.T(), func() {
//dfPlg := NewDfCollector()
dfPlg := dfCollector{
stats: dfp.mockCollector,
}
......@@ -135,35 +133,21 @@ func (dfp *DfPluginSuite) TestCollectMetrics() {
for _, m := range mts {
ns = append(ns, m.Namespace().String())
}
So(len(mts), ShouldEqual, 28)
So(ns, ShouldContain, "/intel/procfs/filesystem/rootfs/space_free")
So(ns, ShouldContain, "/intel/procfs/filesystem/rootfs/space_reserved")
So(ns, ShouldContain, "/intel/procfs/filesystem/rootfs/space_used")
So(ns, ShouldContain, "/intel/procfs/filesystem/rootfs/space_percent_free")
So(ns, ShouldContain, "/intel/procfs/filesystem/rootfs/space_percent_reserved")
So(ns, ShouldContain, "/intel/procfs/filesystem/rootfs/space_percent_used")
So(ns, ShouldContain, "/intel/procfs/filesystem/rootfs/inodes_free")
So(ns, ShouldContain, "/intel/procfs/filesystem/rootfs/inodes_reserved")
So(ns, ShouldContain, "/intel/procfs/filesystem/rootfs/inodes_used")
So(ns, ShouldContain, "/intel/procfs/filesystem/rootfs/inodes_percent_free")
So(ns, ShouldContain, "/intel/procfs/filesystem/rootfs/inodes_percent_reserved")
So(ns, ShouldContain, "/intel/procfs/filesystem/rootfs/inodes_percent_used")
So(ns, ShouldContain, "/intel/procfs/filesystem/rootfs/device_name")
So(ns, ShouldContain, "/intel/procfs/filesystem/rootfs/device_type")
So(ns, ShouldContain, "/intel/procfs/filesystem/big/space_free")
So(ns, ShouldContain, "/intel/procfs/filesystem/big/space_reserved")
So(ns, ShouldContain, "/intel/procfs/filesystem/big/space_used")
So(ns, ShouldContain, "/intel/procfs/filesystem/big/space_percent_free")
So(ns, ShouldContain, "/intel/procfs/filesystem/big/space_percent_reserved")
So(ns, ShouldContain, "/intel/procfs/filesystem/big/space_percent_used")
So(ns, ShouldContain, "/intel/procfs/filesystem/big/inodes_free")
So(ns, ShouldContain, "/intel/procfs/filesystem/big/inodes_reserved")
So(ns, ShouldContain, "/intel/procfs/filesystem/big/inodes_used")
So(ns, ShouldContain, "/intel/procfs/filesystem/big/inodes_percent_free")
So(ns, ShouldContain, "/intel/procfs/filesystem/big/inodes_percent_reserved")
So(ns, ShouldContain, "/intel/procfs/filesystem/big/inodes_percent_used")
So(ns, ShouldContain, "/intel/procfs/filesystem/big/device_name")
So(ns, ShouldContain, "/intel/procfs/filesystem/big/device_type")
So(len(mts), ShouldEqual, 14)
So(ns, ShouldContain, "/intel/procfs/filesystem/*/space_free")
So(ns, ShouldContain, "/intel/procfs/filesystem/*/space_reserved")
So(ns, ShouldContain, "/intel/procfs/filesystem/*/space_used")
So(ns, ShouldContain, "/intel/procfs/filesystem/*/space_percent_free")
So(ns, ShouldContain, "/intel/procfs/filesystem/*/space_percent_reserved")
So(ns, ShouldContain, "/intel/procfs/filesystem/*/space_percent_used")
So(ns, ShouldContain, "/intel/procfs/filesystem/*/inodes_free")
So(ns, ShouldContain, "/intel/procfs/filesystem/*/inodes_reserved")
So(ns, ShouldContain, "/intel/procfs/filesystem/*/inodes_used")
So(ns, ShouldContain, "/intel/procfs/filesystem/*/inodes_percent_free")
So(ns, ShouldContain, "/intel/procfs/filesystem/*/inodes_percent_reserved")
So(ns, ShouldContain, "/intel/procfs/filesystem/*/inodes_percent_used")
So(ns, ShouldContain, "/intel/procfs/filesystem/*/device_name")
So(ns, ShouldContain, "/intel/procfs/filesystem/*/device_type")
})
})
})
......
......@@ -7,12 +7,12 @@
"workflow": {
"collect": {
"metrics": {
"/intel/procfs/filesystem/rootfs/space_free": {},
"/intel/procfs/filesystem/rootfs/space_reserved": {},
"/intel/procfs/filesystem/rootfs/inodes_percent_free": {},
"/intel/procfs/filesystem/rootfs/inodes_percent_used": {},
"/intel/procfs/filesystem/rootfs/device_name": {},
"/intel/procfs/filesystem/sys_fs_cgroup/inodes_used": {}
"/intel/procfs/filesystem/*/space_free": {},
"/intel/procfs/filesystem/*/space_reserved": {},
"/intel/procfs/filesystem/*/inodes_percent_free": {},
"/intel/procfs/filesystem/*/inodes_percent_used": {},
"/intel/procfs/filesystem/*/device_name": {},
"/intel/procfs/filesystem/*/inodes_used": {}
},
"config": {
"/intel/procfs/filesystem": {
......@@ -22,7 +22,7 @@
"process": null,
"publish": [
{
"plugin_name": "file",
"plugin_name": "mock-file",
"config": {
"file": "/tmp/published_df.log"
}
......
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 to comment