simple_structured_logger 0.1.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 37a960d5ba5cba7d48661a92378a88278af39dfb
4
- data.tar.gz: 59d65009423e48bc513e640d859521fcf1e30cbe
2
+ SHA256:
3
+ metadata.gz: 824ec497606b6c639fdc7209c9854243512457bb7b97bc3ae3b6300354f85916
4
+ data.tar.gz: 56bdbf5858c33164a08ec88ee96cb0842c8f11a2caeef1123af14f3a2b0a73f7
5
5
  SHA512:
6
- metadata.gz: acdafee1c25ef8d234488ea38b10c93f436d4a2e860bff853ed02cc417b2c89ab22a8986e7ee1c1598a1ad1c4a36757d4aa081bd0b41d0370335d0aab334e7dd
7
- data.tar.gz: 8a9af6c2ce6b84b4e9e1c53ee1d22b710ad9caafa6d38de5c1c8991bdfbd094bfd34869f59e72520aa389ef06fbcecb9ed44fb5dac84223c6c79dcd930b18af7
6
+ metadata.gz: 8296498d2355f715ccc7a8b089f3129ed39688ebb8503e940f1b729d18d754142878524c48f3ab9cc8221910be0ea6200259ad9c1b1d4fa994f8e2dcab363ad2
7
+ data.tar.gz: 384a55748e300dcc7903be2609094af12fd88a4e2d3c58abf5646fb819314e9cb68b034c25890c2562355fe26babcd89fc422d617fd3373dff255ff0dc6b9ab9
@@ -0,0 +1,7 @@
1
+ # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
2
+ version: 2
3
+ updates:
4
+ - package-ecosystem: "bundler"
5
+ directory: "/" # Location of package manifests
6
+ schedule:
7
+ interval: "monthly"
@@ -0,0 +1,59 @@
1
+ name: "CodeQL"
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ # The branches below must be a subset of the branches above
8
+ branches: [ master ]
9
+ schedule:
10
+ - cron: '24 16 * * 1'
11
+
12
+ jobs:
13
+ analyze:
14
+ name: Analyze
15
+ runs-on: ubuntu-latest
16
+ permissions:
17
+ actions: read
18
+ contents: read
19
+ security-events: write
20
+
21
+ strategy:
22
+ fail-fast: false
23
+ matrix:
24
+ language: [ 'ruby' ]
25
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
26
+ # Learn more about CodeQL language support at https://git.io/codeql-language-support
27
+
28
+ steps:
29
+ - name: Checkout repository
30
+ uses: actions/checkout@v2
31
+
32
+ # Initializes the CodeQL tools for scanning.
33
+ - name: Initialize CodeQL
34
+ uses: github/codeql-action/init@v1
35
+ with:
36
+ languages: ${{ matrix.language }}
37
+ # If you wish to specify custom queries, you can do so here or in a config file.
38
+ # By default, queries listed here will override any specified in a config file.
39
+ # Prefix the list here with "+" to use these queries and those in the config file.
40
+ # queries: ./path/to/local/query, your-org/your-repo/queries@main
41
+
42
+ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
43
+ # If this step fails, then you should remove it and run the build manually (see below)
44
+ - name: Autobuild
45
+ uses: github/codeql-action/autobuild@v1
46
+
47
+ # ℹ️ Command-line programs to run using the OS shell.
48
+ # 📚 https://git.io/JvXDl
49
+
50
+ # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
51
+ # and modify them (or add more) to build your code if your project
52
+ # uses a compiled language
53
+
54
+ #- run: |
55
+ # make bootstrap
56
+ # make release
57
+
58
+ - name: Perform CodeQL Analysis
59
+ uses: github/codeql-action/analyze@v1
@@ -0,0 +1,33 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: Ruby
9
+
10
+ on:
11
+ push:
12
+ branches: [ master ]
13
+ pull_request:
14
+ branches: [ master ]
15
+
16
+ jobs:
17
+ test:
18
+
19
+ runs-on: ubuntu-latest
20
+ strategy:
21
+ matrix:
22
+ ruby-version: ['2.6', '2.7', '3.0', '3.1']
23
+
24
+ steps:
25
+ - uses: actions/checkout@v2
26
+ - name: Set up Ruby
27
+ uses: ruby/setup-ruby@v1
28
+ with:
29
+ ruby-version: ${{ matrix.ruby-version }}
30
+ bundler-cache: true
31
+ - name: Run tests
32
+ run: bundle exec rake
33
+
data/.gitignore CHANGED
@@ -8,3 +8,4 @@
8
8
  /spec/reports/
9
9
  /tmp/
10
10
  /vendor/bundle
11
+ /*.gem
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 3.1.1
data/Gemfile CHANGED
@@ -1,4 +1,2 @@
1
1
  source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in simple_structured_logger.gemspec
4
2
  gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Michael Bianco
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 all
13
+ 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 THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -1,22 +1,109 @@
1
+ [![Ruby](https://github.com/iloveitaly/simple_structured_logger/actions/workflows/ruby.yml/badge.svg)](https://github.com/iloveitaly/simple_structured_logger/actions/workflows/ruby.yml)
2
+ [![gem](https://img.shields.io/gem/v/simple_structured_logger.svg)](https://rubygems.org/gems/simple_structured_logger)
3
+
1
4
  # SimpleStructuredLogger
2
5
 
3
- Dead-simple structured logging in ruby with a dead-simple codebase. That's it.
6
+ Dead-simple structured logging in ruby with a dead-simple codebase. No dependencies, everything logs to stdout, and simple hooks to customize. That's it.
4
7
 
5
8
  ```ruby
6
9
  gem 'simple_structured_logger'
7
10
  ```
8
11
 
12
+ ## Usage
13
+
14
+ You can use this logger anywhere. Class methods, instance methods, use it as a logger for libraries, etc.
15
+
16
+ Some examples:
17
+
18
+ ```ruby
19
+ # in a console or simple script
20
+ include SimpleStructuredLogger
21
+ log.info 'core message', key: Time.now.to_i
22
+
23
+ # in class & instance methods
24
+ class LoggingInModule
25
+ include SimpleStructuredLogger
26
+
27
+ def self.log_something
28
+ log.info 'including the module enables a class and instance method', key: Time.now.to_i
29
+ end
30
+
31
+ def log_something_else
32
+ log.info 'the class and instance method share the same logging context', key: Time.now.to_i
33
+ end
34
+ end
35
+
36
+ # So, how do I set the context? How can I customize how it's set?
37
+ SimpleStructuredLogger.configure do
38
+ expand_context do |context|
39
+ # you can pass in a object and use `expand_context` to extract the relevant keys
40
+ if context[:user]
41
+ context[:user_id] = context[:user].id
42
+ context[:user_name] = context[:user].name
43
+ end
44
+
45
+ context
46
+ end
47
+ end
48
+
49
+ class ExampleJob
50
+ def perform(user_id)
51
+ user = get_user(user_id, job_argument)
52
+ log.set_context(user: user, job: self.class, job_argument: job_argument)
53
+ log.info 'the log will contain the user_id, job_argument, and job class'
54
+
55
+ # you can also add additional default pairs without resetting context
56
+ log.default_tags[:something] = 'else'
57
+ end
58
+ end
59
+
60
+ # Can you pass object arguments as values and automatically expand them? Well, yes, you can!
61
+ SimpleStructuredLogger.configure do
62
+ expand_log do |tags, default_tags|
63
+ if tags[:stripe_resource] && tags[:stripe_resource].respond_to?(:id)
64
+ stripe_resource = tags.delete(:stripe_resource)
65
+ tags[:stripe_resource_id] = stripe_resource.id
66
+ tags[:stripe_resource_type] = stripe_resource.class.to_s
67
+ end
68
+
69
+ # this is a really nice pattern I like to use. The `metric` key can trigger a call out to your observability tooling
70
+ if tags[:metric]
71
+ dimensions = default_tags.slice(:stripe_user_id, :other_default_tag)
72
+ metrics.track_counter(tags[:metric], dimensions: dimensions)
73
+ end
74
+
75
+ tags
76
+ end
77
+ end
78
+
79
+ # want simple formatting? You got it!
80
+ SimpleStructuredLogger.logger.formatter = proc do |severity, _datetime, _progname, msg|
81
+ "#{severity}: #{msg}\n"
82
+ end
83
+
84
+ # Configure the logger directly if you need to
85
+ SimpleStructuredLogger.logger.level(Logger::INFO)
86
+ ```
87
+
88
+ Want to change the log level quickly? Without modifying source?
89
+
90
+ ```shell
91
+ LOG_LEVEL=DEBUG ruby your_script.rb
92
+
93
+ # case does not matter
94
+ LOG_LEVEL=info ruby your_script.rb
95
+ ```
96
+
9
97
  ## Design Goals
10
98
 
11
99
  * Extremely simple codebase that's easy to read and override
12
- * Structured logging that reads nicely
100
+ * Structured logging that reads nicely and is easy to filter using grep or something like Papertrail
13
101
  * Ability to easily set context, and expand context with user-configurable hook
14
102
  * Ability to easily add structured log pre-processing. I want to be able to pass
15
- in an object specific to my application and for the relavent important keys to
103
+ in an object specific to my application and for the relevant important keys to
16
104
  be expanded automatically.
17
105
  * `Rails.logger = SimpleStructuredLogger.new(STDOUT)`
18
- * Not designed around massive systems or scale
19
- * Don't support multiple log destinations
106
+ * Not designed around massive systems or scale: no JSON logging, multiple log destinations, and other fanciness.
20
107
  * Don't build in fancy pre-processing for errors or other common ruby objects
21
108
 
22
109
  ### Opinionated Devops Setup
@@ -32,6 +119,11 @@ gem 'simple_structured_logger'
32
119
  * https://github.com/asenchi/scrolls
33
120
  * https://github.com/stripe/chalk-log
34
121
  * https://github.com/nishidayuya/structured_logger
122
+ * https://github.com/rocketjob/semantic_logger
123
+
124
+ ## Related
125
+
126
+ * https://github.com/roidrage/lograge
35
127
 
36
128
  ## Why is structured logging important?
37
129
 
@@ -41,14 +133,14 @@ gem 'simple_structured_logger'
41
133
  ## What about Rail's tagged logging?
42
134
 
43
135
  Tagged logging is not structured logging. I want to be able to search through
44
- PaperTrail and easily grab an audit trail for a specific context, i.e. `the_job=FailingJob the_user=1`.
45
-
46
- ## Usage
47
-
48
- TODO: Write usage instructions here
136
+ PaperTrail/Splunk/etc and easily grab an audit trail for a specific context, i.e. `the_job=FailingJob the_user=1`.
49
137
 
50
138
  ## Testing
51
139
 
52
140
  ```
53
141
  bundle exec rake
54
142
  ```
143
+
144
+ ## TODO
145
+
146
+ - [ ] Support logs as blocks?
@@ -2,6 +2,14 @@ require 'logger'
2
2
  require 'singleton'
3
3
 
4
4
  module SimpleStructuredLogger
5
+ def self.configure(&block)
6
+ SimpleStructuredLogger::Configuration.instance_eval(&block)
7
+ end
8
+
9
+ def self.logger
10
+ SimpleStructuredLogger::Writer.instance.logger
11
+ end
12
+
5
13
  def log
6
14
  SimpleStructuredLogger::Writer.instance
7
15
  end
@@ -13,25 +21,27 @@ module SimpleStructuredLogger
13
21
  SimpleStructuredLogger::Writer.instance
14
22
  end
15
23
  end
16
-
17
24
  end
18
25
 
19
26
  module Configuration
20
27
  extend self
21
28
 
29
+ @expand_context = nil
30
+ @expand_log = nil
31
+
22
32
  def expand_context(&block)
23
33
  if block.nil?
24
- @expand_context = block
25
- else
26
34
  @expand_context
35
+ else
36
+ @expand_context = block
27
37
  end
28
38
  end
29
39
 
30
40
  def expand_log(&block)
31
41
  if block.nil?
32
- @expand_log = block
33
- else
34
42
  @expand_log
43
+ else
44
+ @expand_log = block
35
45
  end
36
46
  end
37
47
  end
@@ -39,11 +49,21 @@ module SimpleStructuredLogger
39
49
  class Writer
40
50
  include Singleton
41
51
 
42
- attr_reader :default_tags, :logger
52
+ attr_accessor :default_tags, :logger
43
53
 
44
54
  def initialize
45
55
  @logger = ::Logger.new(STDOUT)
46
56
  @default_tags = {}
57
+
58
+ set_log_level_from_environment
59
+ end
60
+
61
+ def set_log_level_from_environment
62
+ env_log_level = ENV['LOG_LEVEL']
63
+
64
+ if !env_log_level.nil? && Logger::Severity.const_defined?(env_log_level.upcase)
65
+ @logger.level = Logger::Severity.const_get(env_log_level.upcase)
66
+ end
47
67
  end
48
68
 
49
69
  def reset_context!
@@ -53,8 +73,8 @@ module SimpleStructuredLogger
53
73
  def set_context(context)
54
74
  reset_context!
55
75
 
56
- if self.respond_to?(:expand_context)
57
- context = self.expand_context(context)
76
+ if SimpleStructuredLogger::Configuration.expand_context
77
+ context = SimpleStructuredLogger::Configuration.expand_context.call(context)
58
78
  end
59
79
 
60
80
  @default_tags.merge!(context)
@@ -76,17 +96,15 @@ module SimpleStructuredLogger
76
96
  @logger.warn("#{msg}: #{stringify_tags(opts)}")
77
97
  end
78
98
 
79
- private
80
-
81
- def stringify_tags(additional_tags)
82
- additional_tags = additional_tags.dup
83
-
84
- if self.respond_to?(:expand_log)
85
- additional_tags = self.expand_log(additional_tags)
86
- end
99
+ private def stringify_tags(additional_tags)
100
+ additional_tags = additional_tags.dup
87
101
 
88
- @default_tags.merge(additional_tags).map { |k,v| "#{k}=#{v}" }.join(' ')
102
+ if SimpleStructuredLogger::Configuration.expand_log
103
+ additional_tags = SimpleStructuredLogger::Configuration.expand_log.call(additional_tags, self.default_tags)
89
104
  end
90
105
 
106
+ @default_tags.merge(additional_tags).map {|k, v| "#{k}=#{v}" }.join(' ')
107
+ end
108
+
91
109
  end
92
110
  end
@@ -4,20 +4,19 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "simple_structured_logger"
7
- spec.version = '0.1.3'
7
+ spec.version = '1.0.0'
8
8
  spec.authors = ["Michael Bianco"]
9
- spec.email = ["mike@cliffsidemedia.com"]
9
+ spec.email = ["mike@mikebian.co"]
10
+ spec.licenses = ['MIT']
10
11
 
11
- spec.summary = "Dead-simple structured logging in ruby with a dead-simple codebase."
12
- # spec.description = %q{TODO: Write a longer description or delete this line.}
12
+ spec.summary = "Dead-simple structured logging in ruby with a simple codebase"
13
13
  spec.homepage = "https://github.com/iloveitaly/simple_structured_logger"
14
14
 
15
15
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
- spec.bindir = "exe"
17
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
16
+ spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
17
  spec.require_paths = ["lib"]
19
18
 
20
- spec.add_development_dependency "bundler", "~> 1.11"
21
- spec.add_development_dependency "rake", "~> 10.0"
22
- spec.add_development_dependency "minitest", "~> 5.0"
19
+ spec.add_development_dependency "bundler", "~> 2.3.10"
20
+ spec.add_development_dependency "rake", "~> 13.0.6"
21
+ spec.add_development_dependency "minitest", "~> 5.15"
23
22
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_structured_logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Bianco
8
- autorequire:
9
- bindir: exe
8
+ autorequire:
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-27 00:00:00.000000000 Z
11
+ date: 2022-03-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,51 +16,58 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.11'
19
+ version: 2.3.10
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.11'
26
+ version: 2.3.10
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: 13.0.6
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: 13.0.6
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: minitest
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '5.0'
47
+ version: '5.15'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '5.0'
55
- description:
54
+ version: '5.15'
55
+ description:
56
56
  email:
57
- - mike@cliffsidemedia.com
58
- executables: []
57
+ - mike@mikebian.co
58
+ executables:
59
+ - console
60
+ - setup
59
61
  extensions: []
60
62
  extra_rdoc_files: []
61
63
  files:
64
+ - ".github/dependabot.yml"
65
+ - ".github/workflows/codeql-analysis.yml"
66
+ - ".github/workflows/ruby.yml"
62
67
  - ".gitignore"
68
+ - ".tool-versions"
63
69
  - Gemfile
70
+ - LICENSE
64
71
  - README.md
65
72
  - Rakefile
66
73
  - bin/console
@@ -68,9 +75,10 @@ files:
68
75
  - lib/simple_structured_logger.rb
69
76
  - simple_structured_logger.gemspec
70
77
  homepage: https://github.com/iloveitaly/simple_structured_logger
71
- licenses: []
78
+ licenses:
79
+ - MIT
72
80
  metadata: {}
73
- post_install_message:
81
+ post_install_message:
74
82
  rdoc_options: []
75
83
  require_paths:
76
84
  - lib
@@ -85,9 +93,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
93
  - !ruby/object:Gem::Version
86
94
  version: '0'
87
95
  requirements: []
88
- rubyforge_project:
89
- rubygems_version: 2.6.4
90
- signing_key:
96
+ rubygems_version: 3.3.7
97
+ signing_key:
91
98
  specification_version: 4
92
- summary: Dead-simple structured logging in ruby with a dead-simple codebase.
99
+ summary: Dead-simple structured logging in ruby with a simple codebase
93
100
  test_files: []