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

Custom Log Levels #463

Closed
yoiang opened this issue Jan 8, 2017 · 15 comments
Closed

Custom Log Levels #463

yoiang opened this issue Jan 8, 2017 · 15 comments

Comments

@yoiang
Copy link

yoiang commented Jan 8, 2017

Hello logrus folks!
It was mentioned in issue #121 that being able to make your own custom log levels would be a feature by 1.0, wanted to make a place to track the feature's progress.

Thanks for the great work!

@stevvooe
Copy link
Collaborator

@yoiang Do you have a proposal for how this would work?

@yoiang
Copy link
Author

yoiang commented Jan 11, 2017

hey @stevvooe! Do you mean what would the API look like or how would it actually be implemented in logrus' guts technically? I am not expert with either but can take some time and figure it out depending on what you're asking!

@stevvooe
Copy link
Collaborator

@yoiang So, the issue is that we already have values that have an ordering. Allowing users to define these may have an impact on how that ordering interacts. Without going into details, bolting this on is likely pretty complex.

@sirupsen may have a more detailed plan for how this might work.

@cretz
Copy link

cretz commented Feb 8, 2017

I suggest simply exposing logrus.Entry.Log(Level, string) (and logrus.Entry.Logf(Level, string, ...interface{})) and adding a logrus.SetCustomLevelName(Level, string) and logrus.GetCustomLevelName(Level) string, bool which are simply backed by a thread-safe map. Then logrus.Level.String() can use the latter before defaulting to "unknown".

Then we can all simply create levels via:

const TraceLevel = logrus.DebugLevel + 1

func init() {
  logrus.SetCustomLevelName(TraceLevel, "trace")
}

This of course does not solve issues where people may want their level in between other levels. The way to solve that with a backwards compatible impl is to keep the Level type and make a new interface and what not:

type Leveler interface {
  Cmp(other Leveler) int
  LevelString() string
}

func (level Level) Cmp(other Leveler) int {
  switch other := other.(type) {
    case Level:
      if level > other {
        return 1
      } else if level < other {
        return -1
      }
      return 0
    default:
      return -other.Cmp(level)
  }
}

func (level Level) LevelString() string { return level.String() }

Then of course have logrus.Entry.Log(Leveler, string) and logrus.Entry.Logf(Leveler, string, ...interface{}). Granted it may have a bit of performance overhead introducing a type switch in every log statement, but it's a thought. I think the first proposal is good enough to solve people's notice/trace wants (or just go ahead and acknowledge there's a level below debug for many common use cases).

@stevvooe
Copy link
Collaborator

stevvooe commented Feb 8, 2017

@cretz Would it be sufficient just to add a Trace level to logrus? I'm really not sure about the effect bolting something on like this.

@cretz
Copy link

cretz commented Feb 8, 2017

@stevvooe - Yes, but it has been explicitly rejected multiple times.

FWIW, I disagree w/ the rejections. In my lib I have Tracef that I just check my own level state on before just sending it off to Debugf which is good enough for me.

@Random-Liu
Copy link

Random-Liu commented Jan 16, 2018

@stevvooe See you here! :D

@cretz I agree with you. In Kubernetes, we usually have:

  • One log level for normal production log output (corresponds to logrus info)
  • One log level for test environment output (corresponds to logrus debug)
  • One log level for actual debug, we don't want to log this in test environment, because they are too spammy. But we do want to be able to turn on those logs when we actually see a problem and try to debug. (corresponds to what? I think this is where trace is useful.)

In cri-containerd, we were using glog previously, and I'm trying to move to logrus to make the log output consistent with containerd. However, this become a issue blocking us.

@miguelmota
Copy link

+1 for custom log levels

@IMBlues
Copy link

IMBlues commented Jan 19, 2018

+1
Just like glog.V(x), we could filter out most of spammy log.

@mwillfox
Copy link

mwillfox commented Feb 8, 2019

+1 for user implemented log levels. A use case that we use a lot that might not have been considered is Cloudwatch Log filtering into Cloudwatch Metrics. In most languages we create a log level called Metric that is generally very high, somewhere above Warn or Error depending on the language. This way our logs that contain metrics that need to be processed are always logged in all environments without extremely verbose logs. Currently with logrus I would have to log these at Info or patch them into Warn which would be weird.

@relwell
Copy link

relwell commented Feb 13, 2019

FWIW @defendertx's comment is exactly the reason I found this issue by searching "logrus custom level" in Google

@Kigamba
Copy link

Kigamba commented Oct 21, 2019

+1 for custom log levels

@freeformz
Copy link
Collaborator

Logrus now (and for a while) has had a Trace level and corresponding methods. That seems to address all the use cases I read through in this issue.

Additionally there are Log, Logf, & Logln methods which take arbitrary levels.

I think the only thing missing is the way that existing levels are somewhat hard coded, making extension / customization of them a bit hard. Related to that: #1009 (comment)

@dm3ch
Copy link

dm3ch commented Nov 17, 2019

Suddenly I think Trace level fits most of needs but not all.

For example custom log levels could be useful also for audit logging, suddenly with current log levels it's very complex to find place for them, and creating custom log level for them could be a good option

@markphelps
Copy link
Collaborator

Closing per the project being put into maintenance mode

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests