Skip to content

WIP - Support for logging from children processes#1861

Closed
marcov wants to merge 2 commits intoopencontainers:masterfrom
marcov:child-logging
Closed

WIP - Support for logging from children processes#1861
marcov wants to merge 2 commits intoopencontainers:masterfrom
marcov:child-logging

Conversation

@marcov
Copy link
Copy Markdown
Contributor

@marcov marcov commented Aug 8, 2018

Add support for children processes logging (including nsexec).
A pipe is used to send logs from children to parent in JSON.
The JSON format used is the same used by logrus JSON formatted,
i.e. children process can use standard logrus APIs.

This improves debugging and can also be used to report warning messages from the children.

marcov added 2 commits August 8, 2018 13:29
Add support for children processes logging (including nsexec).
A pipe is used to send logs from children to parent in JSON.
The JSON format used is the same used by logrus JSON formatted,
i.e. children process can use standard logrus APIs.

Signed-off-by: Marco Vedovati <mvedovati@suse.com>
Pipe close before exec is not necessary as os.Pipe() is calling pipe2
with O_CLOEXEC option.

Signed-off-by: Marco Vedovati <mvedovati@suse.com>
Comment thread libcontainer/standard_init_linux.go Outdated
}
}

logPipe, _ := (logrus.StandardLogger().Out).(*(os.File))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Three things:

  • I'm not sure it's necessary to do (a).(*os.File) -- I think a.(*os.File) will work just as fine (and gofmt should complain at you because it's not idiomatic).

  • You shouldn't ignore the ok value here. Even if it is impossible to occur, you should either make it panic or you should check that logPipe != nil (which is the error case -- because that would also panic).

  • Also we should probably set logPipe to be O_CLOEXEC which would remove the requirement to close it like this.

}
if !p.Init {
return c.newSetnsProcess(p, cmd, parentPipe, childPipe)
return c.newSetnsProcess(p, cmd, parentPipe, childPipe, &logPipe)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It feels unnecessary to pass a reference here -- since the members are pointers there's no real risk of accidentally copying something. The later *logPipe just makes it look confusing.

return nil, newSystemErrorWithCause(err, "including execfifo in cmd.Exec setup")
}
return c.newInitProcess(p, cmd, parentPipe, childPipe)
return c.newInitProcess(p, cmd, parentPipe, childPipe, &logPipe)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ditto on the &logPipe comment here too.

Comment thread libcontainer/logs.go
logrus.WarnLevel: logrus.Warn,
logrus.InfoLevel: logrus.Info,
logrus.DebugLevel: logrus.Debug,
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is a bit ugly, but it looks like logrus gives us no choice (you can't call Entry.log with an explicit level -- it even looks like there's a race condition in the level check inside logrus!). (Not an actionable complaint, just something I noticed.)

"{\"level\":\"%s\", \"msg\": \"", strlevel[level]);

va_start(args, format);
len += vsnprintf(&jsonbuffer[len], sizeof(jsonbuffer) - len, format, args);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

While not an immediate issue, this does mean that we cannot deal with " (or any special characters) inside of the JSON string. Hopefully we won't hit that problem, but it is something to keep in mind.

Comment thread main.go
app.Before = func(context *cli.Context) error {

// do nothing if logrus was already initialized in init.go
if logrus.StandardLogger().Out != logrus.New().Out {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not really a fan of this -- why not set up logging for init here (or setting a global flag) rather than doing it this way?


setExternalDescriptors(fds []string)

getChildLogs()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't really like this name -- maybe forwardChildLogs or proxyChildLogs to make it clear that this method actually pipes directly to logrus.

@marcov marcov changed the title Support for logging from children processes WIP - Support for logging from children processes Aug 20, 2018
@cyphar
Copy link
Copy Markdown
Member

cyphar commented Apr 23, 2019

Closing in favour of #2034. Thanks @marcov for kicking this one off.

@cyphar cyphar closed this Apr 23, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants