-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
New option timestamp.precision
to control timestamp precision
#31682
Conversation
4d55be5
to
82d66a6
Compare
timestamp.precision
to control timestamp precision
Pinging @elastic/elastic-agent-data-plane (Team:Elastic-Agent-Data-Plane) |
@@ -287,6 +287,10 @@ heartbeat.jobs: | |||
# sub-dictionary. Default is false. | |||
#fields_under_root: false | |||
|
|||
# Configure the precision of all timestamps in Heartbeat. |
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.
Am I right in understanding that this basically just changes how time.Time
fields are serialized when used with common.Time
? If so, this should work.
However, we should add a note that time fields will keep their us
(microsecond) paths, such as monitor.duration.us
.
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.
Nevermind, I think we should be fine here, all the us
stuff is durations not timestamps.
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 assume (but not sure) this is meant to control the precision of timestamps used in events sent by outputs. We need to add a test case for this. I don't think changing the implementation of common.Time#MarshalJSON
is sufficient.
The outputs that allow configurable formats have a concept of a codec that is involved in controlling the output format. Perhaps the configuration for this belongs in the codecs that are responsible for marshaling the data.
For example the outputs/codec/json already supports some configuration in the timestamp format by allowing the local time zone to be used.
beats/libbeat/outputs/codec/json/json.go
Lines 80 to 86 in 9b82b2a
// create new encoder with custom time.Time encoding | |
e.folder, err = gotype.NewIterator(visitor, | |
gotype.Folders( | |
codec.MakeUTCOrLocalTimestampEncoder(e.config.LocalTime), | |
codec.MakeBCTimestampEncoder(), | |
), | |
) |
And the format of the timestamps used by the Elasticsearch output are controlled here:
beats/libbeat/esleg/eslegclient/enc.go
Lines 90 to 93 in b581b17
b.folder, err = gotype.NewIterator(visitor, | |
gotype.Folders( | |
codec.MakeTimestampEncoder(), | |
codec.MakeBCTimestampEncoder())) |
return nil | ||
} | ||
|
||
func SetTimestampPrecision(c *conf.C) 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.
This seems important and I think it needs some documentation. Like it should state that it modifies the behavior of common.Time
's MarshalJSON()
and String()
methods . And I think it should call out that it's not safe to call this after you have any other threads using common.Time
because it modifies the global formatter that they all share.
Thinking about this more, I'm wondering if we can opt out of this for heartbeat. This isn't a feature any of our users want / need, and it only creates a support burden. If we can decrease heartbeat's surface area where possible that's a win. |
@andrewkroh @andrewvc For the record the timestamps Beats produce are already in nanosecond precision as implemented in #31553 This PR is just making it configurable for users.
What you you mean by opt out? Do you want to opt out of configuring timestamp precision and stay with the new nanosecond setting? Or do you want to stay on the previous millisecond precision? If you want to opt out of nanosecond precision timestamps, this is the PR that implements it for you. :) |
@andrewkroh Initially, it was my intention. However, only changing the timestamp precision of My reasoning is that all timestamps were globally millisecond precision in Beats. The precisions of timestamps should be configured together where possible. It looks inconsistent if one timestamp is nanosecond, another one is in milliseconds, etc.
It's not only changing I indeed missed |
|
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 rather see the output format controlled without the use of a global state in a common package. The global nature makes test isolation difficult because one test can modify a global and affect other tests. This is less of a concern, but it also creates a concurrency issue since there is no synchronization on the global. Rather than using a global, the desired format could be passed into each output codec instance.
I have a similar feeling about the global nature of timestamp.precision
. If this were scoped to the output config this might give a bit more flexibility in the behavior if it were ever needed (like allowing independent precision for the monitoring output vs the event output).
@@ -87,7 +171,7 @@ func ParseTime(timespec string) (Time, error) { | |||
} | |||
|
|||
func (t Time) String() string { | |||
str, _ := defaultTimeFormatter.Format(time.Time(t).UTC()) | |||
str, _ := timeFormatter.Format(time.Time(t).UTC()) |
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 not only changing MarshalJSON, the PR also affects String function. Event transformers, serializers use the String function of common.Time to get the string representation of the field.
Apart from some test code that uses the stdlib json encoder, I can't think of anything that should be dependent upon common.Time's format in the output path (including processors). Could common.Time retain its static behavior of generating ISO8601 timestamps with nanosecond precision without affecting the output format?
I agree. My initial implementation included a new
On the input side users can rely on the timestamp processor to modify the precision of the timestamp. With that in mind, I think we can get away with setting the granularity globally to nanoseconds, and then decrease it on the input level if needed. |
What does this PR do?
This PR makes timestamp precision configurable. A new config option is added called
timestamp.precision
. Available options aremillisecond
microseconds
andnanosecond
. Default value ismillisecond
.Why is it important?
We made nanosecond support default in #31553. But such timestamps require more storage. Thus, we are making it opt-in.
Checklist
- [ ] I have commented my code, particularly in hard-to-understand areasCHANGELOG.next.asciidoc
orCHANGELOG-developer.next.asciidoc
.