-
Notifications
You must be signed in to change notification settings - Fork 2.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
*: replace verbose with log-level #892
Conversation
I think this incremental approach to enhancing nsq logging is not a bad one. Some comments though:
@judwhite probably has opinions on how nsq logging evolves ... |
|
nsqd/http.go
Outdated
return nil, http_api.Err{400, "INVALID_VALUE"} | ||
} | ||
if verbose { | ||
opts.LogLevel = LOG_INFO |
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.
should this be LOG_DEBUG
for verbose?
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.
... or should it actually change opts.Verbose
?
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 sure should! :D
os.Exit(1) | ||
} | ||
|
||
if opts.StatsdPrefix != "" { | ||
var port string | ||
_, port, err = net.SplitHostPort(opts.HTTPAddress) | ||
if err != nil { | ||
n.logf("ERROR: failed to parse HTTP address (%s) - %s", opts.HTTPAddress, err) | ||
n.logf(LOG_ERROR, "failed to parse HTTP address (%s) - %s", opts.HTTPAddress, err) |
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.
Pre-existing bug: looks like this should be LOG_FATAL
This is looking good to me. I'm still interested in consolidating the common parts between nsqd / nsqlookupd / nsqadmin, but that can be done in a later pull request. I might do that part myself :) |
apps/nsqd/nsqd.go
Outdated
@@ -15,7 +15,7 @@ import ( | |||
|
|||
"github.com/BurntSushi/toml" | |||
"github.com/judwhite/go-svc/svc" | |||
"github.com/mreiferson/go-options" | |||
options "github.com/mreiferson/go-options" |
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.
can we drop this change in all places?
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.
Sure thing.
apps/nsqadmin/main.go
Outdated
|
||
logLevel = flagSet.Int("log-level", nsqadmin.LOG_INFO, "set log verbosity: 1 through 5 (Debug, Info, Warn, Error, Fatal)") | ||
logPrefix = flagSet.String("log-prefix", "[nsqadmin] ", "log message prefix") | ||
verbose = flagSet.Bool("verbose", false, "depreceated in favor of log-level") |
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.
minor typo: should be deprecated
apps/nsqlookupd/nsqlookupd.go
Outdated
@@ -20,8 +20,10 @@ func nsqlookupdFlagSet(opts *nsqlookupd.Options) *flag.FlagSet { | |||
|
|||
flagSet.String("config", "", "path to config file") | |||
flagSet.Bool("version", false, "print version string") | |||
flagSet.Bool("verbose", false, "enable verbose logging") | |||
|
|||
flagSet.Int("log-level", nsqlookupd.LOG_WARN, "set log verbosity: 1 through 5 (Debug, Info, Warn, Error, Fatal)") |
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.
Is it a better UX for these to be strings rather than ints?
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 would be. Could process the string into an int once the flag parsing is done, deal with errors, etc.
Is it worth the extra effort?
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.
Probably yes. Command-line arguments are a sort of API in which changes should be avoided, so better to polish it now.
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.
Let me take a crack at it then.
Odd error on the go 1.7 386 node, twice in a row:
|
Don't worry about random coveralls failures, we won't complain about them :) |
There may be a more elegant way of handling this, but it is escaping me at this time. |
I think (this comment was originally added to a commit accidentally, then deleted and copied here) |
I will throw a default in there tomorrow night. |
contrib/nsqd.cfg.example
Outdated
# 3 = Warning | ||
# 4 = Error | ||
# 5 = Fatal | ||
log-level = 1 |
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.
config file value should be strings too
I wrote a test to check the http configuration side of it and discovered it was racing on logLevel defined in the NSQD struct; I moved it to Similar issue appears with nsqlookupd as Check it out and give me some feedback on how you folks feel about this. |
I think only nsqadmin and nsqd have an http interface for configuration changes after startup, so nsqlookupd shouldn't need |
LOG_FATAL = 5 | ||
) | ||
|
||
func (n *NSQAdmin) logLevelFromString(level string) int { |
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 doesn't need to be a method of the app, it doesn't use the app struct at all.
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 had a similar thought, but additionally was going to suggest that we make levels a type that can be shared across applications. We can provide a function that takes a string and returns an appropriately typed value and also implement the Stringer
interface on the type to satisfy the purpose here.
I think it should also be possible to cast an int
directly to this type if its signature is type LogLevel int
?
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.
Agreed about sharing across applications, but was thinking it would be OK if @antihax did not want to do that refactoring in this pull request. We could have the cmdline flags and http interfaces finalized in this PR, and I could do internal refactoring in a follow-up (and we could "bikeshed" as necessary).
I normally don't entertain promises to clean up in a later pull-request, but since it's me ¯\(ツ)/¯
Or, instead of directly merging this, I could include and then build on it in a separate PR.
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 with deferring if you're going to finish this up @ploxiln
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've been mulling over moving it to a separate package.
Concerned that it will end up looking like nsdq.logf(logger.LOG_WARN, "something")
and a little baffled how to handle the config side. Normally could write custom marshaling functions to deal with the mapping from string to int but i do not see how to support with go-options.
I am ok with you folks refactoring it later; I am still learning atm.
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.
My first idea was to move this stuff into internal/lg/
and rename the constants without the LOG_
prefix, so you would end up typing nsqd.logf(lg.WARN, "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.
(I didn't want to use internal/log/
and possibly conflict with the stdlib in files that import it, but maybe that's not really a problem in practice)
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.
@antihax 👍 SGTM, we can follow up. I appreciate your work on this!
nsqadmin/logger.go
Outdated
case "fatal": | ||
return LOG_FATAL | ||
case "": | ||
return LOG_INFO |
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 don't think you need to handle the blank case, this can be considered invalid.
I also don't think you need ToLower()
, you can just require the lowercase strings. This is not a big deal though.
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 can change these easily, concern would be if log-level was missing from the .cfg; a blank case would silently load a default rather than fail.
Likewise if a user had Debug
in a config instead of debug
, may take them a moment to notice case matters.
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.
Right, I was proposing erroring/exiting for anything but the expected lowercase strings. Blank not "silently loading a default" like you have here, but instead failing as invalid.
(I think that if log-level is missing in the config file you'll get the default "info" from NewOptions()
.)
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.
Yes, you are correct, i see now where the defaults would be loaded.
nsqadmin/logger.go
Outdated
} | ||
|
||
if level >= n.getOpts().logLevel || n.getOpts().Verbose { | ||
n.getOpts().Logger.Output(2, fmt.Sprintf(levelString+": "+f, args...)) |
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.
How about you do opts = n.GetOpts()
just once above, so the atomic.Value
is fetched and cast just once.
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.
Fixed in last commit.
nsqadmin/nsqadmin.go
Outdated
// check log-level is valid and translate to int | ||
switch strings.ToLower(opts.LogLevel) { | ||
case "debug": | ||
opts.logLevel = LOG_DEBUG |
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.
should use logLevelFromString()
here
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.
Fixed.
nsqlookupd/nsqlookupd.go
Outdated
n.logLevel = LOG_ERROR | ||
case "fatal": | ||
n.logLevel = LOG_FATAL | ||
case "": |
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.
another blank
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.
but actually, should use logLevelFromString()
nsqadmin/http.go
Outdated
@@ -732,6 +732,21 @@ func (s *httpServer) doConfig(w http.ResponseWriter, req *http.Request, ps httpr | |||
if err != nil { | |||
return nil, http_api.Err{400, "INVALID_VALUE"} | |||
} | |||
case "log_level": | |||
var logLevelStr string // temporary variable in case the value is invalid | |||
err := json.Unmarshal(body, &logLevelStr) |
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 was testing this PR locally and ran into this - I don't think this should be json, it should just be a plain string.
Treating the body as json representation of a single string means you need to include the quotes e.g. "info"
instead of info
and that seems a bit silly.
(Same comment applies for nsqd.)
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.
To justify this opinion a bit more: "nsqlookupd_tcp_addresses" is a list so json makes sense, and "verbose" is a boolean which has non-quoted representation in json so that's convenient. But adding quotes around a single word, particularly for a manual tool like curl where you end up running curl --data-binary '"info"' ...
, is a bit unexpected.
Interesting complication: |
This seems to me to be close to ready for merge. |
@@ -90,6 +92,8 @@ func NewOptions() *Options { | |||
return &Options{ | |||
ID: defaultID, | |||
LogPrefix: "[nsqd] ", | |||
LogLevel: "info", | |||
logLevel: 2, |
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 putting the logLevel
int default in nsqd.NewOptions()
isn't needed, because it's set from the string in nsqd.New()
. (The same goes for nsqadmin, but you didn't set the logLevel int default in nsqadmin.NewOptions()
.)
But this doesn't hurt (except a tiny bit of code redundancy), and I think it may be fine to wait to fix it in my planned follow-up PR.
I think this is ready to merge. @mreiferson any objections? |
case "fatal": | ||
return LOG_FATAL | ||
default: | ||
return -1 |
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 can be fixed in a follow up).
This feels like a C idiom, not Go. If this function has error conditions, it should return (int, error)
and this should be a case that returns an error.
I'm good, nice work @antihax! |
Is this actually working? I set log-level to "fatal" in the config and still getting lots of these messages:
|
This was merged after version "1.0.0-compat" was released. We need to cut another release. |
@ploxiln : Oh nooo! I did not notice that this was merged after the last release! I assumed it was in the last release. Well my birthday is coming up... and it has been almost a year since this was merged in, can we get a new release soon? |
@mreiferson : nsqd is a dependency of ours on the hephy project (deis workflow) fork and we would like to limit log level in order to remove noise in the logs. Any idea of when we can get a new release? |
@mreiferson I need this too. Not being able to limit logs levels is creating extra cost to our logging solution. |
@mreiferson @ploxiln I need this too. Not being able to limit logs levels is creating extra cost to our logging solution. |
I'll issue a release this week, thanks everyone 🙏 |
@mreiferson Any news on this release? |
@mreiferson @ploxiln Can we get a release? This needs to be addressed. |
@mreiferson : We really would like to limit log-level in our Hephy Workflow nsqd component. A new release with this feature would be really nice. Is there any way we can assist and help out with the release? We can fork and create a release but I would rather someone who knows where exactly to tag even though Travis builds seem to be passing! |
Yep, sorry for the delay 🙏. |
@mreiferson , don't get side-tracked and distracted now ... You have almost finished making this release. 💵 💰 |
@mreiferson Bump release please. |
There was just a v1.1.0-rc1 "release candidate" which you can try :) |
Removed verbose option and added a log-level option so users can customize what they receive in logs.
Should resolve issue #798