kiev 4.3.0 → 4.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/push.yml +80 -0
- data/.rubocop.yml +8 -1
- data/.ruby-version +1 -1
- data/Gemfile +1 -1
- data/README.md +34 -2
- data/gemfiles/que_0.12.2.gemfile +3 -1
- data/gemfiles/que_0.12.3.gemfile +3 -1
- data/gemfiles/rails_4.1.gemfile +3 -1
- data/gemfiles/rails_4.2.gemfile +3 -1
- data/gemfiles/rails_5.2.gemfile +15 -0
- data/gemfiles/ruby_kafka.gemfile +11 -0
- data/gemfiles/{shoryuken_3.1.gemfile → shoryuken_4.0.gemfile} +4 -2
- data/gemfiles/sidekiq_4.2.gemfile +3 -2
- data/gemfiles/sinatra_1.4.gemfile +4 -2
- data/gemfiles/sinatra_2.0.gemfile +4 -2
- data/kiev.gemspec +8 -6
- data/lib/kiev/aws_sns/context_injector.rb +22 -0
- data/lib/kiev/aws_sns.rb +16 -0
- data/lib/kiev/base.rb +17 -3
- data/lib/kiev/base52.rb +1 -1
- data/lib/kiev/config.rb +1 -0
- data/lib/kiev/context_reader.rb +6 -3
- data/lib/kiev/kafka/context_extractor.rb +26 -0
- data/lib/kiev/kafka/context_injector.rb +20 -0
- data/lib/kiev/kafka/message_context.rb +27 -0
- data/lib/kiev/kafka.rb +22 -0
- data/lib/kiev/logger.rb +13 -12
- data/lib/kiev/param_filter.rb +27 -4
- data/lib/kiev/que/job.rb +2 -1
- data/lib/kiev/rack/request_id.rb +15 -13
- data/lib/kiev/rack/request_logger.rb +2 -4
- data/lib/kiev/request_id.rb +2 -1
- data/lib/kiev/request_logger.rb +3 -2
- data/lib/kiev/shoryuken/context_reader.rb +2 -0
- data/lib/kiev/shoryuken/middleware/message_tracer.rb +4 -7
- data/lib/kiev/test.rb +2 -1
- data/lib/kiev/util.rb +1 -0
- data/lib/kiev/version.rb +1 -1
- data/lib/kiev.rb +2 -0
- metadata +43 -34
- data/.travis.yml +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5da27510343d0217fedb4e4282cf9fc6468a63be4484935e2495e31205a2b188
|
4
|
+
data.tar.gz: 3a7ac16381946c418fa4265ab440da10397514766e5c091a87847f4451644251
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ee5e47a70aae2576a0d119c0347fa9707f8a1ff53e8db3f5c1b8ae0bcc39907fd755f1d6112eca317e3b22ce8e2bdb59e83f3e9b70b86014fae995a4377da466
|
7
|
+
data.tar.gz: d976cb714c3e9ca5a2f3aa9c0a505a78d38d4a1c77faddc408555dec2ff3f337dbc9430d881630165933084e2a5c88051ef6fbe530a2c79ebf2f24b64949a329
|
@@ -0,0 +1,80 @@
|
|
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: Main CI
|
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: ['2.5.1', '2.7.2', '2.6.5']
|
23
|
+
gemfile:
|
24
|
+
- gemfiles/ruby_kafka.gemfile
|
25
|
+
- gemfiles/que_0.12.2.gemfile
|
26
|
+
- gemfiles/que_0.12.3.gemfile
|
27
|
+
- gemfiles/rails_5.2.gemfile
|
28
|
+
- gemfiles/shoryuken_4.0.gemfile
|
29
|
+
- gemfiles/sidekiq_4.2.gemfile
|
30
|
+
- gemfiles/sinatra_1.4.gemfile
|
31
|
+
- gemfiles/sinatra_2.0.gemfile
|
32
|
+
allow_failures:
|
33
|
+
- false
|
34
|
+
include:
|
35
|
+
- os: ubuntu
|
36
|
+
ruby-version: ruby-head
|
37
|
+
gemfile: gemfiles/rails_5.2.gemfile
|
38
|
+
allow_failures: true
|
39
|
+
env:
|
40
|
+
BUNDLE_GEMFILE: "${{ matrix.gemfile }}"
|
41
|
+
ALLOW_FAILURES: "${{ matrix.allow_failures }}"
|
42
|
+
REDIS_URL: "redis://localhost:6379/4"
|
43
|
+
DATABASE_URL: ${{ (startsWith(matrix.gemfile,'gemfiles/que') && 'postgres://postgres:postgres@localhost:5432/que_test') || 'sqlite3:db/combustion_test.sqlite'}}
|
44
|
+
continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' }}
|
45
|
+
|
46
|
+
# Service containers to run with `container-job`
|
47
|
+
services:
|
48
|
+
redis:
|
49
|
+
image: redis:latest
|
50
|
+
ports:
|
51
|
+
- 6379:6379
|
52
|
+
# Label used to access the service container
|
53
|
+
postgres:
|
54
|
+
# Docker Hub image
|
55
|
+
image: postgres:9.4
|
56
|
+
# Provide the password for postgres
|
57
|
+
env:
|
58
|
+
POSTGRES_PASSWORD: postgres
|
59
|
+
POSTGRES_DB: que_test
|
60
|
+
# Set health checks to wait until postgres has started
|
61
|
+
ports:
|
62
|
+
- 5432:5432
|
63
|
+
options: >-
|
64
|
+
--health-cmd pg_isready
|
65
|
+
--health-interval 10s
|
66
|
+
--health-timeout 5s
|
67
|
+
--health-retries 5
|
68
|
+
steps:
|
69
|
+
- uses: actions/checkout@v2
|
70
|
+
- name: Set up Ruby
|
71
|
+
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
72
|
+
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
73
|
+
# uses: ruby/setup-ruby@v1
|
74
|
+
uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
|
75
|
+
with:
|
76
|
+
ruby-version: ${{ matrix.ruby }}
|
77
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
78
|
+
|
79
|
+
- name: Run tests
|
80
|
+
run: bundle exec rake || $ALLOW_FAILURES
|
data/.rubocop.yml
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
inherit_from:
|
2
2
|
- https://raw.githubusercontent.com/blacklane/rubocop/master/rubocop.yml
|
3
3
|
|
4
|
-
|
4
|
+
AllCops:
|
5
|
+
TargetRubyVersion: 2.5
|
6
|
+
Exclude:
|
7
|
+
- test/rails_app/**/*.rb # auto-generated
|
8
|
+
- spec/**/*.rb
|
9
|
+
- test/**/*.rb
|
10
|
+
- vendor/bundle/**/*
|
11
|
+
Lint/SuppressedException:
|
5
12
|
Exclude:
|
6
13
|
- test/**/*.rb
|
7
14
|
- spec/**/*.rb
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.5.1
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Kiev [![Build Status](https://
|
1
|
+
# Kiev [![Build Status](https://github.com/blacklane/kiev/workflows/Main%20CI/badge.svg?branch=master)](https://github.com/blacklane/kiev/actions?query=workflow%3A%22Main+CI%22) [![Gem Version](https://badge.fury.io/rb/kiev.svg)](https://badge.fury.io/rb/kiev)
|
2
2
|
|
3
3
|
Kiev is a comprehensive logging library aimed at covering a wide range of frameworks and tools from the Ruby ecosystem:
|
4
4
|
|
@@ -154,6 +154,36 @@ Kiev::Shoryuken.enable
|
|
154
154
|
|
155
155
|
The name of the worker class is not logged by default. Configure [`persistent_log_fields` option](#persistent_log_fields) to include `"shoryuken_class"` if you want this.
|
156
156
|
|
157
|
+
### AWS SNS
|
158
|
+
|
159
|
+
To enhance messages published to SNS topics you can use the ContextInjector:
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
sns_message = { topic_arn: "...", message: "{...}" }
|
163
|
+
Kiev::Kafka.inject_context(sns_message[:message_attributes])
|
164
|
+
|
165
|
+
```
|
166
|
+
|
167
|
+
After this operation the message attributes will also include required context for the Kiev logger.
|
168
|
+
|
169
|
+
### Kafka
|
170
|
+
|
171
|
+
To enhance messages published to Kafka topics you can use the ContextInjector:
|
172
|
+
|
173
|
+
```ruby
|
174
|
+
Kiev::Kafka.inject_context(headers)
|
175
|
+
```
|
176
|
+
|
177
|
+
After this operation the headers variable will also include required context for the Kiev logger.
|
178
|
+
|
179
|
+
If you have a consumed `Kafka::FetchedMessage` you can extract logger context with:
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
Kiev::Kafka.extract_context(message)
|
183
|
+
```
|
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`.
|
186
|
+
|
157
187
|
### Que
|
158
188
|
|
159
189
|
Add the following lines to your initializer code:
|
@@ -219,7 +249,9 @@ For web requests the Kiev middleware will log the following information by defau
|
|
219
249
|
|
220
250
|
* `params` attribute will store both query parameters and request body fields (as long as they are parseable). Sensitive fields will be filtered out - see the `#filtered_params` option.
|
221
251
|
|
222
|
-
* `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).
|
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
|
+
|
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`.
|
223
255
|
|
224
256
|
* `request_depth` represents the position of the current request within a chain of requests. It starts with 0.
|
225
257
|
|
data/gemfiles/que_0.12.2.gemfile
CHANGED
data/gemfiles/que_0.12.3.gemfile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source "https://rubygems.org"
|
2
4
|
|
3
5
|
# need it because of bug in https://github.com/chanks/que/issues/191
|
@@ -12,4 +14,4 @@ gem "rack-test", require: false
|
|
12
14
|
gem "rspec", require: false
|
13
15
|
gem "minitest-reporters", require: false
|
14
16
|
|
15
|
-
gemspec :
|
17
|
+
gemspec path: "../"
|
data/gemfiles/rails_4.1.gemfile
CHANGED
data/gemfiles/rails_4.2.gemfile
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "oj"
|
6
|
+
|
7
|
+
gem "rails", "~> 5.2.4"
|
8
|
+
gem "sqlite3", "1.3.13"
|
9
|
+
|
10
|
+
gem "combustion"
|
11
|
+
gem "rspec", require: false
|
12
|
+
gem "rspec-rails", require: false
|
13
|
+
gem "minitest-reporters", require: false
|
14
|
+
|
15
|
+
gemspec path: "../"
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source "https://rubygems.org"
|
2
4
|
|
3
5
|
gem "aws-sdk", "~> 2.0"
|
4
|
-
gem "shoryuken", "~>
|
6
|
+
gem "shoryuken", "~> 4.0"
|
5
7
|
|
6
8
|
gem "rack-test", require: false
|
7
9
|
gem "minitest-reporters", require: false
|
8
10
|
|
9
|
-
gemspec :
|
11
|
+
gemspec path: "../"
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source "https://rubygems.org"
|
2
4
|
|
3
5
|
gem "oj"
|
@@ -6,10 +8,10 @@ gem "xml-simple"
|
|
6
8
|
|
7
9
|
gem "sinatra", "1.4.7"
|
8
10
|
gem "sinatra-contrib"
|
9
|
-
gem "rack-parser", :
|
11
|
+
gem "rack-parser", require: "rack/parser"
|
10
12
|
|
11
13
|
gem "rack-test", require: false
|
12
14
|
gem "rspec", require: false
|
13
15
|
gem "minitest-reporters", require: false
|
14
16
|
|
15
|
-
gemspec :
|
17
|
+
gemspec path: "../"
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source "https://rubygems.org"
|
2
4
|
|
3
5
|
gem "oj"
|
@@ -6,10 +8,10 @@ gem "xml-simple"
|
|
6
8
|
|
7
9
|
gem "sinatra", "2.0.0"
|
8
10
|
gem "sinatra-contrib"
|
9
|
-
gem "rack-parser", :
|
11
|
+
gem "rack-parser", require: "rack/parser"
|
10
12
|
|
11
13
|
gem "rack-test", require: false
|
12
14
|
gem "rspec", require: false
|
13
15
|
gem "minitest-reporters", require: false
|
14
16
|
|
15
|
-
gemspec :
|
17
|
+
gemspec path: "../"
|
data/kiev.gemspec
CHANGED
@@ -9,7 +9,9 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.licenses = ["MIT"]
|
10
10
|
|
11
11
|
spec.summary = "Distributed logging to JSON integrated with various Ruby frameworks and tools"
|
12
|
-
spec.description = "Kiev is a logging tool aimed at distributed environments. It logs to JSON, while providing
|
12
|
+
spec.description = "Kiev is a logging tool aimed at distributed environments. It logs to JSON, while providing "\
|
13
|
+
"human-readable output in development mode. It integrates nicely with Rails, Sinatra and other"\
|
14
|
+
" Rack-based frameworks, Sidekiq, Que, HTTParty, Her and other Faraday-based HTTP clients."
|
13
15
|
spec.homepage = "https://github.com/blacklane/kiev"
|
14
16
|
|
15
17
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
@@ -17,12 +19,12 @@ Gem::Specification.new do |spec|
|
|
17
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
20
|
spec.require_paths = ["lib"]
|
19
21
|
|
20
|
-
spec.required_ruby_version = ">= 2.
|
22
|
+
spec.required_ruby_version = ">= 2.5"
|
23
|
+
spec.add_dependency "oga", "~> 2.2"
|
21
24
|
spec.add_dependency "rack", ">= 1", "< 3"
|
22
25
|
spec.add_dependency "request_store", ">= 1.0", "< 1.4"
|
23
|
-
spec.add_dependency "oga", "~> 2.2"
|
24
26
|
spec.add_dependency "ruby_dig", "~> 0.0.2" # to support ruby 2.2
|
25
|
-
spec.add_development_dependency "rake"
|
26
|
-
spec.add_development_dependency "rspec"
|
27
|
-
spec.add_development_dependency "rubocop", "0.
|
27
|
+
spec.add_development_dependency "rake", "~> 0"
|
28
|
+
spec.add_development_dependency "rspec", "~> 3.10"
|
29
|
+
spec.add_development_dependency "rubocop", "~> 0.54"
|
28
30
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "kiev/config"
|
4
|
+
require "kiev/subrequest_helper"
|
5
|
+
|
6
|
+
module Kiev
|
7
|
+
module AwsSns
|
8
|
+
class ContextInjector
|
9
|
+
# @param [Hash] message_attributes Injects context headers
|
10
|
+
# @return [Hash]
|
11
|
+
def call(message_attributes = {})
|
12
|
+
Kiev::SubrequestHelper.payload.each do |key, value|
|
13
|
+
message_attributes[key] = {
|
14
|
+
data_type: "String",
|
15
|
+
string_value: value.to_s
|
16
|
+
}
|
17
|
+
end
|
18
|
+
message_attributes
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/kiev/aws_sns.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module Kiev
|
6
|
+
module AwsSns
|
7
|
+
require_relative "kafka/context_injector"
|
8
|
+
|
9
|
+
class << self
|
10
|
+
# @param [Hash] headers
|
11
|
+
def inject_context(headers = {})
|
12
|
+
Kiev::AwsSns::ContextInjector.new.call(headers)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/kiev/base.rb
CHANGED
@@ -26,8 +26,20 @@ module Kiev
|
|
26
26
|
Config.instance.logger
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
30
|
-
|
29
|
+
def filtered_params
|
30
|
+
Config.instance.filtered_params
|
31
|
+
end
|
32
|
+
|
33
|
+
def ignored_params
|
34
|
+
Config.instance.ignored_params
|
35
|
+
end
|
36
|
+
|
37
|
+
def event(log_name, data = EMPTY_OBJ)
|
38
|
+
logger.log(
|
39
|
+
::Logger::Severity::INFO,
|
40
|
+
ParamFilter.filter(data, filtered_params, ignored_params),
|
41
|
+
log_name
|
42
|
+
)
|
31
43
|
end
|
32
44
|
|
33
45
|
def []=(name, value)
|
@@ -47,7 +59,9 @@ module Kiev
|
|
47
59
|
end
|
48
60
|
|
49
61
|
def request_id
|
50
|
-
RequestStore.store[:
|
62
|
+
RequestStore.store[:tracking_id]
|
51
63
|
end
|
64
|
+
|
65
|
+
alias_method :tracking_id, :request_id
|
52
66
|
end
|
53
67
|
end
|
data/lib/kiev/base52.rb
CHANGED
data/lib/kiev/config.rb
CHANGED
data/lib/kiev/context_reader.rb
CHANGED
@@ -6,6 +6,7 @@ module Kiev
|
|
6
6
|
# change field lookup.
|
7
7
|
class ContextReader
|
8
8
|
REQUEST_ID = "request_id"
|
9
|
+
TRACKING_ID = "tracking_id"
|
9
10
|
REQUEST_DEPTH = "request_depth"
|
10
11
|
TREE_PATH = "tree_path"
|
11
12
|
|
@@ -17,12 +18,14 @@ module Kiev
|
|
17
18
|
subject[key]
|
18
19
|
end
|
19
20
|
|
20
|
-
def
|
21
|
-
self[REQUEST_ID] || SecureRandom.uuid
|
21
|
+
def tracking_id
|
22
|
+
self[TRACKING_ID] || self[REQUEST_ID] || SecureRandom.uuid
|
22
23
|
end
|
23
24
|
|
25
|
+
alias_method :request_id, :tracking_id
|
26
|
+
|
24
27
|
def tree_root?
|
25
|
-
!self[REQUEST_ID]
|
28
|
+
!self[TRACKING_ID] && !self[REQUEST_ID]
|
26
29
|
end
|
27
30
|
|
28
31
|
def request_depth
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "message_context"
|
4
|
+
require "kiev/request_id"
|
5
|
+
require "kiev/context_reader"
|
6
|
+
|
7
|
+
module Kiev
|
8
|
+
module Kafka
|
9
|
+
class ContextExtractor
|
10
|
+
include Kiev::RequestId::Mixin
|
11
|
+
|
12
|
+
# @param [Kafka::FetchedMessage] message
|
13
|
+
def call(message)
|
14
|
+
context = Kiev::Kafka::MessageContext.new(message)
|
15
|
+
context_reader = Kiev::ContextReader.new(context)
|
16
|
+
wrap_request_id(context_reader) {}
|
17
|
+
|
18
|
+
Kiev[:message_key] = message.key
|
19
|
+
|
20
|
+
Config.instance.jobs_propagated_fields.each do |key|
|
21
|
+
Kiev[key] = context_reader[key]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "kiev/config"
|
4
|
+
require "kiev/subrequest_helper"
|
5
|
+
|
6
|
+
module Kiev
|
7
|
+
module Kafka
|
8
|
+
class ContextInjector
|
9
|
+
# @param [Hash] headers Injects context headers
|
10
|
+
# @return [Hash]
|
11
|
+
def call(headers = {})
|
12
|
+
Kiev::SubrequestHelper.payload.each do |key, value|
|
13
|
+
field_key = Kiev::Config::DEFAULT_HTTP_PROPAGATED_FIELDS.fetch(key.to_sym, key)
|
14
|
+
headers[field_key] = value
|
15
|
+
end
|
16
|
+
headers
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kiev
|
4
|
+
module Kafka
|
5
|
+
class MessageContext
|
6
|
+
# @param [Kafka::FetchedMessage] message
|
7
|
+
def initialize(message)
|
8
|
+
@headers = message.headers
|
9
|
+
end
|
10
|
+
|
11
|
+
def value(field)
|
12
|
+
headers[header_key(field)] || headers[field.to_s]
|
13
|
+
end
|
14
|
+
|
15
|
+
alias_method :[], :value
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :headers
|
20
|
+
|
21
|
+
# @param [String] field
|
22
|
+
def header_key(field)
|
23
|
+
"x_#{field}".gsub("_", " ").split.map(&:capitalize).join("-")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/kiev/kafka.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module Kiev
|
6
|
+
module Kafka
|
7
|
+
require_relative "kafka/context_extractor"
|
8
|
+
require_relative "kafka/context_injector"
|
9
|
+
|
10
|
+
class << self
|
11
|
+
# @param [Kafka::FetchedMessage] message
|
12
|
+
def extract_context(message)
|
13
|
+
Kiev::Kafka::ContextExtractor.new.call(message)
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param [Hash] headers
|
17
|
+
def inject_context(headers = {})
|
18
|
+
Kiev::Kafka::ContextInjector.new.call(headers)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/kiev/logger.rb
CHANGED
@@ -12,17 +12,20 @@ module Kiev
|
|
12
12
|
extend Forwardable
|
13
13
|
def_delegators(*([:@logger] + ::Logger.instance_methods(false)))
|
14
14
|
|
15
|
-
|
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,
|
20
|
+
FORMATTER = proc do |severity, time, log_name, data|
|
20
21
|
entry =
|
21
22
|
{
|
22
23
|
application: Config.instance.app,
|
23
|
-
|
24
|
+
log_name: log_name || DEFAULT_LOG_NAME,
|
24
25
|
level: severity,
|
25
26
|
timestamp: time.utc,
|
27
|
+
message: log_name || DEFAULT_MESSAGE,
|
28
|
+
tracking_id: RequestStore.store[:tracking_id],
|
26
29
|
request_id: RequestStore.store[:request_id],
|
27
30
|
request_depth: RequestStore.store[:request_depth],
|
28
31
|
tree_path: RequestStore.store[:tree_path]
|
@@ -38,12 +41,12 @@ module Kiev
|
|
38
41
|
entry[:jid] = RequestStore.store[:jid]
|
39
42
|
end
|
40
43
|
|
41
|
-
if !RequestStore.store[:subrequest_count] && %i(request_finished job_finished).include?(
|
44
|
+
if !RequestStore.store[:subrequest_count] && %i(request_finished job_finished).include?(log_name)
|
42
45
|
entry[:tree_leaf] = true
|
43
46
|
end
|
44
47
|
|
45
48
|
if RequestStore.store[:payload]
|
46
|
-
if %i(request_finished job_finished).include?(
|
49
|
+
if %i(request_finished job_finished).include?(log_name)
|
47
50
|
entry.merge!(RequestStore.store[:payload])
|
48
51
|
else
|
49
52
|
Config.instance.persistent_log_fields.each do |field|
|
@@ -67,17 +70,17 @@ module Kiev
|
|
67
70
|
JSON.logstash(entry)
|
68
71
|
end
|
69
72
|
|
70
|
-
DEVELOPMENT_FORMATTER = proc do |severity, time,
|
73
|
+
DEVELOPMENT_FORMATTER = proc do |severity, time, log_name, data|
|
71
74
|
entry = []
|
72
75
|
|
73
76
|
entry << time.iso8601
|
74
|
-
entry << (
|
77
|
+
entry << (log_name || severity).upcase
|
75
78
|
|
76
79
|
if data.is_a?(String)
|
77
80
|
entry << "#{data}\n"
|
78
81
|
end
|
79
82
|
|
80
|
-
if %i(request_finished job_finished).include?(
|
83
|
+
if %i(request_finished job_finished).include?(log_name)
|
81
84
|
verb = RequestStore.store[:request_verb]
|
82
85
|
path = RequestStore.store[:request_path]
|
83
86
|
entry << "#{verb} #{path}" if verb && path
|
@@ -92,10 +95,8 @@ module Kiev
|
|
92
95
|
entry << "(#{duration}ms)" if duration
|
93
96
|
entry << "\n"
|
94
97
|
|
95
|
-
meta =
|
96
|
-
|
97
|
-
request_depth: RequestStore.store[:request_depth]
|
98
|
-
}.merge!(Hash(RequestStore.store[:payload]))
|
98
|
+
meta = RequestStore.store.slice(:trakcing_id, :request_id, :request_depth)
|
99
|
+
.reverse_merge!(Hash(RequestStore.store[:payload]))
|
99
100
|
|
100
101
|
meta.reject! { |_, value| value.nil? }
|
101
102
|
|
data/lib/kiev/param_filter.rb
CHANGED
@@ -1,12 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Kiev
|
4
|
-
|
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
|
-
|
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
|
data/lib/kiev/que/job.rb
CHANGED
@@ -47,7 +47,8 @@ module Kiev
|
|
47
47
|
Kiev[key] = payload[key]
|
48
48
|
end
|
49
49
|
request_store = Kiev::RequestStore.store
|
50
|
-
request_store[:
|
50
|
+
request_store[:tracking_id] = payload[:tracking_id]
|
51
|
+
request_store[:request_id] = payload[:tracking_id] || payload[:request_id]
|
51
52
|
request_store[:request_depth] = payload[:request_depth].to_i + 1
|
52
53
|
request_store[:tree_path] = payload[:tree_path]
|
53
54
|
|
data/lib/kiev/rack/request_id.rb
CHANGED
@@ -14,24 +14,26 @@ module Kiev
|
|
14
14
|
|
15
15
|
def call(env)
|
16
16
|
request_id_header_out = to_rack(:request_id)
|
17
|
-
|
17
|
+
tracking_id_header_out = to_rack(:tracking_id)
|
18
18
|
|
19
|
-
|
20
|
-
RequestStore.store[:
|
19
|
+
tracking_id = make_tracking_id(env[to_http(:tracking_id)] || env[RAILS_REQUEST_ID] || env[to_http(:request_id)])
|
20
|
+
RequestStore.store[:tracking_id] = tracking_id
|
21
|
+
RequestStore.store[:request_id] = tracking_id
|
21
22
|
RequestStore.store[:request_depth] = request_depth(env)
|
22
23
|
RequestStore.store[:tree_path] = tree_path(env)
|
23
24
|
|
24
|
-
@app.call(env).tap
|
25
|
+
@app.call(env).tap do |_status, headers, _body|
|
26
|
+
headers[tracking_id_header_out] = tracking_id
|
27
|
+
headers[request_id_header_out] = tracking_id
|
28
|
+
end
|
25
29
|
end
|
26
30
|
|
27
31
|
private
|
28
32
|
|
29
|
-
# TODO: in Rails 5 they set `headers[X_REQUEST_ID]`, so this will not work
|
30
|
-
# https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/request_id.rb
|
31
|
-
# https://github.com/interagent/pliny/blob/master/lib/pliny/middleware/request_id.rb
|
32
33
|
def tree_root?(env)
|
34
|
+
tracking_id_header_in = to_http(:tracking_id)
|
33
35
|
request_id_header_in = to_http(:request_id)
|
34
|
-
!env[request_id_header_in]
|
36
|
+
!env[tracking_id_header_in] && !env[request_id_header_in]
|
35
37
|
end
|
36
38
|
|
37
39
|
def request_depth(env)
|
@@ -52,15 +54,15 @@ module Kiev
|
|
52
54
|
Config.instance.all_http_propagated_fields[value]
|
53
55
|
end
|
54
56
|
|
55
|
-
def
|
56
|
-
if
|
57
|
-
|
57
|
+
def make_tracking_id(tracking_id)
|
58
|
+
if tracking_id.nil? || tracking_id.empty?
|
59
|
+
internal_tracking_id
|
58
60
|
else
|
59
|
-
Util.sanitize(
|
61
|
+
Util.sanitize(tracking_id)
|
60
62
|
end
|
61
63
|
end
|
62
64
|
|
63
|
-
def
|
65
|
+
def internal_tracking_id
|
64
66
|
SecureRandom.uuid
|
65
67
|
end
|
66
68
|
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],
|
@@ -125,8 +123,8 @@ module Kiev
|
|
125
123
|
sio = StringIO.new(data[:body])
|
126
124
|
gz = Zlib::GzipReader.new(sio)
|
127
125
|
data[:body] = gz.read
|
128
|
-
rescue Zlib::GzipFile::Error =>
|
129
|
-
data[:gzip_parse_error] =
|
126
|
+
rescue Zlib::GzipFile::Error => e
|
127
|
+
data[:gzip_parse_error] = e.message
|
130
128
|
end
|
131
129
|
end
|
132
130
|
end
|
data/lib/kiev/request_id.rb
CHANGED
@@ -7,7 +7,8 @@ module Kiev
|
|
7
7
|
|
8
8
|
def wrap_request_id(context_reader, &_block)
|
9
9
|
request_store = Kiev::RequestStore.store
|
10
|
-
request_store[:
|
10
|
+
request_store[:tracking_id] = context_reader.tracking_id || context_reader.request_id
|
11
|
+
request_store[:request_id] = request_store[:tracking_id]
|
11
12
|
request_store[:request_depth] = context_reader.request_depth
|
12
13
|
request_store[:tree_path] = context_reader.tree_path
|
13
14
|
yield
|
data/lib/kiev/request_logger.rb
CHANGED
@@ -12,8 +12,8 @@ module Kiev
|
|
12
12
|
|
13
13
|
begin
|
14
14
|
return_value = yield
|
15
|
-
rescue StandardError =>
|
16
|
-
error =
|
15
|
+
rescue StandardError => e
|
16
|
+
error = e
|
17
17
|
end
|
18
18
|
|
19
19
|
begin
|
@@ -28,6 +28,7 @@ module Kiev
|
|
28
28
|
Kiev.event(event, data)
|
29
29
|
ensure
|
30
30
|
raise error if error
|
31
|
+
|
31
32
|
return_value
|
32
33
|
end
|
33
34
|
end
|
@@ -1,17 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "kiev/aws_sns/context_injector"
|
4
|
+
|
3
5
|
module Kiev
|
4
6
|
module Shoryuken
|
5
7
|
module Middleware
|
6
8
|
class MessageTracer
|
7
9
|
def call(options)
|
8
|
-
|
9
|
-
|
10
|
-
attrbutes[key] = {
|
11
|
-
data_type: "String",
|
12
|
-
string_value: value.to_s
|
13
|
-
}
|
14
|
-
end
|
10
|
+
options[:message_attributes] ||= {}
|
11
|
+
Kiev::AwsSns::ContextInjector.new.call(options[:message_attributes])
|
15
12
|
yield
|
16
13
|
end
|
17
14
|
end
|
data/lib/kiev/test.rb
CHANGED
data/lib/kiev/util.rb
CHANGED
data/lib/kiev/version.rb
CHANGED
data/lib/kiev.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "kiev/base"
|
4
|
+
require_relative "kiev/aws_sns" if defined?(AWS::SNS)
|
5
|
+
require_relative "kiev/kafka" if defined?(Kafka)
|
4
6
|
require_relative "kiev/rack" if defined?(Rack)
|
5
7
|
require_relative "kiev/railtie" if defined?(Rails)
|
6
8
|
require_relative "kiev/sidekiq" if defined?(Sidekiq)
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kiev
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Blacklane
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-10-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: oga
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.2'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: rack
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,20 +64,6 @@ dependencies:
|
|
50
64
|
- - "<"
|
51
65
|
- !ruby/object:Gem::Version
|
52
66
|
version: '1.4'
|
53
|
-
- !ruby/object:Gem::Dependency
|
54
|
-
name: oga
|
55
|
-
requirement: !ruby/object:Gem::Requirement
|
56
|
-
requirements:
|
57
|
-
- - "~>"
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
version: '2.2'
|
60
|
-
type: :runtime
|
61
|
-
prerelease: false
|
62
|
-
version_requirements: !ruby/object:Gem::Requirement
|
63
|
-
requirements:
|
64
|
-
- - "~>"
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
version: '2.2'
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
68
|
name: ruby_dig
|
69
69
|
requirement: !ruby/object:Gem::Requirement
|
@@ -82,58 +82,58 @@ dependencies:
|
|
82
82
|
name: rake
|
83
83
|
requirement: !ruby/object:Gem::Requirement
|
84
84
|
requirements:
|
85
|
-
- - "
|
85
|
+
- - "~>"
|
86
86
|
- !ruby/object:Gem::Version
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
90
|
version_requirements: !ruby/object:Gem::Requirement
|
91
91
|
requirements:
|
92
|
-
- - "
|
92
|
+
- - "~>"
|
93
93
|
- !ruby/object:Gem::Version
|
94
94
|
version: '0'
|
95
95
|
- !ruby/object:Gem::Dependency
|
96
96
|
name: rspec
|
97
97
|
requirement: !ruby/object:Gem::Requirement
|
98
98
|
requirements:
|
99
|
-
- - "
|
99
|
+
- - "~>"
|
100
100
|
- !ruby/object:Gem::Version
|
101
|
-
version: '
|
101
|
+
version: '3.10'
|
102
102
|
type: :development
|
103
103
|
prerelease: false
|
104
104
|
version_requirements: !ruby/object:Gem::Requirement
|
105
105
|
requirements:
|
106
|
-
- - "
|
106
|
+
- - "~>"
|
107
107
|
- !ruby/object:Gem::Version
|
108
|
-
version: '
|
108
|
+
version: '3.10'
|
109
109
|
- !ruby/object:Gem::Dependency
|
110
110
|
name: rubocop
|
111
111
|
requirement: !ruby/object:Gem::Requirement
|
112
112
|
requirements:
|
113
|
-
- -
|
113
|
+
- - "~>"
|
114
114
|
- !ruby/object:Gem::Version
|
115
|
-
version: 0.
|
115
|
+
version: '0.54'
|
116
116
|
type: :development
|
117
117
|
prerelease: false
|
118
118
|
version_requirements: !ruby/object:Gem::Requirement
|
119
119
|
requirements:
|
120
|
-
- -
|
120
|
+
- - "~>"
|
121
121
|
- !ruby/object:Gem::Version
|
122
|
-
version: 0.
|
122
|
+
version: '0.54'
|
123
123
|
description: Kiev is a logging tool aimed at distributed environments. It logs to
|
124
124
|
JSON, while providing human-readable output in development mode. It integrates nicely
|
125
125
|
with Rails, Sinatra and other Rack-based frameworks, Sidekiq, Que, HTTParty, Her
|
126
126
|
and other Faraday-based HTTP clients.
|
127
|
-
email:
|
127
|
+
email:
|
128
128
|
executables: []
|
129
129
|
extensions: []
|
130
130
|
extra_rdoc_files: []
|
131
131
|
files:
|
132
|
+
- ".github/workflows/push.yml"
|
132
133
|
- ".gitignore"
|
133
134
|
- ".rspec"
|
134
135
|
- ".rubocop.yml"
|
135
136
|
- ".ruby-version"
|
136
|
-
- ".travis.yml"
|
137
137
|
- Gemfile
|
138
138
|
- LICENSE.md
|
139
139
|
- README.md
|
@@ -144,13 +144,17 @@ files:
|
|
144
144
|
- gemfiles/que_0.12.3.gemfile
|
145
145
|
- gemfiles/rails_4.1.gemfile
|
146
146
|
- gemfiles/rails_4.2.gemfile
|
147
|
-
- gemfiles/
|
147
|
+
- gemfiles/rails_5.2.gemfile
|
148
|
+
- gemfiles/ruby_kafka.gemfile
|
149
|
+
- gemfiles/shoryuken_4.0.gemfile
|
148
150
|
- gemfiles/sidekiq_4.2.gemfile
|
149
151
|
- gemfiles/sinatra_1.4.gemfile
|
150
152
|
- gemfiles/sinatra_2.0.gemfile
|
151
153
|
- kiev.gemspec
|
152
154
|
- lib/ext/rack/common_logger.rb
|
153
155
|
- lib/kiev.rb
|
156
|
+
- lib/kiev/aws_sns.rb
|
157
|
+
- lib/kiev/aws_sns/context_injector.rb
|
154
158
|
- lib/kiev/base.rb
|
155
159
|
- lib/kiev/base52.rb
|
156
160
|
- lib/kiev/config.rb
|
@@ -159,6 +163,10 @@ files:
|
|
159
163
|
- lib/kiev/her_ext/client_request_id.rb
|
160
164
|
- lib/kiev/httparty.rb
|
161
165
|
- lib/kiev/json.rb
|
166
|
+
- lib/kiev/kafka.rb
|
167
|
+
- lib/kiev/kafka/context_extractor.rb
|
168
|
+
- lib/kiev/kafka/context_injector.rb
|
169
|
+
- lib/kiev/kafka/message_context.rb
|
162
170
|
- lib/kiev/logger.rb
|
163
171
|
- lib/kiev/param_filter.rb
|
164
172
|
- lib/kiev/que/job.rb
|
@@ -199,7 +207,7 @@ homepage: https://github.com/blacklane/kiev
|
|
199
207
|
licenses:
|
200
208
|
- MIT
|
201
209
|
metadata: {}
|
202
|
-
post_install_message:
|
210
|
+
post_install_message:
|
203
211
|
rdoc_options: []
|
204
212
|
require_paths:
|
205
213
|
- lib
|
@@ -207,15 +215,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
207
215
|
requirements:
|
208
216
|
- - ">="
|
209
217
|
- !ruby/object:Gem::Version
|
210
|
-
version: 2.
|
218
|
+
version: '2.5'
|
211
219
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
212
220
|
requirements:
|
213
221
|
- - ">="
|
214
222
|
- !ruby/object:Gem::Version
|
215
223
|
version: '0'
|
216
224
|
requirements: []
|
217
|
-
|
218
|
-
|
225
|
+
rubyforge_project:
|
226
|
+
rubygems_version: 2.7.6
|
227
|
+
signing_key:
|
219
228
|
specification_version: 4
|
220
229
|
summary: Distributed logging to JSON integrated with various Ruby frameworks and tools
|
221
230
|
test_files: []
|
data/.travis.yml
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
sudo: false
|
2
|
-
branches:
|
3
|
-
only:
|
4
|
-
- master
|
5
|
-
cache:
|
6
|
-
- bundler
|
7
|
-
language: ruby
|
8
|
-
rvm:
|
9
|
-
- 2.3.3
|
10
|
-
- 2.2.3
|
11
|
-
addons:
|
12
|
-
postgresql: "9.4"
|
13
|
-
services:
|
14
|
-
- postgresql
|
15
|
-
- redis-server
|
16
|
-
before_script:
|
17
|
-
- psql -c 'create database que_test;' -U postgres
|
18
|
-
gemfile:
|
19
|
-
- gemfiles/que_0.12.2.gemfile
|
20
|
-
- gemfiles/que_0.12.3.gemfile
|
21
|
-
- gemfiles/rails_4.1.gemfile
|
22
|
-
- gemfiles/rails_4.2.gemfile
|
23
|
-
- gemfiles/shoryuken_3.1.gemfile
|
24
|
-
- gemfiles/sidekiq_4.2.gemfile
|
25
|
-
- gemfiles/sinatra_1.4.gemfile
|
26
|
-
- gemfiles/sinatra_2.0.gemfile
|
27
|
-
matrix:
|
28
|
-
fast_finish: true
|