sw-logger 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 281f87d8270bf0e0fd23fa654ac1efec5c0c2214698b852eed450a67062f0d51
4
+ data.tar.gz: 2e47d4c7beeab382fdbf9b5e7e4103f07f7a48b7e327a3d4b14c0875e0974df7
5
+ SHA512:
6
+ metadata.gz: 1772953120523bc0cf0392065fbd1619ed5b70efc416bc427bf6494ef491349a19c3057bd809b7143ddbd3e4203482e2dad717b2db13852d73f21d1df39eb2c8
7
+ data.tar.gz: 39fe02021d4d5878c0b298d082adb93dc66545ced9f1ab6353387052040528c0873fa5ec803dab789b9f8ff01e88e54f7874bdebf542127da192bb980db04d09
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/.rubocop.yml ADDED
@@ -0,0 +1,21 @@
1
+ # The behavior of RuboCop can be controlled via the .rubocop.yml
2
+ # configuration file. It makes it possible to enable/disable
3
+ # certain cops (checks) and to alter their behavior if they accept
4
+ # any parameters. The file can be placed either in your home
5
+ # directory or in some project directory.
6
+ #
7
+ # RuboCop will start looking for the configuration file in the directory
8
+ # where the inspected file is and continue its way up to the root directory.
9
+ #
10
+ # See https://github.com/rubocop-hq/rubocop/blob/master/manual/configuration.md
11
+
12
+ Style/FrozenStringLiteralComment:
13
+ Enabled: false
14
+ Style/StringLiterals:
15
+ EnforcedStyle: double_quotes
16
+ Style/LineLength:
17
+ Enabled: true
18
+ Max: 80
19
+ Style/Documentation:
20
+ Enabled: false
21
+
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in sw-logger.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
7
+ gem "minitest", "~> 5.0"
data/Gemfile.lock ADDED
@@ -0,0 +1,21 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ sw-logger (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ minitest (5.14.0)
10
+ rake (12.3.3)
11
+
12
+ PLATFORMS
13
+ ruby
14
+
15
+ DEPENDENCIES
16
+ minitest (~> 5.0)
17
+ rake (~> 12.0)
18
+ sw-logger!
19
+
20
+ BUNDLED WITH
21
+ 2.1.4
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Kai Kuchenbecker
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # Sw::Logger
2
+
3
+ This Logger is used in SayWay's applications for context rich logging. That way we can easily extract metrics and analyze our JSON logs.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'sw-logger'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle install
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install sw-logger
20
+
21
+ ## Usage
22
+
23
+ ```ruby
24
+ # get an instance of the logger that logs to standard output
25
+ logger = Sw.logger(STDOUT)
26
+
27
+ # it follows the normal logger interface
28
+ logger.info("Hello World")
29
+ # => I, [2020-01-31T11:00:08.577103 #29982] INFO -- : Hello World
30
+
31
+ # it can be tagged
32
+ logger.tagged("MyApp") { |l| l.debug("is bug free!") }
33
+ # => D, [2020-01-31T11:00:35.585755 #29982] DEBUG -- : [MyApp] is bug free!
34
+
35
+ # you can provide context as a hash
36
+ context = {
37
+ tenant: "FooCorp",
38
+ revision: "4e0b166"
39
+ }
40
+ logger.with_context(context) { |l| l.info("Where am I?") }
41
+ # => I, [2020-01-31T11:00:58.063731 #29982] INFO -- : [tenant=FooCorp] [revision=4e0b166] Where am I?
42
+
43
+ # nested context is just dumped as is for non-json formatters
44
+ logger.with_context(foo: { bar: 42 }) { |l| l.info("Use JSON instead!") }
45
+ # => I, [2020-01-31T11:01:57.894093 #29982] INFO -- : [bar={:foo=>42}] Use JSON instead!
46
+
47
+ # you can go batshit crazy when using a json logger, anything that can be dumped to json is fair game
48
+ Sw.json_logger(STDOUT).with_context(foo: { bar: 42 }) { |l| l.info("Oooh, yeah!") }
49
+ # => {"bar":{"foo":42},"severity":"INFO","timestamp":"2020-01-31T11:27:34.848643","message":"Oooh, yeah!"}
50
+ ```
51
+
52
+ ## Development
53
+
54
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
55
+
56
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
57
+
58
+ ## Contributing
59
+
60
+ Bug reports and pull requests are welcome on GitHub at https://github.com/say-way/sw-logger.
61
+
62
+
63
+ ## License
64
+
65
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "sw/logger"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sw
4
+ module LogFormatter
5
+ class ContextualFormatter < ::Logger::Formatter
6
+ attr_accessor :tags, :context
7
+
8
+ def initialize(context: {}, tags: [])
9
+ super()
10
+ self.context = context
11
+ self.tags = tags
12
+ end
13
+
14
+ def with_context(context)
15
+ previous_context = self.context
16
+ self.context = context
17
+
18
+ yield self
19
+ ensure
20
+ self.context = previous_context
21
+ end
22
+
23
+ def with_tags(tags)
24
+ previous_tags = self.tags
25
+ self.tags = tags
26
+
27
+ yield self
28
+ ensure
29
+ self.tags = previous_tags
30
+ end
31
+
32
+ def current_tags
33
+ tags
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "sw/log_formatter/contextual_formatter"
4
+
5
+ module Sw
6
+ module LogFormatter
7
+ class DefaultFormatter < ContextualFormatter
8
+ def call(severity, time, progname, msg)
9
+ tag_string = tags.map { |tag| "[#{tag}] " }.join
10
+ context_string = context.map { |k, v| "[#{k}=#{v}] " }.join
11
+ message = tag_string + context_string + msg2str(msg)
12
+ super(severity, time, progname, message)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "sw/log_formatter/contextual_formatter"
5
+
6
+ module Sw
7
+ module LogFormatter
8
+ class JsonFormatter < ContextualFormatter
9
+ def initialize(*)
10
+ super
11
+ self.datetime_format ||= "%Y-%m-%dT%H:%M:%S.%6N"
12
+ end
13
+
14
+ def call(severity, time, progname, msg)
15
+ payload = context.merge(
16
+ severity: severity,
17
+ timestamp: format_datetime(time),
18
+ progName: progname,
19
+ tags: tags,
20
+ message: msg2str(msg)
21
+ )
22
+
23
+ JSON.dump(remove_blank_values(payload)) + "\n"
24
+ end
25
+
26
+ private
27
+
28
+ def remove_blank_values(payload)
29
+ payload.select do |_, value|
30
+ next if value.nil?
31
+
32
+ value = value.strip if value.respond_to?(:strip)
33
+ next if value.respond_to?(:empty?) && value.empty?
34
+
35
+ true
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "sw/log_formatter/contextual_formatter"
4
+
5
+ module Sw
6
+ module LogFormatter
7
+ class SimpleFormatter < ContextualFormatter
8
+ def call(_severity, _time, _progname, msg)
9
+ tag_string = tags.map { |tag| "[#{tag}] " }.join
10
+ context_string = context.map { |k, v| "[#{k}=#{v}] " }.join
11
+
12
+ tag_string + context_string + msg2str(msg) + "\n"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+
5
+ module Sw
6
+ class Logger < ::Logger
7
+ VERSION = "0.1.0"
8
+ end
9
+ end
data/lib/sw/logger.rb ADDED
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+ require "sw/logger/version"
5
+ require "sw/log_formatter/simple_formatter"
6
+ require "sw/log_formatter/json_formatter"
7
+ require "sw/log_formatter/default_formatter"
8
+
9
+ module Sw
10
+ def self.logger(*args)
11
+ Sw::Logger.new(*args)
12
+ end
13
+
14
+ def self.json_logger(*args)
15
+ Sw::Logger.new(*args).tap do |logger|
16
+ logger.formatter = Sw::LogFormatter::JsonFormatter.new
17
+ end
18
+ end
19
+
20
+ def self.simple_logger(*args)
21
+ Sw::Logger.new(*args).tap do |logger|
22
+ logger.formatter = Sw::LogFormatter::SimpleFormatter.new
23
+ end
24
+ end
25
+
26
+ class Logger < ::Logger
27
+ def initialize(*)
28
+ super
29
+ self.formatter ||= Sw::LogFormatter::DefaultFormatter.new
30
+ end
31
+
32
+ def with_context(context = {})
33
+ return dup.tap { |it| it.formatter.context = context } unless block_given?
34
+
35
+ formatter.with_context(context.to_h) { yield self }
36
+ end
37
+
38
+ def tagged(*tags)
39
+ tags = Array(tags).flatten
40
+ return dup.tap { |it| it.formatter.tags = tags } unless block_given?
41
+
42
+ formatter.with_tags(tags) { yield self }
43
+ end
44
+
45
+ private
46
+
47
+ def initialize_copy(original)
48
+ self.formatter = original.formatter.dup
49
+ end
50
+ end
51
+ end
data/sw-logger.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ require_relative "lib/sw/logger/version"
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "sw-logger"
5
+ spec.version = Sw::Logger::VERSION
6
+ spec.authors = ["Kai Kuchenbecker"]
7
+ spec.email = ["dev@sayway.com"]
8
+
9
+ spec.summary = "Context enriched logging with plain and json format."
10
+ spec.description = spec.summary
11
+ spec.homepage = "https://github.com/say-way/sw-logger"
12
+ spec.license = "MIT"
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
14
+
15
+ spec.metadata["homepage_uri"] = spec.homepage
16
+ spec.metadata["source_code_uri"] = spec.homepage
17
+
18
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
19
+ `git ls-files -z`
20
+ .split("\x0")
21
+ .reject { |f| f.match(%r{^(test|spec|features)/}) }
22
+ end
23
+ spec.require_paths = ["lib"]
24
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sw-logger
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kai Kuchenbecker
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-01-31 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Context enriched logging with plain and json format.
14
+ email:
15
+ - dev@sayway.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - ".rubocop.yml"
22
+ - Gemfile
23
+ - Gemfile.lock
24
+ - LICENSE.txt
25
+ - README.md
26
+ - Rakefile
27
+ - bin/console
28
+ - bin/setup
29
+ - lib/sw/log_formatter/contextual_formatter.rb
30
+ - lib/sw/log_formatter/default_formatter.rb
31
+ - lib/sw/log_formatter/json_formatter.rb
32
+ - lib/sw/log_formatter/simple_formatter.rb
33
+ - lib/sw/logger.rb
34
+ - lib/sw/logger/version.rb
35
+ - sw-logger.gemspec
36
+ homepage: https://github.com/say-way/sw-logger
37
+ licenses:
38
+ - MIT
39
+ metadata:
40
+ homepage_uri: https://github.com/say-way/sw-logger
41
+ source_code_uri: https://github.com/say-way/sw-logger
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 2.3.0
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubygems_version: 3.0.3
58
+ signing_key:
59
+ specification_version: 4
60
+ summary: Context enriched logging with plain and json format.
61
+ test_files: []