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

devicemapper: rework logging and add --storage-opt dm.libdm_log_level #33845

Merged
merged 4 commits into from
Jul 13, 2017

Conversation

cyphar
Copy link
Contributor

@cyphar cyphar commented Jun 27, 2017

Because libdm doesn't log anything if we have a logging callback
registered, we have to forward our logs to logrus. While this was done
previously in e2f8fbf ("devicemapper: split out devicemapper bindings"),
it was modified in e07d3cd ("devmapper: Fix libdm logging") to remove
the debugging information because it was too voluminous.

However, this has caused us several issues in debugging production
systems because libdm LOG{NOTICE,INFO,DEBUG} logs contain information
that cannot be obtained without recompiling the source.

In order to aid debugging while avoiding large amounts of logs, forward
LOG{NOTICE,INFO} into our debug logs and only output _LOG_DEBUG if an
additional storage-driver specific flag is specified. This respects the
fact that most users aren't going to be debugging devicemapper issues,
while also avoiding the source recompilation burden when debugging.

kitteh

Cosy cat by David O'Hare, on Flickr.

Signed-off-by: Aleksa Sarai [email protected]

/cc @vbatts @rhvgoyal

@cyphar
Copy link
Contributor Author

cyphar commented Jun 27, 2017

As an aside, I wanted to update the docs for dockerd to include the new storagedriver option. I was trying to figure out where the man pages live and it looks like they're no longer in this repo? Where are they now?

/cc @thaJeztah ?

@cpuguy83
Copy link
Member

This looks pretty much like a dup of #32541

@cyphar
Copy link
Contributor Author

cyphar commented Jun 27, 2017

I didn't see that change beforehand. However, this change actually does a lot more than #32541. In particular:

  • It cleans up the exposed callback code (which didn't make sense because we always needed to register a callback anyway).
  • Cleans up the C callback code to not be limited to 256 bytes.
  • Allows a user to specify what their choice of maximum logging is (which is the main point of this patch).
  • Removes some of the other old cruft from the logging code that Fine control of libdevmapper logging #32541 didn't touch.

I do like some of the stuff in p/d/log.go though, we might want to merge those changes as well. How would you like to go on from here?

@cpuguy83
Copy link
Member

Maybe we can just pull those changes in here? (minus the logrus dep in the p/d package).

@cyphar
Copy link
Contributor Author

cyphar commented Jun 27, 2017

Sure, will do. I'm splitting up this patch now so it's more obvious what I'm doing (I squashed it pre-emptively because I was planning on backporting it).

@cyphar
Copy link
Contributor Author

cyphar commented Jun 27, 2017

Actually I just realised that most of the code in pkg/devicemapper/log.go is not really useful if you don't want to have a logrus dependency inside that file (given the rest of my patchset). Effectively you just get a glorified Sprintf wrapper because you can't write a nice Logf without being able to log.

@cyphar cyphar force-pushed the devicemapper-show-me-your-logs branch 2 times, most recently from d9cb749 to c410d20 Compare June 27, 2017 17:22
@rhvgoyal
Copy link
Contributor

I have not looked at this yet. But we very much require something like this as well. Recompiling source code does not work when debugging a system in production. Restarting docker with additional flag is much easier.

So yes, we do need a knob to get fine control of logging by libdevmapper when used with docker.

// through logrus. libdm uses logging *very* liberally and most people using
// --debug [or Docker] aren't going to be debugging libdm bugs. You can enable
// this by setting --storage-opt="dm.log_level=X".
var dmLogLevel = LogLevelErr
Copy link
Contributor

Choose a reason for hiding this comment

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

So this changes default from fatal to level Err? When I had tested last time, even with this level libdm was spewing tons of messages. And it was made worse because we try device removal in a loop. Most of the time these messages are really not worth it.

How about keeping the current defaults and providing a knob to change that default.

Copy link
Contributor Author

@cyphar cyphar Jun 28, 2017

Choose a reason for hiding this comment

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

I ran this a few times and it didn't seem to spam the logs too much (and I don't like ignoring _LOG_ERROR because it causes you to ignore some _do_dm_ioctl errors) but yeah, I'll change it back to the old default.

@@ -2761,6 +2761,14 @@ func NewDeviceSet(root string, doInit bool, options []string, uidMaps, gidMaps [
return nil, errors.New("dm.thinp_autoextend_threshold must be greater than 0 and less than 100")
}
lvmSetupConfig.AutoExtendThreshold = per
case "dm.log_level":
Copy link
Contributor

Choose a reason for hiding this comment

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

Will it make sense to call it dm.libdm_log_level instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that sounds better.

@rhvgoyal
Copy link
Contributor

BTW, I love the idea of breaking down patches in a series. That way one can focus on core bits first and then focus on less important bits later. And its much easier to review.

@thaJeztah
Copy link
Member

As an aside, I wanted to update the docs for dockerd to include the new storagedriver option. I was trying to figure out where the man pages live and it looks like they're no longer in this repo? Where are they now?

The CLI docs were moved to the https://github.com/docker/cli repository (yes, dockerd could have been left in this repository, but after debating the pros/cons we decided that it made things easier to have them in that repository 😅)

@cyphar
Copy link
Contributor Author

cyphar commented Jun 28, 2017

@thaJeztah Alright, I'll match a PR there once this is merged.

@cyphar cyphar force-pushed the devicemapper-show-me-your-logs branch from c410d20 to 5b1dbdf Compare June 28, 2017 03:42
@cyphar
Copy link
Contributor Author

cyphar commented Jun 28, 2017

@rhvgoyal Fix'd. PTAL.

/cc @vbatts

case "dm.libdm_log_level":
level, err := strconv.ParseUint(val, 10, 32)
if err != nil {
return nil, err

Choose a reason for hiding this comment

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

Maybe, we should return a more expressive error here, as for instance case "dm.thinp_autoextend_threshold": does.

@@ -2761,6 +2761,14 @@ func NewDeviceSet(root string, doInit bool, options []string, uidMaps, gidMaps [
return nil, errors.New("dm.thinp_autoextend_threshold must be greater than 0 and less than 100")
}
lvmSetupConfig.AutoExtendThreshold = per
case "dm.libdm_log_level":
level, err := strconv.ParseUint(val, 10, 32)
Copy link

@vrothberg vrothberg Jun 28, 2017

Choose a reason for hiding this comment

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

Considering that DmLogLevel(value int) does bounds checking, we could just parse a 64bit integer here and defer bounds errors to DmLogLevel(value int).

@cyphar cyphar force-pushed the devicemapper-show-me-your-logs branch from 5b1dbdf to 95ae588 Compare June 28, 2017 09:07
@cyphar cyphar changed the title devicemapper: rework logging and add --storage-opt dm.log_debug devicemapper: rework logging and add --storage-opt dm.libdm_log_level Jun 28, 2017
@cyphar cyphar force-pushed the devicemapper-show-me-your-logs branch from 95ae588 to d83f396 Compare June 28, 2017 12:42
@cyphar
Copy link
Contributor Author

cyphar commented Jun 29, 2017

/cc @runcom You probably want to port this to containers/storage. Or if you prefer I can push this PR there as well.

@runcom
Copy link
Member

runcom commented Jun 29, 2017

cc @nalind for c/storage (thanks for the ping!)

@cyphar
Copy link
Contributor Author

cyphar commented Jun 29, 2017

/ping @rhvgoyal @cpuguy83 ?

vsnprintf(buffer, 256, f, ap);
va_end(ap);
va_start(ap, f);
vasprintf(&buffer, f, ap);
Copy link
Contributor

Choose a reason for hiding this comment

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

I get following warning during compilation.

Building: bundles/17.06.0-dev/dynbinary-daemon/dockerd-17.06.0-dev

github.com/docker/docker/pkg/devicemapper

.gopath/src/github.com/docker/docker/pkg/devicemapper/devmapper_wrapper.go: In function ‘log_cb’:
.gopath/src/github.com/docker/docker/pkg/devicemapper/devmapper_wrapper.go:20:2: warning: implicit declaration of function ‘vasprintf’; did you mean ‘vsprintf’? [-Wimplicit-function-declaration]
vasprintf(&buffer, f, ap);
^~~~~~~~~
vsprintf

Copy link
Contributor

Choose a reason for hiding this comment

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

Adding #define _GNU_SOURCE seems to make it go away.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup. For some reason I didn't get the same warning. Hmm.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

@cyphar cyphar force-pushed the devicemapper-show-me-your-logs branch from 439e40f to 7e552bf Compare June 30, 2017 20:09
This limit is unecessary and can lead to the truncation of long libdm
logs (which is quite annoying).

Fixes: b440ec0 ("device-mapper: Move all devicemapper spew to log through utils.Debugf().")
Signed-off-by: Aleksa Sarai <[email protected]>
e07d3cd ("devmapper: Fix libdm logging") removed all of the callers of
DmLogInitVerbose, but we still kept around the wrapper. However, the
libdm dm_log_init_verbose API changes the verbosity of the *default*
libdm logger. Because pkg/devicemapper internally *relies* on using
logging callbacks to understand what errors were encountered by libdm,
this wrapper is useless (it only makes sense for the default logger
which we do not user).

Any user not inside Docker of this function almost certainly was not
using this API correctly, because pkg/devicemapper will misbehave if our
logging callbacks were not registered.

Signed-off-by: Aleksa Sarai <[email protected]>
LogInit used to act as a manual way of registering the *necessary*
pkg/devicemapper logging callbacks. In addition, it was used to split up
the logic of pkg/devicemapper into daemon/graphdriver/devmapper (such
that some things were logged from libdm).

The manual aspect of this API was completely non-sensical and was just
begging for incorrect usage of pkg/devicemapper, so remove that semantic
and always register our own libdm callbacks.

In addition, recombine the split out logging callbacks into
pkg/devicemapper so that the default logger is local to the library and
also shown to be the recommended logger. This makes the code
substantially easier to read. Also the new DefaultLogger now has
configurable upper-bound for the log level, which allows for dynamically
changing the logging level.

Signed-off-by: Aleksa Sarai <[email protected]>
Because we use our own logging callbacks in order to use libdm
effectively, it is quite difficult to debug complicated devicemapper
issues (because any warnings or notices from libdm are muted by our own
callback function). e07d3cd ("devmapper: Fix libdm logging") further
reduced the ability of this debugging by only allowing _LOG_FATAL errors
to be passed to the output.

Unfortunately libdm is very chatty, so in order to avoid making the logs
even more crowded, add a dm.libdm_log_level storage option that allows
people who are debugging the lovely world of libdm to be able to dive in
without recompiling binaries.

The valid values of dm.libdm_log_level map directly to the libdm logging
levels, and are in the range [2,7] as of the time of writing with 7
being _LOG_DEBUG and 2 being _LOG_FATAL. The default is _LOG_FATAL.

Signed-off-by: Aleksa Sarai <[email protected]>
@cyphar cyphar force-pushed the devicemapper-show-me-your-logs branch from 7e552bf to 198f83b Compare July 3, 2017 16:04
@rhvgoyal
Copy link
Contributor

rhvgoyal commented Jul 3, 2017

LGTM

@cyphar thanks for implementing this knob. This is really required to be able to debug some docker issues without recompiling.

Rest of the cleanup is also nice. Makes reading this code easier.

@cyphar
Copy link
Contributor Author

cyphar commented Jul 3, 2017

I'm using this patchset to debug some production issues right now. 😉

@cyphar
Copy link
Contributor Author

cyphar commented Jul 7, 2017

/ping @cpuguy83

@coolljt0725
Copy link
Contributor

ping @cpuguy83

Copy link
Member

@cpuguy83 cpuguy83 left a comment

Choose a reason for hiding this comment

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

LGTM

Tested, looks good.

@cyphar
Copy link
Contributor Author

cyphar commented Jul 12, 2017

/cc @vdemeester @coolljt0725

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

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

LGTM

@thaJeztah thaJeztah merged commit 00b2182 into moby:master Jul 13, 2017
@thaJeztah
Copy link
Member

thanks @cyphar !

@cyphar cyphar deleted the devicemapper-show-me-your-logs branch July 13, 2017 06:03
albers added a commit to albers/docker-cli that referenced this pull request Jul 14, 2017
This adds bash completion for moby/moby#33845.

Signed-off-by: Harald Albers <[email protected]>
kolyshkin added a commit to kolyshkin/moby that referenced this pull request Jul 18, 2017
I am getting the following warning from gcc when compiling the daemon:

> # github.com/docker/docker/pkg/devicemapper
> pkg/devicemapper/devmapper_wrapper.go: In function ‘log_cb’:
> pkg/devicemapper/devmapper_wrapper.go:20:2: warning: ignoring return
> value of ‘vasprintf’, declared with attribute warn_unused_result
> [-Wunused-result]
>  vasprintf(&buffer, f, ap);
>  ^

vasprintf(3) man page says if the function returns -1, the buffer is
undefined, so we should not use it. In practice, I assume, this never
happens so we just return.

Introduced by moby#33845 that resulted in
commit 63328c6 ("devicemapper: remove 256 character limit of libdm logs")

Cc: Aleksa Sarai <[email protected]>
Signed-off-by: Kir Kolyshkin <[email protected]>
andrewhsu pushed a commit to docker-archive/docker-ce that referenced this pull request Jul 20, 2017
I am getting the following warning from gcc when compiling the daemon:

> # github.com/docker/docker/pkg/devicemapper
> pkg/devicemapper/devmapper_wrapper.go: In function ‘log_cb’:
> pkg/devicemapper/devmapper_wrapper.go:20:2: warning: ignoring return
> value of ‘vasprintf’, declared with attribute warn_unused_result
> [-Wunused-result]
>  vasprintf(&buffer, f, ap);
>  ^

vasprintf(3) man page says if the function returns -1, the buffer is
undefined, so we should not use it. In practice, I assume, this never
happens so we just return.

Introduced by moby/moby#33845 that resulted in
commit 63328c6 ("devicemapper: remove 256 character limit of libdm logs")

Cc: Aleksa Sarai <[email protected]>
Signed-off-by: Kir Kolyshkin <[email protected]>
Upstream-commit: 7da12bc
Component: engine
bonczj pushed a commit to bonczj/moby-json-file-logger that referenced this pull request Jul 25, 2017
I am getting the following warning from gcc when compiling the daemon:

> # github.com/docker/docker/pkg/devicemapper
> pkg/devicemapper/devmapper_wrapper.go: In function ‘log_cb’:
> pkg/devicemapper/devmapper_wrapper.go:20:2: warning: ignoring return
> value of ‘vasprintf’, declared with attribute warn_unused_result
> [-Wunused-result]
>  vasprintf(&buffer, f, ap);
>  ^

vasprintf(3) man page says if the function returns -1, the buffer is
undefined, so we should not use it. In practice, I assume, this never
happens so we just return.

Introduced by moby#33845 that resulted in
commit 63328c6 ("devicemapper: remove 256 character limit of libdm logs")

Cc: Aleksa Sarai <[email protected]>
Signed-off-by: Kir Kolyshkin <[email protected]>
riyazdf pushed a commit to riyazdf/cli that referenced this pull request Aug 2, 2017
This adds bash completion for moby/moby#33845.

Signed-off-by: Harald Albers <[email protected]>
silvin-lubecki pushed a commit to silvin-lubecki/engine-extract that referenced this pull request Mar 16, 2020
I am getting the following warning from gcc when compiling the daemon:

> # github.com/docker/docker/pkg/devicemapper
> pkg/devicemapper/devmapper_wrapper.go: In function ‘log_cb’:
> pkg/devicemapper/devmapper_wrapper.go:20:2: warning: ignoring return
> value of ‘vasprintf’, declared with attribute warn_unused_result
> [-Wunused-result]
>  vasprintf(&buffer, f, ap);
>  ^

vasprintf(3) man page says if the function returns -1, the buffer is
undefined, so we should not use it. In practice, I assume, this never
happens so we just return.

Introduced by moby/moby#33845 that resulted in
commit 63328c6 ("devicemapper: remove 256 character limit of libdm logs")

Cc: Aleksa Sarai <[email protected]>
Signed-off-by: Kir Kolyshkin <[email protected]>
Upstream-commit: 7da12bc
Component: engine
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants