lumberjack_capture_device 1.0.1 → 1.1.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
2
  SHA256:
3
- metadata.gz: 35d8ad5610c0d02fbc90b22a141d58aac09de8f98dcbfa85ed71c69d90e3aae2
4
- data.tar.gz: 96657c5cb4a6dfc2431b8fe1689469950f5f144db64f29413df79baa1bf18aeb
3
+ metadata.gz: 66cd8d5b6e75a04f7c7d0ef12469c999138d102e414be22a6f97b08bb9bf1cbd
4
+ data.tar.gz: 0b783ca27c07301ac2c16dbf56f181260f68ae08aa8b6ee3afed33f5f680cca4
5
5
  SHA512:
6
- metadata.gz: f22f7e086c58df3f4fc180b8d84df5bb49c7fc3966f578ae644b8a9c95ca7a143ad71f82f277622af4607377e9ea7219af10f07af6d38bbd07d674a4e3746a9c
7
- data.tar.gz: 706cf53df406ca2702b314d89b9f38e9d55c764e667a852a7c2e08fc30e808315a5199e7f603acab6af8748fb15b078da69b9985a10d60c16806b6569e43f48b
6
+ metadata.gz: 82c1cac6a0b4c075a464b3abe5bb7b0ce4ebb8d6083f50d9efd12a966b45105fed43b330f15a4a7da6d455107af6853c67713f95792222a156435539b0dbd661
7
+ data.tar.gz: a5e43d1232499898e019db99581dce01e7e1ca15919a0b0c23fb1e45a4b6a28714177d5418c6b1fa882057544ed2c69067ca80130690bd564be2c9409e0d73fc
data/CHANGELOG.md CHANGED
@@ -4,10 +4,20 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## 1.1.0
8
+
9
+ ### Added
10
+
11
+ - Support for matching tag structures in log entries regardless of if they are specified with dot notation or nested tags. So "foo.bar" will match a tag with the structure `{foo: {bar: "value"}}` or `{"foo.bar" => value}`.
12
+
7
13
  ## 1.0.1
14
+
8
15
  ### Added
16
+
9
17
  - Ruby 3 compatibility
10
18
 
11
19
  ## 1.0.0
20
+
12
21
  ### Added
22
+
13
23
  - Initial release.
data/README.md CHANGED
@@ -1,26 +1,27 @@
1
+ # Lumberjack Capture Device
2
+
1
3
  [![Continuous Integration](https://github.com/bdurand/lumberjack_capture_device/actions/workflows/continuous_integration.yml/badge.svg)](https://github.com/bdurand/lumberjack_capture_device/actions/workflows/continuous_integration.yml)
2
4
  [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
5
+ [![Gem Version](https://badge.fury.io/rb/lumberjack_capture_device.svg)](https://badge.fury.io/rb/lumberjack_capture_device)
3
6
 
4
- # Lumberjack Capture Device
5
-
6
- This is a plugin device for the [lumberjack gem](https://github.com/bdurand/lumberjack) that enables capturing log messages in a test suite so that assertions can be made against them. It provides and easy and stable method of testing that specific log messages are being sent to a logger.
7
+ This is a plugin device for the [lumberjack gem](https://github.com/bdurand/lumberjack) that enables capturing log messages in a test suite so that assertions can be made against them. It provides an easy and stable method of testing that specific log messages are being sent to a logger.
7
8
 
8
- Using mocks and stubs on a logger to test that it receives messages can make for a brittle test suite since there can a wide variety of code writing messages to logs and your test suite may have a higher log level turned on causing it skip messages at a lower level.
9
+ Using mocks and stubs on a logger to test that it receives messages can make for a brittle test suite since there can be a wide variety of code writing messages to logs and your test suite may have a higher log level turned on causing it to skip messages at a lower level.
9
10
 
10
- For instance, this rspec code can break if any of the code called by the `do_something` writes a different info log message:
11
+ For instance, this RSpec code can break if any of the code called by `do_something` writes a different info log message:
11
12
 
12
13
  ```ruby
13
14
  do_something
14
- expect(Rail.logger).to receive(:info).with("Something happened")
15
+ expect(Rails.logger).to receive(:info).with("Something happened")
15
16
  ```
16
17
 
17
18
  It will also break if the test suite logger has the log level set to `warn` or higher since it will then skip all info and debug messages.
18
19
 
19
20
  ## Usage
20
21
 
21
- You can call the `Lumberjack::CaptureDevice.capture` method to override a logger so that it will capture log entries within a block to an in memory buffer. This method will yield the capturing log device as well as return it as the result of the method. The log level will also be temporarily set to debug within the block, so you can capture all log messages without having to change the log level for the entire test suite.
22
+ You can call the `Lumberjack::CaptureDevice.capture` method to temporarily override a logger so that it will capture log entries within a block to an in-memory buffer. This method will yield the capturing log device and also return it as the result of the method. The log level will also be temporarily set to debug within the block, so you can capture all log messages without having to change the log level for the entire test suite.
22
23
 
23
- You can use the `include?` method on the log device to determine if specific log entries were made. This would be the equivalent code to the above rspec test, but without the brittleness of mocking method calls:
24
+ You can use the `include?` method on the log device to determine if specific log entries were made. This would be the equivalent code to the above RSpec test, but without the brittleness of mocking method calls:
24
25
 
25
26
  ```ruby
26
27
  Lumberjack::CaptureDevice.capture(Rails.logger) do |logs|
@@ -44,12 +45,47 @@ assert(logs.include?(level: :info, message: "Something happened"))
44
45
  ```
45
46
 
46
47
 
47
- You can filter the logs on level, message, and tags. The level option can take either a label (i.e. `:warn`) or a constant (i.e. `Logger::WARN`). The message filter can be either an exact string, or a regular expression or any matcher supported by your test library. The tags argument can match tags with a Hash mapping tag names to the matcher.
48
+ You can filter the logs on level, message, and tags.
49
+
50
+ - The level option can take either a label (i.e. `:warn`) or a constant (i.e. `Logger::WARN`).
51
+ - The message filter can be either an exact string or a regular expression, or any matcher supported by your test library.
52
+ - The tags argument can match tags with a Hash mapping tag names to the matcher values. If tags are nested, you can use dot notation on tag names to reference nested tags.
48
53
 
49
54
  ```ruby
50
55
  expect(logs).to include(level: :info, message: /something/i)
51
56
  expect(logs).to include(level: Logger::INFO, tags: {foo: "bar"})
52
57
  expect(logs).to include(tags: {foo: anything, count: {one: 1}})
58
+ expect(logs).to include(tags: {foo: anything, "count.one" => 1})
59
+ ```
60
+
61
+ You can also use the `Lumberjack::CaptureDevice#extract` method with the same arguments as used by `include?` to extract all log entries that match the filters. You can get all of the log entries with `Lumberjack::CaptureDevice#buffer`.
62
+
63
+ ## Installation
64
+
65
+ Add this line to your application's Gemfile:
66
+
67
+ ```ruby
68
+ gem 'lumberjack_capture_device'
53
69
  ```
54
70
 
55
- You can also use the `Lumberjack::CaptureDevice#extract` method with the same arguments as used by `include?` to grab all lines that match the filters. And finally, you can access all the log entries with `Lumberjack::CaptureDevice#buffer`.
71
+ And then execute:
72
+
73
+ ```bash
74
+ $ bundle install
75
+ ```
76
+
77
+ Or install it yourself as:
78
+
79
+ ```bash
80
+ $ gem install lumberjack_capture_device
81
+ ```
82
+
83
+ ## Contributing
84
+
85
+ Open a pull request on GitHub.
86
+
87
+ Please use the [standardrb](https://github.com/testdouble/standard) syntax and lint your code with `standardrb --fix` before submitting.
88
+
89
+ ## License
90
+
91
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.1
1
+ 1.1.0
@@ -14,6 +14,20 @@ module Lumberjack
14
14
  # the logger. In addition, all formatters will be removed and the log level will be set
15
15
  # to debug. The device being written to be both yielded to the block as well as returned
16
16
  # by the method call.
17
+ #
18
+ # @param logger [Lumberjack::Logger] The logger to capture entries from.
19
+ # @yield [device] The block to execute while capturing log entries.
20
+ # @return [Lumberjack::CaptureDevice] The device that captured the log entries.
21
+ # @yieldparam device [Lumberjack::CaptureDevice] The device that will capture the log entries.
22
+ # @example
23
+ # Lumberjack::CaptureDevice.capture(logger) do |logs|
24
+ # logger.info("This will be captured")
25
+ # expect(logs).to include(level: :info, message: "This will be captured")
26
+ # end
27
+ #
28
+ # @example
29
+ # logs = Lumberjack::CaptureDevice.capture(logger) { logger.info("This will be captured") }
30
+ # expect(logs).to include(level: :info, message: "This will be captured")
17
31
  def capture(logger)
18
32
  device = new
19
33
  save_device = logger.device
@@ -64,14 +78,32 @@ module Lumberjack
64
78
  # ```
65
79
  # logs.include(level: :warn, message: /something happened/, tags: {duration: instance_of(Float)})
66
80
  # ```
81
+ #
82
+ # @param args [Hash] The filters to apply to the captured entries.
83
+ # @option args [String, Regexp] :message The message to match against the log entries.
84
+ # @option args [String, Symbol, Integer] :level The log level to match against the log entries.
85
+ # @option args [Hash] :tags A hash of tag names to values to match against the log entries. The tags
86
+ # will match nested tags using dot notation (e.g. `foo.bar` will match a tag with the structure
87
+ # `{foo: {bar: "value"}}`).
88
+ # @return [Boolean] True if any entries match the specified filters, false otherwise.
67
89
  def include?(args)
68
90
  !extract(**args.merge(limit: 1)).empty?
69
91
  end
70
92
 
71
93
  # Return all the captured entries that match the specified filters. These filters are
72
94
  # the same as described in the `include?` method.
95
+ #
96
+ # @param message [String, Regexp, nil] The message to match against the log entries.
97
+ # @param level [String, Symbol, Integer, nil] The log level to match against the log entries.
98
+ # @param tags [Hash, nil] A hash of tag names to values to match against the log entries. The tags
99
+ # will match nested tags using dot notation (e.g. `foo.bar` will match a tag with the structure
100
+ # `{foo: {bar: "value"}}`).
101
+ # @param limit [Integer, nil] The maximum number of entries to return. If nil, all matching entries
102
+ # will be returned.
103
+ # @return [Array<Lumberjack::Entry>] An array of log entries that match the specified filters.
73
104
  def extract(message: nil, level: nil, tags: nil, limit: nil)
74
105
  matches = []
106
+
75
107
  if level
76
108
  # Normalize the level filter to numeric values.
77
109
  level = (level.is_a?(Integer) ? level : Lumberjack::Severity.label_to_level(level))
@@ -82,13 +114,22 @@ module Lumberjack
82
114
  break if limit && matches.size >= limit
83
115
  end
84
116
  end
117
+
85
118
  matches
86
119
  end
87
120
 
88
121
  private
89
122
 
90
123
  def matched?(entry, message_filter, level_filter, tags_filter)
91
- match?(entry.message, message_filter) && match?(entry.severity, level_filter) && match_tags?(entry.tags, tags_filter)
124
+ return false unless match?(entry.message, message_filter)
125
+ return false unless match?(entry.severity, level_filter)
126
+
127
+ tags_filter = Lumberjack::Utils.expand_tags(tags_filter) if tags_filter.is_a?(Hash)
128
+ tags = Lumberjack::Utils.expand_tags(entry.tags)
129
+
130
+ return false unless match_tags?(tags, tags_filter)
131
+
132
+ true
92
133
  end
93
134
 
94
135
  def match?(value, filter)
@@ -99,16 +140,19 @@ module Lumberjack
99
140
  def match_tags?(tags, filter)
100
141
  return true unless filter
101
142
  return false unless tags
143
+
102
144
  filter.all? do |name, value_filter|
103
145
  name = name.to_s
104
146
  tag_values = tags[name]
105
147
  if tag_values.is_a?(Hash)
106
148
  if value_filter.is_a?(Hash)
107
- match_tags?(Lumberjack::Tags.stringify_keys(tag_values), value_filter)
149
+ match_tags?(tag_values, value_filter)
108
150
  else
109
151
  false
110
152
  end
111
- elsif tag_values || tags.include?(name)
153
+ elsif value_filter.nil? || (value_filter.is_a?(Array) && value_filter.empty?)
154
+ tag_values.nil? || (tag_values.is_a?(Array) && tag_values.empty?)
155
+ elsif tags.include?(name)
112
156
  match?(tag_values, value_filter)
113
157
  else
114
158
  false
@@ -8,6 +8,12 @@ Gem::Specification.new do |spec|
8
8
  spec.homepage = "https://github.com/bdurand/lumberjack_capture_device"
9
9
  spec.license = "MIT"
10
10
 
11
+ spec.metadata = {
12
+ "homepage_uri" => spec.homepage,
13
+ "source_code_uri" => spec.homepage,
14
+ "changelog_uri" => "#{spec.homepage}/blob/main/CHANGELOG.md"
15
+ }
16
+
11
17
  # Specify which files should be added to the gem when it is released.
12
18
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
13
19
  ignore_files = %w[
@@ -25,8 +31,8 @@ Gem::Specification.new do |spec|
25
31
 
26
32
  spec.require_paths = ["lib"]
27
33
 
28
- spec.required_ruby_version = ">= 2.4.0"
34
+ spec.required_ruby_version = ">= 2.5"
29
35
 
30
- spec.add_dependency "lumberjack", ">=1.1.0"
36
+ spec.add_dependency "lumberjack", ">=1.3.3"
31
37
  spec.add_development_dependency "bundler"
32
38
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lumberjack_capture_device
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Durand
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-25 00:00:00.000000000 Z
11
+ date: 2025-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lumberjack
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 1.1.0
19
+ version: 1.3.3
20
20
  type: :runtime
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.1.0
26
+ version: 1.3.3
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,7 +38,7 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- description:
41
+ description:
42
42
  email:
43
43
  - bbdurand@gmail.com
44
44
  executables: []
@@ -54,8 +54,11 @@ files:
54
54
  homepage: https://github.com/bdurand/lumberjack_capture_device
55
55
  licenses:
56
56
  - MIT
57
- metadata: {}
58
- post_install_message:
57
+ metadata:
58
+ homepage_uri: https://github.com/bdurand/lumberjack_capture_device
59
+ source_code_uri: https://github.com/bdurand/lumberjack_capture_device
60
+ changelog_uri: https://github.com/bdurand/lumberjack_capture_device/blob/main/CHANGELOG.md
61
+ post_install_message:
59
62
  rdoc_options: []
60
63
  require_paths:
61
64
  - lib
@@ -63,15 +66,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
63
66
  requirements:
64
67
  - - ">="
65
68
  - !ruby/object:Gem::Version
66
- version: 2.4.0
69
+ version: '2.5'
67
70
  required_rubygems_version: !ruby/object:Gem::Requirement
68
71
  requirements:
69
72
  - - ">="
70
73
  - !ruby/object:Gem::Version
71
74
  version: '0'
72
75
  requirements: []
73
- rubygems_version: 3.0.3
74
- signing_key:
76
+ rubygems_version: 3.4.10
77
+ signing_key:
75
78
  specification_version: 4
76
79
  summary: Testing device for the lumberjack gem that can be used for asserting messages
77
80
  have been logged in a test suite.