minato_logger 0.2.19 → 0.3.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: f523fd2c4e6ebb0bc2ef9cad19a5e0a0f48f29e4f27ff81b98bce11a848ed768
4
- data.tar.gz: 0e2c98f92018bd6cdc91eb7b8e60fec03e6e34d28d4e4afdca7f54e09c853115
3
+ metadata.gz: 06f80153de91decba9f1d6a522d0b1e4d9b960ad25e73c233a0bc72631d86a18
4
+ data.tar.gz: 68ea47ede5ecb8d9c2dafa98730113433a8a8bde2195d1549b08e7411f8d9c08
5
5
  SHA512:
6
- metadata.gz: 113a8a0543e35113868f8dff23bcf942c5c5b089fab83eaeff0c3c422b1bec0ddeec9733e7f4aa119a9cf69715a015d05d18d5da1c95dc15bddc3e4f51284cee
7
- data.tar.gz: 4269bfa90e60c7230767b517ec6dd4e3f31d4ac732953f3aeb2cfeab9914029d27b1804af37f8704b66ec9351aedcf1ba7a5c5f796239bc7f7f29685e673109b
6
+ metadata.gz: 9310c36ead85d039a937756560785b2aee184e4b92e8171f486d0bca3d93c5425caede4c535aec8cf59f601b907de9eef97c9af8b67b4e4b4b1effc2fc168744
7
+ data.tar.gz: f658c941750803befda71f8e1455ccdb0292f4ffe1d75d37d84cb37bcf47b99acea4e9c692090614f85d8f04004778765a872db5bab2c47885ef49ffc0a30091
data/.rubocop.yml CHANGED
@@ -8,7 +8,7 @@ AllCops:
8
8
 
9
9
  Style/StringLiterals:
10
10
  Enabled: true
11
- EnforcedStyle: single_quotes
11
+ EnforcedStyle: double_quotes
12
12
 
13
13
  Style/StringLiteralsInInterpolation:
14
14
  Enabled: true
@@ -18,7 +18,4 @@ Style/Documentation:
18
18
  Enabled: false
19
19
 
20
20
  Layout/LineLength:
21
- Max: 125
22
-
23
- Metrics/ClassLength:
24
- Max: 150
21
+ Max: 120
data/Rakefile CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'bundler/gem_tasks'
4
- require 'rspec/core/rake_task'
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
5
 
6
6
  RSpec::Core::RakeTask.new(:spec)
7
7
 
8
- require 'rubocop/rake_task'
8
+ require "rubocop/rake_task"
9
9
 
10
10
  RuboCop::RakeTask.new
11
11
 
@@ -2,16 +2,10 @@
2
2
 
3
3
  module MinatoLogger
4
4
  class Configuration
5
- attr_reader :middleware, :route_blacklist, :sensitive_headers
5
+ attr_reader :middleware
6
6
 
7
7
  def initialize
8
8
  @middleware = MinatoLogger::Middleware.new
9
- @route_blacklist = %w[/health/alive /health/ready]
10
- @sensitive_headers = %w[
11
- AUTHORIZATION PROXY_AUTHORIZATION X_CSRF_TOKEN
12
- HTTP_AUTHORIZATION HTTP_PROXY_AUTHORIZATION
13
- HTTP_X_CSRF_TOKEN COOKIE HTTP_COOKIE
14
- ]
15
9
 
16
10
  yield(self) if block_given?
17
11
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support'
3
+ require "active_support"
4
4
 
5
5
  module MinatoLogger
6
6
  module Formatters
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'json'
3
+ require "json"
4
4
 
5
5
  module MinatoLogger
6
6
  module Formatters
@@ -18,7 +18,7 @@ module MinatoLogger
18
18
  private
19
19
 
20
20
  def sanitize_hash(hash)
21
- hash.transform_keys! { |key| key.to_s.encode('UTF-8', invalid: :replace, undef: :replace, replace: '?') }
21
+ hash.transform_keys! { |key| key.to_s.encode("UTF-8", invalid: :replace, undef: :replace, replace: "?") }
22
22
  hash.transform_values! do |value|
23
23
  sanitize_hash_value(value)
24
24
  end
@@ -27,11 +27,11 @@ module MinatoLogger
27
27
  def sanitize_hash_value(value)
28
28
  case value
29
29
  when String
30
- value.encode('UTF-8', invalid: :replace, undef: :replace, replace: '?')
30
+ value.encode("UTF-8", invalid: :replace, undef: :replace, replace: "?")
31
31
  when Hash
32
32
  sanitize_hash(value)
33
33
  when Array
34
- value.map { |v| v.is_a?(String) ? v.encode('UTF-8', invalid: :replace, undef: :replace, replace: '?') : v }
34
+ value.map { |v| v.is_a?(String) ? v.encode("UTF-8", invalid: :replace, undef: :replace, replace: "?") : v }
35
35
  else
36
36
  value
37
37
  end
@@ -46,20 +46,18 @@ module MinatoLogger
46
46
  end
47
47
 
48
48
  def add_message_to_logs(log, message)
49
- ruby_version = { ruby_version: RUBY_VERSION }
50
- return log.merge(message, ruby_version) unless message.is_a? String
49
+ return log.merge(message) unless message.is_a? String
51
50
 
52
- log.merge({ message: message }, ruby_version)
51
+ log.merge({ message: message, ruby_version: RUBY_VERSION })
53
52
  end
54
53
 
55
54
  def add_tags_to_message(msg)
56
55
  return msg unless tags_text.present?
57
56
 
58
57
  if msg.is_a?(Hash)
59
- msg = msg.transform_keys(&:to_s)
60
- msg['message'] = "#{tags_text}#{msg["message"]}"
58
+ msg["message"] = "#{tags_text} #{msg["message"]}"
61
59
  else
62
- msg = "#{tags_text}#{msg}"
60
+ msg = "#{tags_text} #{msg}"
63
61
  end
64
62
 
65
63
  msg
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'minato_logger/formatters/base_formatter'
4
- require 'minato_logger/formatters/fluent_bit'
3
+ require "minato_logger/formatters/base_formatter"
4
+ require "minato_logger/formatters/fluent_bit"
5
5
 
6
6
  module MinatoLogger
7
7
  module Formatters
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/logger'
4
- require 'active_support/tagged_logging'
3
+ require "active_support/logger"
4
+ require "active_support/tagged_logging"
5
5
 
6
- require_relative 'formatters/fluent_bit'
6
+ require_relative "formatters/fluent_bit"
7
7
 
8
8
  module MinatoLogger
9
9
  class Logger < ActiveSupport::Logger
10
10
  include ActiveSupport::TaggedLogging
11
11
 
12
- def initialize(out = nil)
13
- super(out || $stdout)
12
+ def initialize
13
+ super($stdout)
14
14
  @formatter = Formatters::FluentBit.new
15
15
  end
16
16
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MinatoLogger
4
+ class Railtie < ::Rails::Railtie
5
+ config.minato_logger = MinatoLogger::Configuration.default
6
+
7
+ config.after_initialize do |app|
8
+ app.config.colorize_logging = false if Rails.env.production?
9
+
10
+ if defined? Minato::Trace::Middleware::IntegrateWithCloudLogging
11
+ app.config.minato_logger.middleware.use = Minato::Trace::Middleware::IntegrateWithCloudLogging
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MinatoLogger
4
- VERSION = '0.2.19'
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/minato_logger.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'minato_logger/version'
4
- require 'minato_logger/middleware'
5
- require 'minato_logger/configuration'
6
- require 'minato_logger/formatters'
7
- require 'minato_logger/logger'
8
- require 'minato_logger/engine'
3
+ require "minato_logger/version"
4
+ require "minato_logger/middleware"
5
+ require "minato_logger/configuration"
6
+ require "minato_logger/formatters"
7
+ require "minato_logger/logger"
8
+ require "minato_logger/rails" if defined? Rails::Railtie
9
9
 
10
10
  module MinatoLogger
11
11
  class << self
@@ -1,22 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'lib/minato_logger/version'
3
+ require_relative "lib/minato_logger/version"
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = 'minato_logger'
6
+ spec.name = "minato_logger"
7
7
  spec.version = MinatoLogger::VERSION
8
- spec.authors = ['Ferreri']
9
- spec.email = ['contato@ferreri.co']
8
+ spec.authors = ["Ferreri"]
9
+ spec.email = ["contato@ferreri.co"]
10
10
 
11
- spec.summary = 'Log enhancements for Minato Rails Apps.'
12
- spec.homepage = 'https://gitlab.com/ferreri/minato/minato-logger-rails'
13
- spec.license = 'MIT'
14
- spec.required_ruby_version = '>= 2.6.0'
11
+ spec.summary = "Log enhancements for Minato Rails Apps."
12
+ spec.homepage = "https://gitlab.com/ferreri/minato/minato-logger-rails"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = ">= 2.6.0"
15
15
 
16
- spec.metadata['homepage_uri'] = spec.homepage
17
- spec.metadata['source_code_uri'] = 'https://gitlab.com/ferreri/minato/minato-logger-rails'
18
- spec.metadata['changelog_uri'] = 'https://gitlab.com/ferreri/minato/minato-logger-rails/-/blob/main/CHANGELOG.md?ref_type=heads'
19
- spec.metadata['rubygems_mfa_required'] = 'true'
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = "https://gitlab.com/ferreri/minato/minato-logger-rails"
18
+ spec.metadata["changelog_uri"] = "https://gitlab.com/ferreri/minato/minato-logger-rails/-/blob/main/CHANGELOG.md?ref_type=heads"
19
+ spec.metadata["rubygems_mfa_required"] = "true"
20
20
 
21
21
  # Specify which files should be added to the gem when it is released.
22
22
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@@ -26,10 +26,10 @@ Gem::Specification.new do |spec|
26
26
  f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
27
27
  end
28
28
  end
29
- spec.bindir = 'exe'
29
+ spec.bindir = "exe"
30
30
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
- spec.require_paths = ['lib']
31
+ spec.require_paths = ["lib"]
32
32
 
33
- spec.add_dependency 'activesupport', '>= 7.0.0'
34
- spec.add_dependency 'rails', '>= 7.0.0'
33
+ spec.add_dependency "activesupport", "~> 8.0.2"
34
+ spec.add_dependency "rails", ">= 8.0.0"
35
35
  end
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minato_logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.19
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ferreri
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-02-26 00:00:00.000000000 Z
11
+ date: 2025-08-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 7.0.0
19
+ version: 8.0.2
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: 7.0.0
26
+ version: 8.0.2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rails
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 7.0.0
33
+ version: 8.0.0
34
34
  type: :runtime
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: 7.0.0
40
+ version: 8.0.0
41
41
  description:
42
42
  email:
43
43
  - contato@ferreri.co
@@ -57,13 +57,12 @@ files:
57
57
  - compose.yml
58
58
  - lib/minato_logger.rb
59
59
  - lib/minato_logger/configuration.rb
60
- - lib/minato_logger/engine.rb
61
60
  - lib/minato_logger/formatters.rb
62
61
  - lib/minato_logger/formatters/base_formatter.rb
63
62
  - lib/minato_logger/formatters/fluent_bit.rb
64
63
  - lib/minato_logger/logger.rb
65
64
  - lib/minato_logger/middleware.rb
66
- - lib/minato_logger/middlewares/request_response_logger.rb
65
+ - lib/minato_logger/rails.rb
67
66
  - lib/minato_logger/version.rb
68
67
  - minato_logger.gemspec
69
68
  - sig/minato_logger.rbs
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rails'
4
- require_relative 'middlewares/request_response_logger'
5
- require_relative 'configuration'
6
- require 'rails/rack/logger'
7
-
8
- module MinatoLogger
9
- class Engine < ::Rails::Engine
10
- isolate_namespace MinatoLogger
11
-
12
- initializer 'minato_logger.add_middleware' do |app|
13
- app.config.minato_logger = MinatoLogger::Configuration.default
14
- app.config.log_formatter = MinatoLogger::Formatters::FluentBit.new
15
- app.config.colorize_logging = false if Rails.env.production?
16
- if defined? Minato::Trace::Middleware::IntegrateWithCloudLogging
17
- app.config.minato_logger.middleware.use Minato::Trace::Middleware::IntegrateWithCloudLogging
18
- end
19
- Rails.application.config.middleware.swap(
20
- Rails::Rack::Logger,
21
- MinatoLogger::Middlewares::RequestResponseLogger,
22
- []
23
- )
24
- end
25
- end
26
- end
@@ -1,167 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'json'
4
- require 'rails/rack/logger'
5
-
6
- module MinatoLogger
7
- module Middlewares
8
- class RequestResponseLogger < Rails::Rack::Logger
9
- private
10
-
11
- def call_app(request, env)
12
- should_log = should_log?(request)
13
- ctx = {}
14
- ctx[:request] = build_request_context_base(request) if should_log
15
- log_request(request, env, ctx) if should_log
16
- handle = dispatch_request_event(request)
17
- status, headers, rack_body, log_body = process_request(env)
18
- ctx[:response] = { status: status, headers: headers, body: log_body } if should_log
19
- log_response(request, env, ctx) if should_log
20
- finish_request_instrumentation(handle, env['rails.rack_logger_tag_count'])
21
-
22
- [status, headers, rack_body]
23
- end
24
-
25
- def compute_tags(request)
26
- tags_to_use = @taggers.presence || Rails.application.config.log_tags || []
27
- tags_to_use.collect do |tag|
28
- next tag.call(request) if tag.is_a?(Proc)
29
- next request.send(tag) if tag.is_a?(Symbol)
30
-
31
- tag
32
- end
33
- end
34
-
35
- def build_request_context_base(request)
36
- { start_time: current_time, headers: extract_request_headers(request),
37
- body: extract_request_body(request) }
38
- end
39
-
40
- def should_log?(request)
41
- blacklist = Rails.application.config.minato_logger.route_blacklist || []
42
- blacklist.none? do |item|
43
- next item.call(request) if item.is_a?(Proc)
44
-
45
- request.path == item
46
- end
47
- end
48
-
49
- def process_request(env)
50
- status, headers, response = @app.call(env)
51
- content_type = headers['Content-Type'].to_s
52
-
53
- if content_type.include?('application/json') || content_type.include?('text/')
54
- body_str = extract_body_safely(response || [])
55
- [status, headers, [body_str], body_str]
56
- else
57
- [status, headers, response, "[Binary or Stream Response: #{content_type}]"]
58
- end
59
- end
60
-
61
- def dispatch_request_event(request)
62
- instrumenter = ActiveSupport::Notifications.instrumenter
63
- handle = instrumenter.build_handle('request.action_dispatch', { request: request })
64
- handle.start
65
- handle
66
- end
67
-
68
- def log_request(request, env, ctx)
69
- payload = { type: 'REQUEST', message: "Receiving request #{request.method} #{request.fullpath}" }
70
- payload.merge!(default_log_data(request, env, ctx))
71
- log(payload)
72
- end
73
-
74
- def log_response(request, env, ctx)
75
- ctx[:response][:duration] = ((current_time - ctx.dig(:request, :start_time)) * 1000).round(2)
76
- payload = build_response_payload(request, env, ctx)
77
- log_level = ctx.dig(:response, :status) >= 500 ? :error : :info
78
- log(payload, log_level)
79
- end
80
-
81
- def default_log_data(request, env, ctx)
82
- route = env['action_dispatch.route_uri_pattern'] || request.path
83
- request = { id: request.request_id, method: request.method,
84
- time: Time.zone.now.iso8601, remote_ip: request.remote_ip, route: route, ip: request.ip,
85
- path: request.fullpath, params: filter_params(request), headers: ctx.dig(:request, :headers),
86
- body: ctx.dig(:request, :body) }
87
- { rails_version: Rails.version, request: request }
88
- end
89
-
90
- def build_response_payload(request, env, ctx)
91
- response = { body: safe_parse_json(ctx.dig(:response, :body)),
92
- headers: filter_sensitive_headers(ctx.dig(:response, :headers)),
93
- status: ctx.dig(:response, :status), duration: ctx.dig(:response, :duration) }
94
- payload = { type: 'RESPONSE', response: response,
95
- message: "Responding #{request.method} #{request.fullpath} " \
96
- "- #{ctx.dig(:response, :status)} (#{ctx.dig(:response, :duration)}ms)" }
97
- default_log_data(request, env, ctx).merge(payload)
98
- end
99
-
100
- def log(payload, level = :info)
101
- Rails.logger.public_send(level, payload)
102
- rescue StandardError => e
103
- Rails.logger.error({ message: "Logger Error: #{e.message}", payload: payload })
104
- end
105
-
106
- def extract_body_safely(response)
107
- body = []
108
- response.each { |part| body << part.to_s } if response.respond_to?(:each)
109
- response.close if response.respond_to?(:close)
110
- body.join
111
- end
112
-
113
- def filter_params(request)
114
- request.filtered_parameters.except(:controller, :action, :format)
115
- rescue StandardError
116
- {}
117
- end
118
-
119
- def safe_parse_json(body)
120
- return nil if body.blank?
121
-
122
- JSON.parse(body)
123
- rescue JSON::ParserError
124
- body.to_s
125
- end
126
-
127
- def extract_request_body(request)
128
- return nil unless request.body
129
- return '[Multipart Form Data / File Upload]' if request.content_type.to_s.include?('multipart/form-data')
130
-
131
- body = request.raw_post
132
- return nil if body.blank?
133
-
134
- request.body.rewind if request.body.respond_to?(:rewind)
135
- safe_parse_json(body)
136
- rescue StandardError => e
137
- "Error reading request body: #{e}"
138
- end
139
-
140
- def extract_request_headers(request)
141
- headers = {}
142
- request.headers.each do |k, v|
143
- next unless k.start_with?('HTTP_') || %w[CONTENT_TYPE CONTENT_LENGTH].include?(k)
144
-
145
- normalized_key = k.start_with?('HTTP_') ? k[5..] : k
146
-
147
- headers[normalized_key] = v
148
- end
149
-
150
- filter_sensitive_headers(headers)
151
- end
152
-
153
- def current_time
154
- Process.clock_gettime(Process::CLOCK_MONOTONIC)
155
- end
156
-
157
- def filter_sensitive_headers(headers)
158
- return {} unless headers.is_a?(Hash)
159
-
160
- headers.reject do |k, _|
161
- key = k.to_s.upcase.tr('-', '_')
162
- Rails.application.config.minato_logger.sensitive_headers.any? { |sensitive| key.include?(sensitive) }
163
- end
164
- end
165
- end
166
- end
167
- end