{"id":305,"date":"2019-11-25T19:33:36","date_gmt":"2019-11-26T03:33:36","guid":{"rendered":"http:\/\/modulesafari.com\/?p=305"},"modified":"2019-12-01T19:25:55","modified_gmt":"2019-12-02T03:25:55","slug":"logrus","status":"publish","type":"post","link":"http:\/\/modulesafari.com\/logrus\/","title":{"rendered":"Logrus; a structured logger for Go"},"content":{"rendered":"\n\n\n[et_pb_section fb_built=”1″ _builder_version=”3.22″][et_pb_row _builder_version=”4.0.6″][et_pb_column type=”4_4″ _builder_version=”4.0.6″][et_pb_text _builder_version=”4.0.7″ text_text_color=”#000000″ text_font_size=”16px” hover_enabled=”0″]

Logrus is a structured logger for Golang, which offers modularity, flexibility, and compatibility (github<\/a>). Most projects can switch over to using logrus with a single Linux command. With an incredibly small learning curve and a plethora of extensions, logrus could be the right choice for your project.<\/p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=”4.0.6″][et_pb_column type=”4_4″ _builder_version=”4.0.6″][et_pb_text _builder_version=”4.0.6″ text_text_color=”#000000″ text_font_size=”16px”]

Hello World<\/h2>\n

Logrus is one of the easiest hello world’s you can find, here it is, in a basically a single line of code.<\/p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=”4.0.6″][et_pb_column type=”4_4″ _builder_version=”4.0.6″][et_pb_text _builder_version=”4.0.6″]

\npackage main\n\nimport(\n\t\"github.com\/sirupsen\/logrus\"\n)\n\nfunc main(){\n\tlogrus.WithFields(logrus.Fields{\n        \t\"foo\":\"bar\"}).Info(\"hello world\")\n}\n\n<\/pre>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=”4.0.6″][et_pb_column type=”4_4″ _builder_version=”4.0.6″][et_pb_text _builder_version=”4.0.6″ text_text_color=”#000000″ text_font_size=”16px”]

Injection <\/h2>\nOne of the places where logrus shines the brightest is its ability to be swapped into a codebase. You can easily change the global logger, which can be optimal for older, large codebases, since injecting a logger would not be reasonable. [\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=”4.0.6″][et_pb_column type=”4_4″ _builder_version=”4.0.6″][et_pb_text _builder_version=”4.0.6″ text_text_color=”#000000″ text_font_size=”16px”]
\npackage main\n\nimport (\n\tlog \"github.com\/sirupsen\/logrus\"\n)\n\ntype msFormater struct{}\n\nfunc (mf msFormater) Format(entry *log.Entry) ([]byte, error) {\n\tentry.Data[\"module\"] = \"safari\"\n\n\tformatter := log.TextFormatter{}\n\treturn formatter.Format(entry)\n}\n\nfunc main() {\n\tlog.SetFormatter(msFormater{})\n\tlog.SetLevel(log.DebugLevel)\n\tlog.Info(\"hello\")\n}\n<\/pre>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=”4.0.7″][et_pb_column type=”4_4″ _builder_version=”4.0.7″][et_pb_text _builder_version=”4.0.7″]

Benchmark<\/h2>\n

While Logrus offers significantly more features than the built-in log package, it is also important to take performance into account. For this benchmark, I will be testing 4 logging cases: large string, map, map with small members, and large string with caller reporting. The code used for this benchmark can be found here<\/a>.<\/p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=”4.0.7″][et_pb_column type=”4_4″ _builder_version=”4.0.7″][et_pb_text _builder_version=”4.0.7″]

BenchmarkLogrus-16                   \t  358696      3222 ns\/op\nBenchmarkLog-16                      \t 4048160       330 ns\/op\nBenchmarkLogrusMap-16                \t  331330      3523 ns\/op\nBenchmarkLogMap-16                   \t  638674      2005 ns\/op\nBenchmarkLogrusMapSmallMembers-16    \t  326095      3625 ns\/op\nBenchmarkLogMapSmallMembers-16       \t  624159      1935 ns\/op\nBenchmarkLogrusCallerReport-16       \t  181448      6657 ns\/op\nBenchmarkLogCallerReport-16          \t 1246078      1024 ns\/op\n<\/pre>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=”4.0.7″][et_pb_column type=”4_4″ _builder_version=”4.0.7″][et_pb_text _builder_version=”4.0.7″]

The built-in log parser was able to beat out logrus by a factor of 10:1 when it comes to logging pure text via the Print<\/code> function call. As the complexity increases, Logrus gains traction against the build-in package. When logging a map, Logrus managed to get all the way down to a 1.75:1 ratio. Now, I wonder if Logrus would be able to beat out the default logger if we leverage this to its advantage. So, I put it in the most minimal mode I could find, and then ran it on a map with 1000 members.\u00a0<\/p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=”4.0.7″][et_pb_column type=”4_4″ _builder_version=”4.0.7″][et_pb_text _builder_version=”4.0.7″]

BenchmarkLogrusBestCase-16           \t    1518    759788 ns\/op\nBenchmarkLogBestCase-16              \t    1750    683142 ns\/op\n<\/pre>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=”4.0.7″][et_pb_column type=”4_4″ _builder_version=”4.0.7″][et_pb_text _builder_version=”4.0.7″]

Sadly, it seems like the default logger will always have a slight performance advantage over Logrus. The best result I was able to produce was a 1.1:1.0 ratio, which isn’t bad. However, this was done under very artificial conditions, having all of the features disabled. From the results, it is fairly safe to say that the difference in performance mainly results from the extra bells and whistles provided by the library. <\/p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=”4.0.7″][et_pb_column type=”4_4″ _builder_version=”4.0.7″][et_pb_text _builder_version=”4.0.7″]

Personally, despite the extra overhead, I have found the additional features to be incredibly useful. Pluggable formatting makes it extremely easy to be compliant with any log analysis platform. Additionally, the ability to have different verbosity levels is incredibly helpful for reducing the cost of your log ingestion pipeline. <\/p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][\/et_pb_section]\n\n\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":464,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"on","_et_pb_old_content":"\n

<\/p>\n\n\n\n

Advantages<\/h2>\n","_et_gb_content_width":""},"categories":[6],"tags":[9,12,11,10],"yst_prominent_words":[139,95,130,140,92,138,93,131,137,136,129,97,127,99,133,82,128,134,132,135],"yoast_head":"\nLogrus; a structured logger for Go - Module Safari<\/title>\n<meta name=\"description\" content=\"Logrus is a structured logger for Golang, which offers modularity, flexibility, and compatibility. Read more about Logrus here.\" \/>\n<meta name=\"robots\" content=\"index, follow\" \/>\n<meta name=\"googlebot\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<meta name=\"bingbot\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"http:\/\/modulesafari.com\/logrus\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Logrus; a structured logger for Go - Module Safari\" \/>\n<meta property=\"og:description\" content=\"Logrus is a structured logger for Golang, which offers modularity, flexibility, and compatibility. Read more about Logrus here.\" \/>\n<meta property=\"og:url\" content=\"http:\/\/modulesafari.com\/logrus\/\" \/>\n<meta property=\"og:site_name\" content=\"Module Safari\" \/>\n<meta property=\"article:published_time\" content=\"2019-11-26T03:33:36+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-12-02T03:25:55+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/modulesafari.com\/wp-content\/uploads\/2019\/11\/logrus2.png\" \/>\n\t<meta property=\"og:image:width\" content=\"615\" \/>\n\t<meta property=\"og:image:height\" content=\"542\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"http:\/\/modulesafari.com\/#organization\",\"name\":\"Module Safari\",\"url\":\"http:\/\/modulesafari.com\/\",\"sameAs\":[],\"logo\":{\"@type\":\"ImageObject\",\"@id\":\"http:\/\/modulesafari.com\/#logo\",\"inLanguage\":\"en-US\",\"url\":\"http:\/\/modulesafari.com\/wp-content\/uploads\/2019\/11\/PNG-Logo-02-not-transparent.png\",\"width\":2026,\"height\":530,\"caption\":\"Module Safari\"},\"image\":{\"@id\":\"http:\/\/modulesafari.com\/#logo\"}},{\"@type\":\"WebSite\",\"@id\":\"http:\/\/modulesafari.com\/#website\",\"url\":\"http:\/\/modulesafari.com\/\",\"name\":\"Module Safari\",\"description\":\"development simplified\",\"publisher\":{\"@id\":\"http:\/\/modulesafari.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"http:\/\/modulesafari.com\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"http:\/\/modulesafari.com\/logrus\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"http:\/\/modulesafari.com\/wp-content\/uploads\/2019\/11\/logrus2.png\",\"width\":615,\"height\":542,\"caption\":\"logrus\"},{\"@type\":\"WebPage\",\"@id\":\"http:\/\/modulesafari.com\/logrus\/#webpage\",\"url\":\"http:\/\/modulesafari.com\/logrus\/\",\"name\":\"Logrus; a structured logger for Go - Module Safari\",\"isPartOf\":{\"@id\":\"http:\/\/modulesafari.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"http:\/\/modulesafari.com\/logrus\/#primaryimage\"},\"datePublished\":\"2019-11-26T03:33:36+00:00\",\"dateModified\":\"2019-12-02T03:25:55+00:00\",\"description\":\"Logrus is a structured logger for Golang, which offers modularity, flexibility, and compatibility. Read more about Logrus here.\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"http:\/\/modulesafari.com\/logrus\/\"]}]},{\"@type\":\"Article\",\"@id\":\"http:\/\/modulesafari.com\/logrus\/#article\",\"isPartOf\":{\"@id\":\"http:\/\/modulesafari.com\/logrus\/#webpage\"},\"author\":{\"@id\":\"http:\/\/modulesafari.com\/#\/schema\/person\/a31876f85a9f031cf62afd4e79f746aa\"},\"headline\":\"Logrus; a structured logger for Go\",\"datePublished\":\"2019-11-26T03:33:36+00:00\",\"dateModified\":\"2019-12-02T03:25:55+00:00\",\"commentCount\":0,\"mainEntityOfPage\":{\"@id\":\"http:\/\/modulesafari.com\/logrus\/#webpage\"},\"publisher\":{\"@id\":\"http:\/\/modulesafari.com\/#organization\"},\"image\":{\"@id\":\"http:\/\/modulesafari.com\/logrus\/#primaryimage\"},\"keywords\":\"golang,library,logging,logrus\",\"articleSection\":\"Golang\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"http:\/\/modulesafari.com\/logrus\/#respond\"]}]},{\"@type\":[\"Person\"],\"@id\":\"http:\/\/modulesafari.com\/#\/schema\/person\/a31876f85a9f031cf62afd4e79f746aa\",\"name\":\"Nathaniel Blakely\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"http:\/\/modulesafari.com\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"http:\/\/1.gravatar.com\/avatar\/1d85a4c5bf257b6a8972ab9bbaee0b51?s=96&d=mm&r=g\",\"caption\":\"Nathaniel Blakely\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","_links":{"self":[{"href":"http:\/\/modulesafari.com\/wp-json\/wp\/v2\/posts\/305"}],"collection":[{"href":"http:\/\/modulesafari.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/modulesafari.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/modulesafari.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/modulesafari.com\/wp-json\/wp\/v2\/comments?post=305"}],"version-history":[{"count":27,"href":"http:\/\/modulesafari.com\/wp-json\/wp\/v2\/posts\/305\/revisions"}],"predecessor-version":[{"id":684,"href":"http:\/\/modulesafari.com\/wp-json\/wp\/v2\/posts\/305\/revisions\/684"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/modulesafari.com\/wp-json\/wp\/v2\/media\/464"}],"wp:attachment":[{"href":"http:\/\/modulesafari.com\/wp-json\/wp\/v2\/media?parent=305"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/modulesafari.com\/wp-json\/wp\/v2\/categories?post=305"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/modulesafari.com\/wp-json\/wp\/v2\/tags?post=305"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"http:\/\/modulesafari.com\/wp-json\/wp\/v2\/yst_prominent_words?post=305"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}