kiev 4.5.0 → 4.8.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f160c0e287ac552fab279ebc1974bf2de5704af494766872e1e2abfa11b48766
4
- data.tar.gz: f2601c9be33ecc63b3741e76832b2b409250a4b5e7365ede3a40cc6a59c0eb6f
3
+ metadata.gz: 4d40605191a7b91d8df6797e3d0e9fa73f82eec5b60dc340f600f5a70b1374ce
4
+ data.tar.gz: 524309f5f0e91a96abc5d85ae158e9316f71c13af2f4076742c14f45812aaec8
5
5
  SHA512:
6
- metadata.gz: 9560e9929db4c64e968dc39d2efadb6b9a09cff5ced0a7e5ffacd823c63273bcd05be4e1918b5e4b70586c73f8520e4d62dccc9e83795908f0981d0ed14ca6e1
7
- data.tar.gz: 4caa6b83331e522867ec3254ac5a3f0356c3336a452ade39e9c8df022f5409a17cc1a024c10cee80353252bec8da66b36aea5430cc4947c59acc0dab0fa1eccd
6
+ metadata.gz: 52737e6382ca2e0ce2e6cf5c0ead72a30454e456ea8b126fc65c30f06c68dc02ba082f74534a84e041b88931d1ea6de1f365d6dff73e148c160c158659553b3f
7
+ data.tar.gz: 9010b961ccbef8dcbc2f39a844ab1f2992e50f7d4ede821cc5329391df24f5e8fde18422d06aa20f9fbc6110fa60d9d1170bd1b95918e7c630413c1f89c1d42e
data/README.md CHANGED
@@ -176,13 +176,13 @@ Kiev::Kafka.inject_context(headers)
176
176
 
177
177
  After this operation the headers variable will also include required context for the Kiev logger.
178
178
 
179
- If you have a consumed `Kafka::FetchedMessage` you can extract logger context with:
179
+ If you have a consumed `Kafka::FetchedMessage` you can extract logger context with:
180
180
 
181
181
  ```ruby
182
182
  Kiev::Kafka.extract_context(message)
183
183
  ```
184
184
 
185
- This will work regardless if headers are in HTTP format, e.g. `X-Tracking-Id` or plain field names: `tracking_id`. Plus the `message_key` field will contain the key of processed message. In case you want to log some more fields configure `persistent_log_fields` and `jobs_propagated_fields`.
185
+ This will work regardless if headers are in HTTP format, e.g. `X-Tracking-Id` or plain field names: `tracking_id`. Plus the `message_key` field will contain the key of processed message. In case you want to log some more fields configure `persistent_log_fields` and `jobs_propagated_fields`.
186
186
 
187
187
  ### Que
188
188
 
@@ -251,7 +251,7 @@ For web requests the Kiev middleware will log the following information by defau
251
251
 
252
252
  * `request_id` is the correlation ID and will be the same across all requests within a chain of requests. It's represented as a UUID (version 4). (currently deprecated in favor of a new name: `tracking_id`)
253
253
 
254
- * `tracking_id` is the correlation ID and will be the same across all requests within a chain of requests. It's represented as a UUID (version 4). If not provided the value is seeded from deprecated `request_id`.
254
+ * `tracking_id` is the correlation ID and will be the same across all requests within a chain of requests. It's represented as a UUID (version 4). If not provided the value is seeded from deprecated `request_id`.
255
255
 
256
256
  * `request_depth` represents the position of the current request within a chain of requests. It starts with 0.
257
257
 
@@ -317,6 +317,11 @@ Kiev.event(:my_event, { some_array: [1, 2, 3] })
317
317
 
318
318
  # Log other data types (will be available under the `message` key)
319
319
  Kiev.event(:my_event, "hello world")
320
+
321
+ # Log with given severity [debug, info, warn, error, fatal]
322
+ Kiev.info(:my_event)
323
+ Kiev.info(:my_event, { some_array: [1, 2, 3] })
324
+ Kiev.info(:my_event, "hello world")
320
325
  ```
321
326
 
322
327
  However, `Kiev.logger` implements the Ruby `Logger` class, so all the other methods are available as well:
@@ -439,6 +444,28 @@ get "/" do
439
444
  end
440
445
  ```
441
446
 
447
+ ### log_level
448
+ You can specify log level.
449
+
450
+ ```ruby
451
+ Kiev.configure do |config|
452
+ # One of: 0, 1, 2, 3, 4 (DEBUG, INFO, WARN, ERROR, FATAL)
453
+ config.log_level = 0
454
+ end
455
+ ```
456
+
457
+ ### disable_filter_for_log_levels
458
+ You can specify for which log levels personal identifying information filter will NOT be applied.
459
+
460
+ ```ruby
461
+ Kiev.configure do |config|
462
+ # [DEBUG, INFO, WARN, ERROR, FATAL]
463
+ config.disable_filter_for_log_levels = [0, 1, 2, 3, 4]
464
+ end
465
+ ```
466
+
467
+ **By default enabled for all suppported log levels.**
468
+
442
469
  ## nginx
443
470
 
444
471
  If you want to log 499 and 50x errors in nginx, which will not be captured by Ruby application, consider adding this to your nginx configuration:
@@ -6,7 +6,7 @@ source "https://rubygems.org"
6
6
  gem "multi_json"
7
7
  gem "oj"
8
8
 
9
- gem "que", ">= 0.12.3"
9
+ gem "que", "0.12.3"
10
10
  gem "pg"
11
11
  gem "sequel"
12
12
 
@@ -11,5 +11,8 @@ gem "rspec", require: false
11
11
  gem "minitest-reporters", require: false
12
12
 
13
13
  gem "her"
14
+ # We need to do it, since her gem doesn't lock upper boundry
15
+ # https://github.com/remi/her/blob/master/her.gemspec#L26
16
+ gem "faraday", "~> 1.9.3"
14
17
 
15
18
  gemspec path: "../"
data/lib/kiev/base.rb CHANGED
@@ -13,21 +13,38 @@ require_relative "config"
13
13
  require_relative "util"
14
14
  require_relative "subrequest_helper"
15
15
  require_relative "hanami"
16
+ require "forwardable"
17
+ require "logger"
16
18
 
17
19
  module Kiev
18
20
  class << self
21
+ extend Forwardable
22
+
23
+ def_delegators :config,
24
+ :logger,
25
+ :filtered_params,
26
+ :ignored_params,
27
+ :log_level,
28
+ :disable_filter_for_log_levels
29
+
19
30
  EMPTY_OBJ = {}.freeze
20
31
 
21
32
  def configure
22
33
  yield(Config.instance)
23
34
  end
24
35
 
25
- def logger
26
- Config.instance.logger
36
+ def config
37
+ Config.instance
38
+ end
39
+
40
+ def event(log_name, data = EMPTY_OBJ, severity = log_level)
41
+ logger.log(severity, logged_data(data), log_name)
27
42
  end
28
43
 
29
- def event(event_name, data = EMPTY_OBJ)
30
- logger.log(::Logger::Severity::INFO, data, event_name)
44
+ Config.instance.supported_log_levels.each_pair do |key, value|
45
+ define_method(key) do |log_name, data = EMPTY_OBJ|
46
+ event(log_name, data, value)
47
+ end
31
48
  end
32
49
 
33
50
  def []=(name, value)
@@ -51,5 +68,13 @@ module Kiev
51
68
  end
52
69
 
53
70
  alias_method :tracking_id, :request_id
71
+
72
+ private
73
+
74
+ def logged_data(data)
75
+ return data if disable_filter_for_log_levels.include?(log_level)
76
+
77
+ ParamFilter.filter(data, filtered_params, ignored_params)
78
+ end
54
79
  end
55
80
  end
data/lib/kiev/config.rb CHANGED
@@ -75,6 +75,16 @@ module Kiev
75
75
  end
76
76
  end
77
77
 
78
+ SUPPORTED_LOG_LEVELS = {
79
+ debug: ::Logger::DEBUG,
80
+ info: ::Logger::INFO,
81
+ warn: ::Logger::WARN,
82
+ error: ::Logger::ERROR,
83
+ fatal: ::Logger::FATAL
84
+ }.freeze
85
+
86
+ private_constant :SUPPORTED_LOG_LEVELS
87
+
78
88
  attr_accessor :app,
79
89
  :log_request_condition,
80
90
  :log_request_error_condition,
@@ -89,10 +99,12 @@ module Kiev
89
99
 
90
100
  attr_reader :development_mode,
91
101
  :logger,
102
+ :log_level,
92
103
  :http_propagated_fields,
93
104
  :jobs_propagated_fields,
94
105
  :all_http_propagated_fields, # for internal use
95
- :all_jobs_propagated_fields # for internal use
106
+ :all_jobs_propagated_fields, # for internal use
107
+ :disable_filter_for_log_levels
96
108
 
97
109
  def initialize
98
110
  @log_request_condition = DEFAULT_LOG_REQUEST_CONDITION
@@ -105,9 +117,10 @@ module Kiev
105
117
  @development_mode = false
106
118
  @ignored_rack_exceptions = DEFAULT_IGNORED_RACK_EXCEPTIONS.dup
107
119
  @logger = Kiev::Logger.new(STDOUT)
108
- @log_level = nil
120
+ @log_level = default_log_level
109
121
  @persistent_log_fields = []
110
122
  @pre_rack_hook = DEFAULT_PRE_RACK_HOOK
123
+ @disable_filter_for_log_levels = []
111
124
  self.propagated_fields = {}
112
125
  update_logger_settings
113
126
  end
@@ -138,20 +151,32 @@ module Kiev
138
151
  end
139
152
 
140
153
  def log_level=(value)
154
+ raise ArgumentError, "Unsupported log level #{value}" unless supported_log_level?(value)
155
+
141
156
  @log_level = value
142
157
  update_logger_settings
143
158
  end
144
159
 
160
+ def disable_filter_for_log_levels=(log_levels)
161
+ raise ArgumentError, "Unsupported log levels" unless array_with_log_levels?(log_levels)
162
+
163
+ @disable_filter_for_log_levels = log_levels
164
+ end
165
+
145
166
  def development_mode=(value)
146
167
  @development_mode = value
147
168
  update_logger_settings
148
169
  end
149
170
 
171
+ def supported_log_levels
172
+ SUPPORTED_LOG_LEVELS
173
+ end
174
+
150
175
  private
151
176
 
152
177
  def update_logger_settings
153
178
  @logger.formatter = formatter
154
- @logger.level = @log_level || default_log_level
179
+ @logger.level = @log_level
155
180
  end
156
181
 
157
182
  def formatter
@@ -161,5 +186,15 @@ module Kiev
161
186
  def default_log_level
162
187
  development_mode ? ::Logger::DEBUG : ::Logger::INFO
163
188
  end
189
+
190
+ def array_with_log_levels?(log_levels)
191
+ return false unless log_levels.is_a?(Array)
192
+
193
+ log_levels.all? { |level| supported_log_level?(level) }
194
+ end
195
+
196
+ def supported_log_level?(log_level)
197
+ supported_log_levels.value?(log_level)
198
+ end
164
199
  end
165
200
  end
data/lib/kiev/logger.rb CHANGED
@@ -12,17 +12,19 @@ module Kiev
12
12
  extend Forwardable
13
13
  def_delegators(*([:@logger] + ::Logger.instance_methods(false)))
14
14
 
15
- DEFAULT_EVENT_NAME = "log"
15
+ DEFAULT_LOG_NAME = "log"
16
+ DEFAULT_MESSAGE = "log"
16
17
  LOG_ERROR = "ERROR"
17
18
  ERROR_STATUS = 500
18
19
 
19
- FORMATTER = proc do |severity, time, event_name, data|
20
+ FORMATTER = proc do |severity, time, log_name, data|
20
21
  entry =
21
22
  {
22
23
  application: Config.instance.app,
23
- event: event_name || DEFAULT_EVENT_NAME,
24
+ log_name: log_name || DEFAULT_LOG_NAME,
24
25
  level: severity,
25
26
  timestamp: time.utc,
27
+ message: log_name || DEFAULT_MESSAGE,
26
28
  tracking_id: RequestStore.store[:tracking_id],
27
29
  request_id: RequestStore.store[:request_id],
28
30
  request_depth: RequestStore.store[:request_depth],
@@ -39,12 +41,12 @@ module Kiev
39
41
  entry[:jid] = RequestStore.store[:jid]
40
42
  end
41
43
 
42
- if !RequestStore.store[:subrequest_count] && %i(request_finished job_finished).include?(event_name)
44
+ if !RequestStore.store[:subrequest_count] && %i(request_finished job_finished).include?(log_name)
43
45
  entry[:tree_leaf] = true
44
46
  end
45
47
 
46
48
  if RequestStore.store[:payload]
47
- if %i(request_finished job_finished).include?(event_name)
49
+ if %i(request_finished job_finished).include?(log_name)
48
50
  entry.merge!(RequestStore.store[:payload])
49
51
  else
50
52
  Config.instance.persistent_log_fields.each do |field|
@@ -68,17 +70,17 @@ module Kiev
68
70
  JSON.logstash(entry)
69
71
  end
70
72
 
71
- DEVELOPMENT_FORMATTER = proc do |severity, time, event_name, data|
73
+ DEVELOPMENT_FORMATTER = proc do |severity, time, log_name, data|
72
74
  entry = []
73
75
 
74
76
  entry << time.iso8601
75
- entry << (event_name || severity).upcase
77
+ entry << (log_name || severity).upcase
76
78
 
77
79
  if data.is_a?(String)
78
80
  entry << "#{data}\n"
79
81
  end
80
82
 
81
- if %i(request_finished job_finished).include?(event_name)
83
+ if %i(request_finished job_finished).include?(log_name)
82
84
  verb = RequestStore.store[:request_verb]
83
85
  path = RequestStore.store[:request_path]
84
86
  entry << "#{verb} #{path}" if verb && path
@@ -1,12 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kiev
4
- module ParamFilter
4
+ class ParamFilter
5
5
  FILTERED = "[FILTERED]"
6
6
 
7
7
  def self.filter(params, filtered_params, ignored_params)
8
+ new(filtered_params, ignored_params).call(params)
9
+ end
10
+
11
+ def initialize(filtered_params, ignored_params)
12
+ @filtered_params = normalize(filtered_params)
13
+ @ignored_params = normalize(ignored_params)
14
+ end
15
+
16
+ def call(params)
17
+ return params unless filterable?(params)
18
+
8
19
  params.each_with_object({}) do |(key, value), acc|
9
- next if ignored_params.include?(key)
20
+ next if ignored_params.include?(key.to_s)
10
21
 
11
22
  if defined?(ActionDispatch) && value.is_a?(ActionDispatch::Http::UploadedFile)
12
23
  value = {
@@ -17,14 +28,26 @@ module Kiev
17
28
  end
18
29
 
19
30
  acc[key] =
20
- if filtered_params.include?(key) && !value.is_a?(Hash)
31
+ if filtered_params.include?(key.to_s) && !value.is_a?(Hash)
21
32
  FILTERED
22
33
  elsif value.is_a?(Hash)
23
- filter(value, filtered_params, ignored_params)
34
+ call(value)
24
35
  else
25
36
  value
26
37
  end
27
38
  end
28
39
  end
40
+
41
+ private
42
+
43
+ attr_reader :filtered_params, :ignored_params
44
+
45
+ def filterable?(params)
46
+ params.respond_to?(:each_with_object)
47
+ end
48
+
49
+ def normalize(params)
50
+ Set.new(params.map(&:to_s))
51
+ end
29
52
  end
30
53
  end
@@ -85,8 +85,6 @@ module Kiev
85
85
  request.params
86
86
  end
87
87
 
88
- params = ParamFilter.filter(params, config.filtered_params, config.ignored_params)
89
-
90
88
  data = {
91
89
  host: request.host, # env["HTTP_HOST"] || env["HTTPS_HOST"],
92
90
  params: params.empty? ? nil : params, # env[Rack::QUERY_STRING],
data/lib/kiev/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kiev
4
- VERSION = "4.5.0"
4
+ VERSION = "4.8.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kiev
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.5.0
4
+ version: 4.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Blacklane
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-02-08 00:00:00.000000000 Z
11
+ date: 2022-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oga
@@ -222,8 +222,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
222
222
  - !ruby/object:Gem::Version
223
223
  version: '0'
224
224
  requirements: []
225
- rubyforge_project:
226
- rubygems_version: 2.7.6
225
+ rubygems_version: 3.3.7
227
226
  signing_key:
228
227
  specification_version: 4
229
228
  summary: Distributed logging to JSON integrated with various Ruby frameworks and tools