-
Notifications
You must be signed in to change notification settings - Fork 46
Conversation
func initClient(c *collector, endpoint string) error { | ||
dc, err := container.NewDockerClient(endpoint) | ||
if err != nil { | ||
return err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing log
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logs moved to collector
level. This package only returns errors now
@@ -0,0 +1,164 @@ | |||
package collector |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing header
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
header added
fields := strings.Split(txt, " ") | ||
for _, opt := range strings.Split(fields[len(fields)-1], ",") { | ||
if opt == subsystem { | ||
return fields[4], nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
possible index out of range?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would require to /proc/self/mountinfo
change its format. I think it's not needed
} | ||
} | ||
|
||
v, err := strconv.ParseUint(fields[0], 10, 64) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe use "major" instead of "v"?
} | ||
major := v | ||
|
||
v, err = strconv.ParseUint(fields[1], 10, 64) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe use "minor" instead of "v"?
|
||
stats.Cgroups.PidsStats.Current = current | ||
|
||
var max uint64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
max shouldn't be initialized with some default value? What will happen if limit = "max"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is initialized to default value of uint64
which is 0
. For limit equal to zero, it means no limit.
What will happen if limit = "max"?
In this case limit will be set to defult value of max
if err != nil { | ||
return err | ||
} | ||
fmt.Println(pid, isHost, procfs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unnecessary print
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed
http://www.apache.org/licenses/LICENSE-2.0.txt | ||
|
||
|
||
Copyright 2015 Intel Corporation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2017, also in other files? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it was agreed before dates in header files don't have to be updated while introducing changes to already released plugin.
return *policy, nil | ||
} | ||
|
||
type collector struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we move this type definition on the top, after const definition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unexported type. It's quite common code style to keep unexported types below exported ones
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to @kindermoumoute's comment because this is a type which is returned by New()
in line 94, so it will be great to have a definition of this structure after const or variables (which are also unexported but are placed on the top despite this).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New()
now returns interface. collector
type as unexported type stays behind exported API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, that is fine for me.
} // the end of range over ids | ||
} | ||
|
||
if len(metrics) == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be the first thing to test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. It tests if metrics collection process actually collected anything
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My bad, I thought you were catching if len(mts) == 0
. This case should never be allowed by the framework though.
// namespace plugin name | ||
PLUGIN_NAME = "docker" | ||
// version of plugin | ||
PLUGIN_VERSION = 5 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please, increment the version of plugin
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Version increased to 6
return &collector{ | ||
containers: map[string]*container.ContainerData{}, | ||
mounts: map[string]string{}, | ||
}, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After this refactoring, returning error from New() is no longer needed - returned err is always nil. Consider removing error from output and updating go-doc for this function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great
c.conf, err = getDockerConfig(mts[0].Config) | ||
if err != nil { | ||
log.WithFields(log.Fields{ | ||
"plugin": "docker_collector", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding "plugin" as log's field duplicates information added by framework, so this field might be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed logging in whole module
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great
64567f6
to
afff4f3
Compare
} | ||
|
||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Notice that tcp metrics and tcp6 metrics are exactly the same. what is more the way of retrieving these data differs only in the taken path. For this refactored code distinguishing between tcp and tcp is made on defined structures, please consider putting all this code from GetStats in different function with input argument pointing to "net/tcp" or "net/tcp6" depending on a case and use tcpStatsFromProc
directly, so functions TcpStatsFromProc
and Tcp6StatsFromProc
are not longer needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for changing that, now it looks good
|
||
if len(containers) == 0 { | ||
return nil, fmt.Errorf("No docker containers found %d", len(containers)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed that this if
statement does not have sense because this containers
map always contains "root". So, what do you think about moving this statement before adding "root" to this map, but only logging this fact as an "INFO" or "DEBUG", because even there is no docker containers, collection should not fail as it works currently (in a sense by accident).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for moving it up and adding a log, now it looks good
hugetlb_stats/\<size\>/max_usage | uint64 | Max "hugepagesize" hugetlb usage recorded | ||
hugetlb_stats/\<size\>/usage | uint64 | Current usage for "hugepagesize" hugetlb | ||
| | | ||
blkio_stats/io_merged_recursive/\<N\>/value | uint64 | Total number of bios/requests merged into requests belonging from all the descendant cgroups |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marcin-krolik, what's about major
, minor
, and op
for blkio_stats?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the occasion if you could remove metric "network/name" which is no longer exposed (because of including name as a dynamic element), it will be great :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great, but @marcin-krolik - could you make descriptions of these major
, minor
, and op
blkio_stats consistent with the rest? Also, a new line might be put between these points:
1) Hierarchical version of cgroups counter which in addition to the cgroup's own value includes the sum of all hierarchical children's values (2) Each blkio statistic additionally exposes major, minor and op metric
cpu_stats/throttling_data/throttled_time | uint64 | The total time duration for which tasks in a cgroup have been throttled | ||
cpu_stats/cpu_shares | uint64 | contains an integer value that specifies a relative share of CPU time available to the tasks in a cgroup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To keep consistency, consider changing contains an integer value that specifies a relative share of CPU time available to the tasks in a cgroup
to The relative share of CPU time available to the tasks in a cgroup
. Please, take into account the rest of similar cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, thanks
blkio_stats/io_serviced_recursive/\<N\>/value | uint64 | Number of IOs (bio) issued to the disk from all the descendant cgroups | ||
blkio_stats/io_time_recursive/\<N\>/value | uint64 | Disk time allocated to cgroup per device in milliseconds from all the descendant cgroups | ||
blkio_stats/io_wait_time_recursive/\<N\>/value | uint64 | Total amount of time the IOs for this cgroup spent waiting in the scheduler queues for service from all the descendant cgroups | ||
blkio_stats/sectors_recursive/\<N\>/value | uint64 | number of sectors transferred to/from disk from all descendant group | ||
|
||
<sup>(1)</sup> Hierarchical version of cgroups counter which in addition to the cgroup's own value includes the sum of all hierarchical children's values | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you like to update the link to Kernel cgroups documentation, currenty it does not work.
So METRICS.md, line 131 should be changed to:
Read more about cgroups in [Kernel documentation](https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
cgroupfs string | ||
driver string | ||
mounts map[string]string | ||
conf map[string]string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coud you add comments to the rest of stucture's fields as it's done for "containers" and "client"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
} | ||
|
||
for group := range groups { | ||
// during initialization of docker client information about running containers is collectd |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"collectd" probably to collected"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, now it is ok
|
||
if rid != "root" { | ||
if c.cgroupfs == "systemd" { | ||
cpath = filepath.Join(cpath, "system.slice", fmt.Sprintf("docker-%s.scope", c.containers[rid].ID)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about adding here a log with information about the path to cgroups? I suppose it will be helfpul based on issues which were reported in the past.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After changing this fragment of code, there is still lack of logging of cgroup paths - I suppose that based on past issues putting a log there will be very helpful.
// only log error when it was not possible to access metric source | ||
if err != nil { | ||
log.WithFields(log.Fields{ | ||
"plugin": "docker_collector", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
duplication - you do not need "plugin": "docker_collector" in logs, because Snap's framework will add that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great
@@ -367,38 +369,10 @@ func TestCollectMetrics(t *testing.T) { | |||
}) | |||
}) | |||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you like to add tests covering cases for filesystem metrics and alsonew ones (hugetlb, blkio and cpuset statistics)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it could be delivered in separate PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, that works for me
c.driver = drv | ||
|
||
log.WithFields(log.Fields{ | ||
"plugin": "docker_collector", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This field "plugin": "docker_collector"
might be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, now it looks great
|
||
func getDockerConfig(cfg plugin.Config) (map[string]string, error) { | ||
config := make(map[string]string) | ||
values := []string{"endpoint", "procfs"} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make sense to declare strings "endpoint" and " procfs" as a constant? Also, if this getDockerConfig
function is added, maybe checking all required configs will be better and then return combined error or []error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These strings are used only once, I don't see any point in adding them as constants.
values := []string{"endpoint", "procfs"} | ||
var err error | ||
for _, v := range values { | ||
config[v], err = getStringFromConfig(cfg, v) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain why cfg.GetString(key)
is not called directly, but a new function getStringFromConfig
was used for do it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be. Changed to direct call
} | ||
|
||
op := "" | ||
valueField := 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Light suggestion - consider renaming valueField
to indexOfFieldValue
or sth similar that clearly suggest that this is an index, not a value itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed to index
} | ||
|
||
func getCFQStats(path string, stats *container.Statistics) error { | ||
var blkioStats []container.BlkioStatEntry |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Light suggestion - consider renaming blkioStats
to blkioStatEntry
to highlight that this is only a part of blkio stats, of course up to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are single entries, and each entry is blkio statistic, quite descriptive. I don't see the need to change that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.sectors_recursive")); err != nil { | ||
return err | ||
} | ||
stats.Cgroups.BlkioStats.SectorsRecursive = blkioStats |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider changing this statement:
if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.sectors_recursive")); err != nil {
return err
}
stats.Cgroups.BlkioStats.SectorsRecursive = blkioStats
to
if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.sectors_recursive")); err == nil {
stats.Cgroups.BlkioStats.SectorsRecursive = blkioStats
} else {
errs=append(errs, err)
}
and returning []error with error messages from all called getBlkioStat
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With current implementation it fails early with first error. What would be an advantage of your approach?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main advantage of this approach is informing a user about all blkiostats errors in a first run, but I can agree that for this case it does not matter so much. However, this is really helpful in such cases like checking if config options are correct - that allows avoiding many runs with fails.
So, it looks ok
if blkioStats, err := getBlkioStat(filepath.Join(path, "blkio.io_serviced_recursive")); err == nil && blkioStats != nil { | ||
return getCFQStats(path, stats) | ||
} | ||
return getStats(path, stats) // Use generic stats as fallback |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you put here (or above functions getCFQStats
and getStats
) what distinguishes them - I mean why, based on on availability of blkio.io_serviced_recursive
, one of them is called, otherwise the second one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is already stated in comment from line 44 // Try to read CFQ stats available on all CFQ enabled kernels first
and then // Use generic stats as fallback
in line 48
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At first glance, these comments were not clear for me, but thanks for explanation. 👍
@@ -200,17 +206,38 @@ func (self *RealFsInfo) GetFsInfoForPath(mountSet map[string]struct{}) ([]Fs, er | |||
} | |||
|
|||
// GetFsStats returns filesystem statistics for a given container | |||
func GetFsStats(container *docker.Container) (map[string]wrapper.FilesystemInterface, error) { | |||
func (du *DiskUsageCollector) GetStats(stats *container.Statistics, opts container.GetStatOpt) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now GetStats()
routine is basing on a constant path to storage mount point, /var/lib/docker
. It might be good idea to discover this path while initializing docker client with call to GetDockerParam("DockerRootDir")
- see Docker API /info
endpoint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. Thanks!
return err | ||
} | ||
|
||
drv, err := dc.GetDockerParam("Driver") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider change it to c.driver, err = dc.GetDockerParam("Driver")
, so it will exactly the same way how it's done above`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
log.WithFields(log.Fields{ | ||
"plugin": "docker_collector", | ||
"block": "initClient", | ||
}).Infof("Docker client initialized with %s and %s drivers", drv, c.cgroupfs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider changing drv
to c.driver
in this info-log message
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
||
// GetStats reads throttling metrics from Cpu Group from cpu.stat | ||
func (cpu *Cpu) GetStats(stats *container.Statistics, opts container.GetStatOpt) error { | ||
path, err := opts.GetStringValue("cgroup_path") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a concern about calling opts.GetStringValue("cgroup_path")
in each of GetStats
functions. Putting cgroup_path
as an input argument instead of opts
might have more sense, so these GetStats function will be delacred in the following way:
func (cpu *Cpu) GetStats(stats *container.Statistics, cgroup_path string) error
func (cpuacct *CpuAcct) GetStats(stats *container.Statistics, cgroup_path string) error
func (cpuShares *CpuShares) GetStats(stats *container.Statistics, cgroup_path container.GetStatOpt) error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed that for network GetStats not only cgroup_path is needed, but also others fields from opts, so please ignore my comment above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will complicate interface. For other groups then cgroups getters other sets of parameters is required. With opts it easier to handle different cases
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, I agree with that
nameArray := strings.Split(st.Name(), "-") | ||
pageSize, err := units.RAMInBytes(nameArray[1]) | ||
if err != nil { | ||
return []string{}, err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return nil, err
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
} | ||
for _, st := range files { | ||
nameArray := strings.Split(st.Name(), "-") | ||
pageSize, err := units.RAMInBytes(nameArray[1]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marcin-krolik, please verify if this nameArray[1] does not cause potential out-of -range error in case when st.Name()
does not contain "-" and splitting returns only one element.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Such situation would require changes in structure of kernel file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
return 0, err | ||
} | ||
|
||
return strconv.ParseUint(strings.Trim(string(raw), "\n"), 10, 64) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider changing strings.Trim(string(raw), "\n")
to strings.TrimSpace(string(raw))
what will remove "\n" and others white spaces
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
|
||
value, err = strconv.ParseUint(fields[1], 10, 64) | ||
if err != nil { | ||
return name, value, err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about adding to error message some info which will be helpful to point which value cannot be parsed to uint, for example:
fmt.Errorf("Cannot parse value for field %s, err=%s", field[0], err.Error())
or maybe put some log- it might be here or in a place where parseEntry
is called.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ParseUint
error already contains such information eg. strconv.ParseUint: parsing "33f": invalid syntax
hugetlbStats.MaxUsage = maxUsage | ||
hugetlbStats.Failcnt = failcnt | ||
|
||
stats.Cgroups.HugetlbStats[pageSize] = hugetlbStats |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small suggestion: consider removing hugetlbStats
var in this case, because it's not really needed. It might be implemented in the following way:
stats.Cgroups.HugetlbStats[pageSize] = container.HugetlbStats{
Usage: usage,
MaxUsage: maxUsage,
Failcnt: failcnt,
}
but up to you - if you prefer leave it as it is now, that's ok for me too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
return err | ||
} | ||
|
||
if val, ok := stats.Cgroups.MemoryStats.Stats["cache"]; ok { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding a comment to explain why stats.Cgroups.MemoryStats.Stats is checked as a first to get cache value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
// MemoryCache implements StatGetter interface | ||
type MemoryCache struct{} | ||
|
||
// GetStats reads memory cache metric from Memory Group from memory.stat |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, verify if this description is really equivalent to how this func works
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is, cache value is taken from memory.stat file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
|
||
var max uint64 | ||
if limit != "max" { | ||
max, err = strconv.ParseUint(strings.Trim(string(limit), "\n"), 10, 64) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using strings.TrimSpace(string(limit))
instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
|
||
// DockerClient holds fsouza go-dockerclient instance ready for communication with the server endpoint `unix:///var/run/docker.sock`, | ||
// cache instance which is used to store output from docker container inspect (to avoid execute inspect request multiply times, it is called only once per container) | ||
// and diskUsageCollector which is responsible for collecting container disk usage (based on `du -u` command) in the background |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please check if this comment is up to date - I noticed that diskUsageCollector
is no longer in DockerClient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
return info, nil | ||
} | ||
|
||
// GetDockerParam returns given parameter value fro running docker engine |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fro
should be from
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
|
||
// GetDockerParam returns given parameter value fro running docker engine | ||
func (dc *DockerClient) GetDockerParam(param string) (string, error) { | ||
env, err := dc.cl.Info() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about changing it to GetDockerParams and allowing to make a request for a few params, so dc.cl.Info()
will be executed only once. Does it have a sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After change, it looks great
|
||
for scanner.Scan() { | ||
txt := scanner.Text() | ||
fields := strings.Split(txt, " ") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small suggestion - consider using here strings.Fields(txt)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
scanner := bufio.NewScanner(f) | ||
for scanner.Scan() { | ||
txt := scanner.Text() | ||
fields := strings.Split(txt, " ") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small suggestion - consider using here strings.Fields(txt)
@@ -52,11 +54,12 @@ type RealFsInfo struct { | |||
labels map[string]string | |||
} | |||
|
|||
var collector DiskUsageCollector | |||
//var collector DiskUsageCollector | |||
|
|||
type DiskUsageCollector struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider re-use here the comment from client.go#L5 about DiskUsageCollector
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
"module": "network", | ||
"block": "GetStats", | ||
}).Errorf("Unknown tcp stats file %s", tcp.StatsFile) | ||
return err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here a new error should be created and returned, consider put here return fmt.Errorf("Unknown tcp stats file %s", tcp.StatsFile")
. At the moment it looks like the last err's value is returned what means "nil".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
return val.(int), nil | ||
} | ||
|
||
return 1, fmt.Errorf("could not find value for key %s", key) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does it return 1? Returning 0 seems to be more appropriate, but up to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
|
||
return stats | ||
func (m *MockTcp6) GetStats(stats *container.Statistics, opts container.GetStatOpt) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mocking for Tcp6 might be removed after TCP6 structure is no longer used
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
func (opt GetStatOpt) GetStringValue(key string) (string, error) { | ||
val, exists := opt[key] | ||
if exists { | ||
return val.(string), nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding checking the result of type assertion. It might look like below:
func (opt GetStatOpt)getStringValue(key string)(string, error) {
if val, exists := opt[key]; exists {
if valStr, ok := val.(string); ok {
return valStr, nil
}
return "", fmt.Errorf("Value for key `%s` is expected to be string, but it isn't", key)
}
return "", fmt.Errorf("Cannot find value for key `%s`", key)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check added
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
10c63e1
to
40c85d5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
03b56f9
to
571b736
Compare
1bc4589
to
013199d
Compare
Fixes #21, #34, #56
Summary of changes:
openlibcontainers/runc
TODO:
container/cgroupfs
package