HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
sirupsen
logrus
Go2014–2025
sirupsen / logrus

logrus

Structured, pluggable logging for Go.

23Distinct people
25Mentions
0Explicit recommenders
25.8KGitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

Structured, pluggable logging for Go.

GitHub

Where it is used

No documented product use was verified in the last source check.

What people are saying

No recommendation phrase was found in the indexed comments.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

Mentioned in the same Hacker News threads. That is not proof they are substitutes.

This week on Hacker News

Nov 7–Nov 14 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/14/2026, 3:56:07 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year25 dated mentions

Observed mentions: 2014-03-13 10:08:23 UTC to 2025-04-01 05:08:54 UTC.

012342014-01-01 00:00:00 UTC to 2015-01-01 00:00:00 UTC (exclusive): 3 mentions; 1 submissions, 2 comments20142015-01-01 00:00:00 UTC to 2016-01-01 00:00:00 UTC (exclusive): 4 mentions; 0 submissions, 4 comments2016-01-01 00:00:00 UTC to 2017-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2017-01-01 00:00:00 UTC to 2018-01-01 00:00:00 UTC (exclusive): 3 mentions; 0 submissions, 3 comments2018-01-01 00:00:00 UTC to 2019-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2019-01-01 00:00:00 UTC to 2020-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments20192020-01-01 00:00:00 UTC to 2021-01-01 00:00:00 UTC (exclusive): 3 mentions; 0 submissions, 3 comments2021-01-01 00:00:00 UTC to 2022-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2023-01-01 00:00:00 UTC to 2024-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2024-01-01 00:00:00 UTC to 2025-01-01 00:00:00 UTC (exclusive): 3 mentions; 0 submissions, 3 comments2025-01-01 00:00:00 UTC to 2026-01-01 00:00:00 UTC (exclusive): 2 mentions; 1 submissions, 1 comments2025

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20142014-01-01 00:00:00 UTC2015-01-01 00:00:00 UTC312
20152015-01-01 00:00:00 UTC2016-01-01 00:00:00 UTC404
20162016-01-01 00:00:00 UTC2017-01-01 00:00:00 UTC000
20172017-01-01 00:00:00 UTC2018-01-01 00:00:00 UTC303
20182018-01-01 00:00:00 UTC2019-01-01 00:00:00 UTC202
20192019-01-01 00:00:00 UTC2020-01-01 00:00:00 UTC000
20202020-01-01 00:00:00 UTC2021-01-01 00:00:00 UTC303
20212021-01-01 00:00:00 UTC2022-01-01 00:00:00 UTC202
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC101
20232023-01-01 00:00:00 UTC2024-01-01 00:00:00 UTC202
20242024-01-01 00:00:00 UTC2025-01-01 00:00:00 UTC303
20252025-01-01 00:00:00 UTC2026-01-01 00:00:00 UTC211

From the project README

An excerpt from the repository, fetched Nov 13, 2026.

Read the project’s introduction
Logrus Logrus is a structured logger for Go (golang), completely API compatible with the standard library logger. Logrus is in maintenance mode. The project focuses on security, bug fixes, and performance improvements. New features are not planned, aside from changes required to provide interoperability with other logging ecosystems (e.g., Go's log/slog). I believe Logrus' biggest contribution is to have played a part in today's widespread use of structured logging in Golang. There doesn't seem to be a reason to do a major, breaking iteration into Logrus V2, since the fantastic Go community has built those independently. Many fantastic alternatives have sprung up. Logrus would look like those, had it been re-designed with what we know about structured logging in Go today. Check out, for example, Zerolog, Zap, and Apex. Nicely color-coded in development (when a TTY is attached, otherwise just plain text): With logrus.SetFormatter(&logrus.JSONFormatter{}), for easy parsing by logstash or Splunk: {"animal":"walrus","level":"info","msg":"A group of walrus emerges from the ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"} {"level":"warning","msg":"The group's number increased tremendously!","number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"} {"animal":"walrus","level":"info","msg":"A giant walrus appears!","size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"} {"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.","size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"} {"level":"fatal","msg":"The ice breaks!","number":100,"omg":true,"time":"2014-03-10 19:57:38.562543128 -0400 EDT"} With the default logrus.SetFormatter(&logrus.TextFormatter{}) when a TTY is not attached, the output is compatible with the logfmt format: time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8 time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10 time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4 time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009 time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" animal=orca err="It's over 9000!" number=100 omg=true size=9009 To ensure this behaviour even if a TTY is attached, set your formatter as follows: logrus.SetFormatter(&logrus.TextFormatter{ DisableColors: true, FullTimestamp: true, }) Logging Method Name If you wish to add the calling method as a field, instruct the logger via: logrus.SetReportCaller(true) This adds the caller as 'method' like so: {"animal":"penguin","level":"fatal","method":"github.com/sirupsen/arcticcreatures.migrate","msg":"a penguin swims by","time":"2014-03-10 19:57:38.562543129 -0400 EDT"} time="2015-03-26T01:27:38-04:00" level=fatal method=github.com/sirupsen/arcticcreatures.migrate msg="a penguin swims by" animal=penguin Note that this does add measurable overhead - the cost will depend on the version of Go, but is between 20 and 40% in recent tests with 1.6 and 1.7. You can validate this in your environment via benchmarks: go test -bench=ReportCaller Case-sensitivity The organization's name was changed to lower-case. If you are getting import conflicts due to case sensitivity, please use the lower-case import: github.com/sirupsen/logrus. Example The simplest way to use Logrus is simply the package-level exported logger: package main import "github.com/sirupsen/logrus" func main() { logrus.WithFields(logrus.Fields{ "animal": "walrus", }).Info("A walrus appears") } Note that it's completely api-compatible with the stdlib logger, so you can replace your log imports everywhere with log "github.com/sirupsen/logrus" and you'll now have the flexibility of Logrus. You can customize it all you want: package main import ( "os" log "github.com/sirupsen/logrus" ) func init() { // Log as JSON instead of the default ASCII formatter. log.SetFormatter(&log.JSONFormatter{}) // Output to stdout instead of the default stderr // Can be any io.Writer, see below for File example log.SetOutput(os.Stdout) // Only log the warning severity or above. log.SetLevel(log.WarnLevel) } func main() { log.WithFields(log.Fields{ "animal": "walrus", "size": 10, }).Info("A group of walrus emerges from the ocean") log.WithFields(log.Fields{ "omg": true, "number": 122, }).Warn("The group's number increased tremendously!") log.WithFields(log.Fields{ "omg": true, "number": 100, }).Fatal("The ice breaks!") // A common pattern is to re-use fields between logging statements by re-using // the logrus.Entry returned from WithFields() contextLogger := log.WithFields(log.Fields{ "common": "this is a common field", "other": "I also should be logged always", }) contextLogger.Info("I'll be logged with common and other field") contextLogger.Info("Me too") } For more advanced usage such as logging to multiple locations from the same application, you can also create an instance of the logrus Logger: package main import ( "os" "github.com/sirupsen/logrus" ) // Create a new instance of the logger. You can have any number of instances. var logger = logrus.New() func main() { // The API for setting attributes is a little different than the package level // exported logger. See Godoc. logger.Out = os.Stdout // You could set this to any `io.Writer` such as a file // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) // if err == nil { // logger.Out = file // } else { // logger.Info("Failed to log to file, using default stderr") // } logger.WithFields(logrus.Fields{ "animal": "walrus", "size": 10, }).Info("A group of walrus emerges from the oc
Read the full README on GitHub

What Hacker News says

25 sources
For an internal-only dependency it's possible. But if you've got a lot of active branches, or long-lived feature branches, it'll create chaos in merge conflicts. Even worse if you've got multiple supported versions of a product on release branches (e.g., `main-v1.0`, `main-v1.1`, `main-v1.2`, and `main` itself for the yet-to-be-released `v1.3`) you either make backports awful (by only changing the import path on `main`) or have to change even more things (by changing the import path on the release branches too). It's effectively impossible for pubic-facing dependencies. Imagine if https://github.com/sirupsen/logrus wanted to change their Go modules import path, for example to move to another git hosting provider. (Logrus is great by the way, I'm only 'picking' on it as a popular Go library that's used everywhere.) GitHub tells me that alm
Read the rest
ost 200,000 Go projects depend on it (https://github.com/sirupsen/logrus/network/dependents), so all of them would need to change every source file they do logging in (probably most of them) in order to handle that. GitHub seems like it's going to be eternal for now, but when the industry moves on in 10 years time every single Go project is going to break. This would be a problem for any source dependency management solution of course, it's not like any of the others are immune to this issue. But because Go has you encode the Git path in every source file you import it into, the level of change to fix it is an order of magnitude higher.
In Go is my hammer, and everything is a nail
But in that case it should have a note saying it's finished or in maintenance mode (e.g. https://github.com/sirupsen/logrus); include references to replacements, offer paid support if you really need it or still use it, keep an eye on issues, and update dependencies. Else, ask for a new maintainer. While code can be considered done (especially if no new features are added), it should never go unmaintained. If it's actually used a lot of course.
In Tracking the Fake GitHub Star Black Market
The "go install" part of the installation instructions results in this error: $ git clone https://github.com/jafarlihi/rssnix --depth=1 && cd rssnix && go install Cloning into 'rssnix'... remote: Enumerating objects: 10, done. remote: Counting objects: 100% (10/10), done. remote: Compressing objects: 100% (8/8), done. remote: Total 10 (delta 1), reused 4 (delta 1), pack-reused 0 Unpacking objects: 100% (10/10), done. config.go:8:2: cannot find package "github.com/go-ini/ini" in any of: /usr/lib/go-1.10/src/github.com/go-ini/ini (from $GOROOT) /home/user/go/src/github.com/go-ini/ini (from $GOPATH) feed.go:9:2: cannot find package "github.com/mmcdole/gofeed" in any of: /usr/lib/go-1.10/src/github.com/mmcdole/gofeed (from $GOROOT) /home/user/go/src/github.com/mmcdole/gofeed (from $GOPATH) config.go:9:2: cannot
Read the rest
find package "github.com/sirupsen/logrus" in any of: /usr/lib/go-1.10/src/github.com/sirupsen/logrus (from $GOROOT) /home/user/go/src/github.com/sirupsen/logrus (from $GOPATH) main.go:10:2: cannot find package "github.com/urfave/cli/v2" in any of: /usr/lib/go-1.10/src/github.com/urfave/cli/v2 (from $GOROOT) /home/user/go/src/github.com/urfave/cli/v2 (from $GOPATH) feed.go:11:2: cannot find package "golang.org/x/exp/slices" in any of: /usr/lib/go-1.10/src/golang.org/x/exp/slices (from $GOROOT) /home/user/go/src/golang.org/x/exp/slices (from $GOPATH) edit: uname -a => Linux x1 5.4.0-132-generic #148~18.04.1-Ubuntu SMP Mon Oct 24 20:41:14 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
In Show HN: Rssnix – Unix-style filesystem-based RSS/Atom/JSON Feed fetcher/reader
Sure. We use Prometheus exporters, most of the exporters are written in Go. And this is a snip from the vmware-exporter for our VMware estate. metrics.go The first throw was this: import ( "context" "github.com/prometheus/client_golang/prometheus" log "github.com/sirupsen/logrus" "github.com/vmware/govmomi/find" "github.com/vmware/govmomi/view" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" So as it currently stands I have no idea what those modules are and what I am loading. Browsing each of those repos sure will tell me, but that's not my role. My role is to make X operational. And if that repo doesn't exist anymore and you go to compile, it fails. More overhead if I need to make changes to any of those modules. I would need to git clone it somewhere, make the change and then either reco
Read the rest
mmit it to git, or do something to make it locally available. At least with NPM, CPAN they are local to the file system. So lets start: var ( prometheusHostPowerState = prometheus.NewGaugeVec(prometheus.GaugeOpts{ Namespace: namespace, Subsystem: "host", Name: "power_state", Help: "poweredOn 1, poweredOff 2, standBy 3, other 0", }, []string{"host_name"}) I understand all of that. Power_state, display the help, power status description etc, however prometheus.NewGaugeVec -- Sounds great. What is it? Where do I find this? What module is this related too? That's where it falls down for me. I now have to duck in to the rabbit hole of github to find out where that function is phrased and in this sense "under-the-hood" could also count for library .pm files in perl, but now having to navigate GitHub really messes with my workflow.
In The ecosystem of the Go programming language
Right URLs never change. Remember when one of the most popular golang logging libraries renamed from github.com/Sirupsen/logrus to github.com/sirupsen/logrus and all of a sudden everything would break because you were using both via some dep vendor. Or Java where you get 80 char of namespaces that may or may not change because the library moved to be an eclipse project.
In Python typosquatting is about more than typos
Depends on how you do it. It's designed first and foremost to work with vendored dependencies in a monorepo, and the external repository support is newer. Bazel won't pull in transitive dependencies unless you ask it to in the WORKSPACE file, which means that you can use a private mirror for all your dependencies if you like, which is fairly easy in practice (I do it for personal projects). The experience will vary depending on your preferences and the languages you use. With Go + Bazel, my experience is that the Bazel version will have fewer dependencies than the equivalent "go mod" version, because "go mod" will pull in dependencies more coarsely and Bazel has more fine-grained control. Go mod will pull in dependencies for the entire repo that you depend on, but with Bazel, you only need dependencies for the individual subpackages. As a
Read the rest
specific example... suppose you use github.com/jackc/pgx. With "go mod" you end up with "github.com/sirupsen/logrus" in your transitive dependencies, but with Bazel you don't, unless you use the part of pgx that requires logrus. You can also end up with "half the internet" in your dependencies pretty easily, but I think these days that is just the price of including random libraries in your project. As far as I can tell, the approach to avoid depending on half the internet is to be very conservative about your dependencies, but that is true regardless of the system you use to manage them. Just to pick on the JavaScript ecosystem, if you start a new JavaScript project and pull in TypeScript, Rollup, and Terser, you'll end up with a very SMALL lock file because each of these libraries have a very small number of carefully chosen dependencies.
In Bazel For Open-Source C/C++ Libraries Distribution
My work mainly involves setting up internal enterprise applications. - The standard testing package - Manually setup dependency injection. Generally a flow like config=>databases=>models=>routes=>server. - https://github.com/gorilla/mux for routing and https://github.com/swaggo/swag for documentation - As for HTTP frameworks I just use the standard package and I really enjoy https://github.com/sirupsen/logrus for logging We use IIS. I really wanted to use go so, I found a way to run go applications on top of it. That was not fun to figure out, but I can make use of the windows authentication underneath IIS. Required a custom module that forwards some headers to my go applications. Also the version of IIS we use doesn't even support http2 which sucks.
In Ask HN: How are you using Go to write production-grade back end services?
For Go just use logrus https://github.com/sirupsen/logrus It’s easy to use and full of features. There are faster packages out there but you don’t really need them unless you’re Twitter scale or something. For log aggregation in all environments try oklog https://github.com/oklog/oklog Much easier to run and maintain then Elastic, excellent performance and scalability. Especially good if you’re a small shop and don’t have the time or resources to complicate your infrastructure.
In Ask HN: What are the best logging packages you have come across?
You forgot URLs as import namespaces. It makes it literally impossible to swap one library for another (a rename or fork). A simple example that had caused tons of grief and had probably wasted lots of man-hours is when github.com/Sirupsen/logrus became github.com/sirupsen/logrus. Vendoring sort of works for simpler "I need a patched version of this" cases, but is not a real solution.
In Why I Don't Like Golang (2016)

Showing the 15 most recent of 25 sources. Enable JavaScript to search and browse every indexed mention.

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.