New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Perfmon metricset output format option #3976
Perfmon metricset output format option #3976
Conversation
Jenkins standing by to test this. If you aren't a maintainer, you can ignore this comment. Someone with commit access, please review this and clear it for Jenkins to run. |
1 similar comment
Jenkins standing by to test this. If you aren't a maintainer, you can ignore this comment. Someone with commit access, please review this and clear it for Jenkins to run. |
// PdhFmtLong returns data as a long integer. | ||
PdhFmtLong = C.PDH_FMT_LONG | ||
PdhFmtLong PdhCounterFormat = C.PDH_FMT_LONG |
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.
Looks like other formatters below also should have the same PdhCounterFormat
type applied.
}, nil | ||
} | ||
|
||
func (q *Query) AddCounter(counterPath string) error { | ||
func (q *Query) AddCounter(counterPath string, format string) 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.
From an API perspective I would not allow a free-form string for format
. I would declare an enum for the allowed format types. And then inside of the function reject unknown format
enum values with an error.
@@ -3,15 +3,20 @@ | |||
package perfmon | |||
|
|||
import ( | |||
"strings" | |||
|
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.
Remove the newline between stdlib imports and sort them.
@@ -37,6 +42,18 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { | |||
return nil, err | |||
} | |||
|
|||
for _, value := range config.CounterConfig { | |||
form := strings.ToLower(value.Format) |
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 a switch here.
switch strings.ToLower(value.Format) {
case "":
// use float
case "float", "uint32", "uint64":
default:
// error
}
@@ -8,6 +8,8 @@ performance counters. | |||
|
|||
You must configure queries for the Windows performance counters that you wish | |||
to collect. The example below collects processor time and disk writes. | |||
With `format` you can set the output format for an specific counter. Possible values are |
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 it makes sense to expose the intricacies of uint32 vs uint64 because JSON doesn't make any distinction between these types. Maybe just offer float
and long
(and long
uses uint64
under the hood).
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.
typo: should say "for a specific counter"
switch format { | ||
case "float": | ||
q.counters[counterPath].format = PdhFmtDouble | ||
case "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.
Shouldn't these actually be called int64
and int32
? I didn't see any mention that the values are unsigned in the docs (possibly I missed it). And you do cast to int64
and int32
later in the code.
@@ -18,7 +18,7 @@ func TestQuery(t *testing.T) { | |||
} | |||
defer q.Close() | |||
|
|||
err = q.AddCounter(processorTimeCounter) | |||
err = q.AddCounter(processorTimeCounter, "float") |
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.
We need some additional test cases for the new formats.
@@ -118,20 +133,28 @@ func (q *Query) Execute() error { | |||
} | |||
|
|||
type Value struct { | |||
Num float64 | |||
Num interface{} |
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.
From a user perspective I'm not really liking that I have to type assert Num
to get interpret the value. Maybe in a separate PR we could improve the API for Query
. One option would be to have separate FloatValues()
and Int64Values()
methods that return map[string]FloatValue
and map[string]Int64Value
respectively.
Hi @andrewkroh. I have changed the format option you proposed. Now there are only |
jenkins, test it |
type Format int | ||
|
||
const ( | ||
FLOAT Format = iota |
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 would probably call these FloatFormat
and LongFormat
since the names are rather generic. Constants should use upper-camel-case (I usually ignore this rule for constants brought over from C code).
There is a merge conflict that needs resolved. |
@@ -8,6 +8,8 @@ performance counters. | |||
|
|||
You must configure queries for the Windows performance counters that you wish | |||
to collect. The example below collects processor time and disk writes. | |||
With `format` you can set the output format for an specific counter. Possible values are | |||
`float`, and `long`. If nothing is selected the default value is `float`. |
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.
Minor: should say float
and long
(no comma)
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.
@dedemorton, many thanks!!
@@ -8,6 +8,8 @@ performance counters. | |||
|
|||
You must configure queries for the Windows performance counters that you wish | |||
to collect. The example below collects processor time and disk writes. | |||
With `format` you can set the output format for an specific counter. Possible values are |
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.
typo: should say "for a specific counter"
case "float", "long": | ||
default: | ||
err := fmt.Errorf("format '%s' for counter '%s' are not valid", value.Format, value.Alias) | ||
return nil, errors.Wrap(err, "initialization failed") |
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.
You could use errors.Errorf()
here.
This PR adds the a new config option
format
for the perfmon metricset. Possible values arefloat
,uint64
anduint32
. The default value isfloat
. My first approach was to set the format for all counters. But i think to define it on counter level gives the user more flexibility.