Skip to content
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

Docker time stamps as metric time stamps #7434

Merged
merged 5 commits into from May 6, 2020

Conversation

i-prudnikov
Copy link
Contributor

Required for all PRs:

  • Signed CLA.
  • [] Associated README.md updated.
  • Has appropriate unit tests.

This PR comes from #7068, the first part - Use docker timestamps as metric timestamp.
Logs are streamed with timestamps, time stamps parsed from log message and added as metric timestamp. No custom read logic implemented, as stdcopy.StdCopy appears to remove headers from messages while demultiplexing that is a perfect fit.

Readme is not updated as nothing was changed in the plugin configuration interface.

@@ -311,6 +316,37 @@ func (d *DockerLogs) tailContainerLogs(
}
}

func parseLogEntry(rawMessage []byte, acc *telegraf.Accumulator, containerID *string) (time.Time, []byte) {
var message []byte
switch length := len(rawMessage); {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this function use bytes.SplitN(line, []byte(" "), 2). if there aren't 2 splits return an error, otherwise you are good to parse and return (time, message, err)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good, but I think theres is one edge case here, when the message is empty, I mean that it is only timestamp without any trailing whitespace, it is not an error. So in this case we need to return ts, empty message, and nil error. The caller function will make a decision either to emit empty message as a telegraf metric or not.
Moreover, I think that we should emit empty messages, as that is what container produced, but right now, this is thrown away. What is your opinion?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's emit the empty string as the message.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated as discussed

message, err = r.ReadString('\n')
message, err = r.ReadBytes('\n')
//Parsing timestamp and message
messageTs, message = parseLogEntry(message, &acc, &containerID)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change this function to support returning an error, if an error is returned you can acc.AddError(err) and skip processing the line.

@@ -52,7 +52,12 @@ type Response struct {
func (r *Response) Close() error {
return nil
}

func getFirst(p ...interface{}) interface{} {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define this like:

func MustParse(layout, value string) time.Time {
    tm, err := time.Parse(layout, value)
    if err != nil {
        panic(err)
    }
    return tm
}

@danielnelson danielnelson added this to the 1.15.0 milestone May 1, 2020
@danielnelson danielnelson added the feat Improvement on an existing feature such as adding a new setting/mode to an existing plugin label May 1, 2020
@danielnelson
Copy link
Contributor

Opened a PR against your fork, can you take a look: devopsext#1

}

return timeStamp, message, nil
return ts, message, nil
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@danielnelson , This cause copying the content of message, initially the function was returning []byte that is cheaper from this perspective (especially respecting the possible long lines of output from multiple containers). Moreover, later, the message is trimmed with TrimRightFunc(message, unicode.IsSpace), that again involve building new string. Should we revert back this to using []bytes until calling acc.AddFields? What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move TrimRightFunc into this function and apply the bytes version of it before converting the message to a string. The conversion/copy must happen at some point, its still best to do it here, but we just want to do it once.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adjusted as discussed

@danielnelson danielnelson merged commit 0924ad2 into influxdata:master May 6, 2020
@i-prudnikov i-prudnikov deleted the docker_log_original_ts branch May 6, 2020 19:14
idohalevi pushed a commit to idohalevi/telegraf that referenced this pull request Sep 29, 2020
@sjwang90 sjwang90 mentioned this pull request Feb 16, 2021
3 tasks
arstercz pushed a commit to arstercz/telegraf that referenced this pull request Mar 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat Improvement on an existing feature such as adding a new setting/mode to an existing plugin
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants