-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add support for diskio name templates & udev tags
- Loading branch information
Showing
5 changed files
with
261 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package system | ||
|
||
import ( | ||
"bufio" | ||
"fmt" | ||
"os" | ||
"strings" | ||
"syscall" | ||
) | ||
|
||
type diskInfoCache struct { | ||
stat syscall.Stat_t | ||
values map[string]string | ||
} | ||
|
||
var udevPath = "/run/udev/data" | ||
|
||
func (s *DiskIOStats) diskInfo(devName string) (map[string]string, error) { | ||
fi, err := os.Stat("/dev/" + devName) | ||
if err != nil { | ||
return nil, err | ||
} | ||
stat, ok := fi.Sys().(*syscall.Stat_t) | ||
if !ok { | ||
return nil, nil | ||
} | ||
|
||
if s.infoCache == nil { | ||
s.infoCache = map[string]diskInfoCache{} | ||
} | ||
ic, ok := s.infoCache[devName] | ||
if ok { | ||
return ic.values, nil | ||
} else { | ||
ic = diskInfoCache{ | ||
stat: *stat, | ||
values: map[string]string{}, | ||
} | ||
s.infoCache[devName] = ic | ||
} | ||
di := ic.values | ||
|
||
major := stat.Rdev >> 8 & 0xff | ||
minor := stat.Rdev & 0xff | ||
|
||
f, err := os.Open(fmt.Sprintf("%s/b%d:%d", udevPath, major, minor)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer f.Close() | ||
scnr := bufio.NewScanner(f) | ||
|
||
for scnr.Scan() { | ||
l := scnr.Text() | ||
if len(l) < 4 || l[:2] != "E:" { | ||
continue | ||
} | ||
kv := strings.SplitN(l[2:], "=", 2) | ||
if len(kv) < 2 { | ||
continue | ||
} | ||
di[kv[0]] = kv[1] | ||
} | ||
|
||
return di, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// +build linux | ||
|
||
package system | ||
|
||
import ( | ||
"io/ioutil" | ||
"os" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
var nullDiskInfo = []byte(` | ||
E:MY_PARAM_1=myval1 | ||
E:MY_PARAM_2=myval2 | ||
`) | ||
|
||
// setupNullDisk sets up fake udev info as if /dev/null were a disk. | ||
func setupNullDisk(t *testing.T) func() error { | ||
td, err := ioutil.TempDir("", ".telegraf.TestDiskInfo") | ||
require.NoError(t, err) | ||
|
||
origUdevPath := udevPath | ||
|
||
cleanFunc := func() error { | ||
udevPath = origUdevPath | ||
return os.RemoveAll(td) | ||
} | ||
|
||
udevPath = td | ||
err = ioutil.WriteFile(td+"/b1:3", nullDiskInfo, 0644) // 1:3 is the 'null' device | ||
if err != nil { | ||
cleanFunc() | ||
t.Fatal(err) | ||
} | ||
|
||
return cleanFunc | ||
} | ||
|
||
func TestDiskInfo(t *testing.T) { | ||
clean := setupNullDisk(t) | ||
defer clean() | ||
|
||
s := &DiskIOStats{} | ||
di, err := s.diskInfo("null") | ||
require.NoError(t, err) | ||
assert.Equal(t, "myval1", di["MY_PARAM_1"]) | ||
assert.Equal(t, "myval2", di["MY_PARAM_2"]) | ||
|
||
// test that data is cached | ||
err = clean() | ||
require.NoError(t, err) | ||
|
||
di, err = s.diskInfo("null") | ||
require.NoError(t, err) | ||
assert.Equal(t, "myval1", di["MY_PARAM_1"]) | ||
assert.Equal(t, "myval2", di["MY_PARAM_2"]) | ||
|
||
// unfortunately we can't adjust mtime on /dev/null to test cache invalidation | ||
} | ||
|
||
// DiskIOStats.diskName isn't a linux specific function, but dependent | ||
// functions are a no-op on non-Linux. | ||
func TestDiskIOStats_diskName(t *testing.T) { | ||
defer setupNullDisk(t)() | ||
|
||
tests := []struct { | ||
templates []string | ||
expected string | ||
}{ | ||
{[]string{"$MY_PARAM_1"}, "myval1"}, | ||
{[]string{"${MY_PARAM_1}"}, "myval1"}, | ||
{[]string{"x$MY_PARAM_1"}, "xmyval1"}, | ||
{[]string{"x${MY_PARAM_1}x"}, "xmyval1x"}, | ||
{[]string{"$MISSING", "$MY_PARAM_1"}, "myval1"}, | ||
{[]string{"$MY_PARAM_1", "$MY_PARAM_2"}, "myval1"}, | ||
{[]string{"$MISSING"}, "null"}, | ||
{[]string{"$MY_PARAM_1/$MY_PARAM_2"}, "myval1/myval2"}, | ||
{[]string{"$MY_PARAM_2/$MISSING"}, "null"}, | ||
} | ||
|
||
for _, tc := range tests { | ||
s := DiskIOStats{ | ||
NameTemplates: tc.templates, | ||
} | ||
assert.Equal(t, tc.expected, s.diskName("null"), "Templates: %#v", tc.templates) | ||
} | ||
} | ||
|
||
// DiskIOStats.diskTags isn't a linux specific function, but dependent | ||
// functions are a no-op on non-Linux. | ||
func TestDiskIOStats_diskTags(t *testing.T) { | ||
defer setupNullDisk(t)() | ||
|
||
s := &DiskIOStats{ | ||
DeviceTags: []string{"MY_PARAM_2"}, | ||
} | ||
dt := s.diskTags("null") | ||
assert.Equal(t, map[string]string{"MY_PARAM_2": "myval2"}, dt) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// +build !linux | ||
|
||
package system | ||
|
||
type diskInfoCache struct{} | ||
|
||
func (s *DiskIOStats) diskInfo(devName string) (map[string]string, error) { | ||
return nil, nil | ||
} |