-
Notifications
You must be signed in to change notification settings - Fork 107
fix duration vars processing and error handling in cass idx #1141
Conversation
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
I think you forgot ConfigProcess in some of the tools? |
I believe |
idx/cassandra/config.go
Outdated
disableInitialHostLookup bool | ||
} | ||
|
||
const timeUnits = "Valid time units are 'ns', 'us' (or 'µs'), 'ms', 's', 'm', 'h'" |
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.
in a file, please put first global consts and vars, then types followed first by their constructor, then by their methods
both mt-index-cat and mt-whisper-importer-writer call cassandra.ConfigSetup(), allowing the configuration to be altered. neither of them calls cassandra.ConfigProcess()
seems like you're contradicting your other statement where you said ConfigProcess should be called if IdxConfig can be modified. or am I missing something? |
} | ||
updateInterval32 = uint32(updateInterval.Nanoseconds() / int64(time.Second)) |
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 did we remove this here and move it to IdxConfig.Validate()
validation should validate the config. setting this property must not be forgotten, so it should not be in the Validate method (which is optional)
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.
Validate
is not optional, it is called at the beginning of New
. This way updateInterval
is validated before it is attempted to be used in this assignment.
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 but it smells like bad code hygiene and for someone reading the code, that flow is not obvious.
and the question remains, why is this line in validate if it has nothing to do with validation, and why is it removed from New() which seems like a better place to put 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.
Fair enough, I suppose it really doesn't have anything to do with validation itself, other than relying on validation to run before it is assigned. I will move it back to New() and adjust the comments.
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 phone now but if that property is a derivative of the cfg that's set in New it should probably be a field of the index struct not of the config object
When cassandra.New is called it will Validate as ConfigProcess does and fail the same. It would be redundant to call it before cassandra.New, unless there is a specific index setting to validate that has been changed since it was initiated and that would affect the initialization of some other component. I was not very clear in my original reply. For the two tools affected by these changes we should be ok without calling ConfigProcess due to the ordering in their initialization sequences. |
AFAIK, everywhere in the codebase we follow the pattern that all configuration is validated before we start initializing stuff and executing business logic. and I think it's a useful convention that we should consistently apply. if it means validating more then once, so be it. |
} | ||
if cfg.timeout == 0 { | ||
return errors.New("timeout must be greater than 0. " + timeUnits) | ||
} |
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.
all these errors are be misleading when a user entered a non-zero value that didn't parse.
Perhaps reword as "timeout invalid. Must be greater than 0 and parseable with https://golang.org/pkg/time/#ParseDuration" or something
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.
since we use flag.ExitOnError, that should work in theory, but in practice, it doesn't seem to
when I use update-interval = 4H
I get:
metrictank_1_cced215491fa | 2018-11-21 05:58:48.740 [FATAL] cassandra-idx: Config validation error. updateInterval must be greater than 0. Valid time units are 'ns', 'us' (or 'µs'), 'ms', 's', 'm', 'h'
meaning we don't detect parse errors, and just pass the 0 value through. In this case we're lucky that we also do the != 0 check, but we don't do that everywhere.
unfortunately, we already knew this which is why it was brought up before: #944 (comment)
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 are we still using github.com/rakyll/globalconf
? we have our own fixed version github.com/grafana/globalconf
idx/cassandra/config.go
Outdated
func (cfg *IdxConfig) Validate() error { | ||
if cfg.updateInterval == 0 { | ||
return errors.New("updateInterval must be greater than 0. " + timeUnits) | ||
} |
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 can't implement proper validation without stopping supporting a zero value? that seems rather sad.
if we're no longer allowing 0 for this value:
- the help message must be updated
- this is a breaking change and should be made much more explicit. please mention breaking changes clearly in the PR 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.
I just tried out github.com/grafana/globalconf
. We can still support zero values with it.
a3d50d6
to
d9287da
Compare
@@ -182,11 +181,13 @@ func main() { | |||
|
|||
cluster.Init("mt-whisper-importer-writer", gitHash, time.Now(), "http", int(80)) | |||
|
|||
cassandra.ConfigProcess() |
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.
again. config validation (ConfigProcess()) should be before we start initalizing stuff. the sooner we can abort the program the better.
prune-interval = 3h | ||
# synchronize index changes to cassandra. not all your nodes need to do this. | ||
update-cassandra-index = true | ||
#frequency at which we should update flush changes to cassandra. only relevant if update-cassandra-index is true. | ||
#frequency at which we should update flush changes to cassandra. only relevant if update-cassandra-index is true. valid time units are 'ns', 'us' (or 'µs'), 'ms', 's', 'm', 'h'. Setting to '0s' will cause instant updates. |
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.
kindof weird to tell users that they can use all these subsecond units but in New()
round down to a round number of seconds. but it's fine i guess.
we could use https://github.com/raintank/dur instead which accepts units /sec/secs/second/seconds, m/min/mins/minute/minutes, h/hour/hours, d/day/days, w/week/weeks, mon/month/months, y/year/years
but those high units are more than what we need. a side benefit would be though that we don't need to convert to uint32 anymore.
anyway, seems like more hassle than it's worth.
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 are right, that is a little weird. Maybe we should specify that although you can use all of those time units, it will round to 1 second. Also, if the time they specify is less than 1 second that it will treat it like 0, thus causing instant updates.
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 we don't have to do anything. our performance with value of 1s would be the same as it is with <1s since we don't accept messages more frequently than a second anyway.
well, i'm glad we now finally meet the main objective, which is to bail out when a duration var cannot be parsed.
|
I think this PR now finally meets the objectives.. |
oh, and address my previous comment of course about ConfigProcess... |
beautiful..
|
add ability to implement custom validation for config values in cass idx add config.go for cass idx configuration update cass idx tests to use new config update metrictank config and docs to show valid time units update mt-index-cat to use new cass idx config update mt-whisper-importer-writer to use new cass idx config See also: #944
add comments
update comments
update configuration files update documentation
force pushing rebase on master to resolve some conflicts.. |
e83045f
to
995d817
Compare
add err handling for 0 value durations in cass idx
add ability to implement custom validation for config values in cass idx
add config.go for cass idx configuration
update cass idx tests to use new config
update metrictank config and docs to show valid time units
update mt-index-cat to use new cass idx config
update mt-whisper-importer-writer to use new cass idx config
For earlier discussions on the previous PR to address this issue please see #1098
See also: #944, grafana/globalconf#3