luna_park 0.11.6 → 0.12.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/gem-push.yml +3 -3
- data/.gitignore +1 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile.lock +41 -1
- data/Guardfile +42 -0
- data/lib/luna_park/http/response.rb +8 -1
- data/lib/luna_park/http/send.rb +13 -4
- data/lib/luna_park/notifiers/log/formatters.rb +70 -0
- data/lib/luna_park/notifiers/log.rb +26 -59
- data/lib/luna_park/notifiers/tagged_log/options.rb +87 -0
- data/lib/luna_park/notifiers/tagged_log/tagged_formatter.rb +90 -0
- data/lib/luna_park/notifiers/tagged_log.rb +105 -0
- data/lib/luna_park/version.rb +1 -1
- data/luna_park.gemspec +4 -0
- metadata +63 -3
- data/.github/gem-push.yml +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 14e20ec6fc8a3a6e96958a184503dbc5850dbf74e14c8d5943514c32c264337b
|
4
|
+
data.tar.gz: 6b3860177c18140dc5ea8c3a1e5e26577a952597d6f9c8f820499b6128b29d97
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 509321c66abc91c03bfd78cad59f8201c0961a064facf057bdd3db339747a4adb7eb227e09228bb486e8aa7261348d64fe554e034ba2d07b438d963ced03f004
|
7
|
+
data.tar.gz: 6c95a9de22724e65fd6afccc731b671aec2853e15bc7948a3ea395ac2735e1b30d0130773a8fccb9d6d714537cc0bd2ed44e3301b1e72de25f9cbab3ca4d4486
|
@@ -13,11 +13,11 @@ jobs:
|
|
13
13
|
packages: write
|
14
14
|
|
15
15
|
steps:
|
16
|
-
- uses: actions/checkout@
|
16
|
+
- uses: actions/checkout@v3
|
17
17
|
- name: Set up Ruby 2.5
|
18
|
-
uses:
|
18
|
+
uses: ruby/setup-ruby@v1
|
19
19
|
with:
|
20
|
-
ruby-version: 2.5
|
20
|
+
ruby-version: '2.5'
|
21
21
|
|
22
22
|
- name: Publish to GPR
|
23
23
|
run: |
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,14 @@ 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
|
+
## [0.12.0] - 2023-02-23
|
8
|
+
Changed
|
9
|
+
- Added `TaggedLog`
|
10
|
+
|
11
|
+
## [0.11.7] - 2022-10-07
|
12
|
+
Changed
|
13
|
+
- Added `formatter` to `Notifiers::Log`. Using `format` in initializer is now deprecated.
|
14
|
+
|
7
15
|
## [0.11.6] - 2021-10-06
|
8
16
|
Changed
|
9
17
|
- in `UseCases::Scenario` now abstract method is `#perform` - not `call!`. It is backward-compatible change: `call!` still works as abstract, and public interface was not changed.
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
luna_park (0.
|
4
|
+
luna_park (0.12.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -69,6 +69,29 @@ GEM
|
|
69
69
|
multipart-post (>= 1.2, < 3)
|
70
70
|
ruby2_keywords
|
71
71
|
faraday-net_http (1.0.1)
|
72
|
+
ffi (1.15.5)
|
73
|
+
formatador (1.1.0)
|
74
|
+
guard (2.18.0)
|
75
|
+
formatador (>= 0.2.4)
|
76
|
+
listen (>= 2.7, < 4.0)
|
77
|
+
lumberjack (>= 1.0.12, < 2.0)
|
78
|
+
nenv (~> 0.1)
|
79
|
+
notiffany (~> 0.0)
|
80
|
+
pry (>= 0.13.0)
|
81
|
+
shellany (~> 0.0)
|
82
|
+
thor (>= 0.18.1)
|
83
|
+
guard-bundler (3.0.1)
|
84
|
+
bundler (>= 2.1, < 3)
|
85
|
+
guard (~> 2.2)
|
86
|
+
guard-compat (~> 1.1)
|
87
|
+
guard-compat (1.2.1)
|
88
|
+
guard-rspec (4.7.3)
|
89
|
+
guard (~> 2.1)
|
90
|
+
guard-compat (~> 1.1)
|
91
|
+
rspec (>= 2.99.0, < 4.0)
|
92
|
+
guard-rubocop (1.5.0)
|
93
|
+
guard (~> 2.0)
|
94
|
+
rubocop (< 2.0)
|
72
95
|
hashdiff (1.0.1)
|
73
96
|
http-accept (1.7.0)
|
74
97
|
http-cookie (1.0.3)
|
@@ -77,12 +100,20 @@ GEM
|
|
77
100
|
concurrent-ruby (~> 1.0)
|
78
101
|
iniparse (1.5.0)
|
79
102
|
json (2.3.1)
|
103
|
+
listen (3.8.0)
|
104
|
+
rb-fsevent (~> 0.10, >= 0.10.3)
|
105
|
+
rb-inotify (~> 0.9, >= 0.9.10)
|
106
|
+
lumberjack (1.2.8)
|
80
107
|
method_source (1.0.0)
|
81
108
|
mime-types (3.3.1)
|
82
109
|
mime-types-data (~> 3.2015)
|
83
110
|
mime-types-data (3.2020.0512)
|
84
111
|
multipart-post (2.1.1)
|
112
|
+
nenv (0.3.0)
|
85
113
|
netrc (0.11.0)
|
114
|
+
notiffany (0.1.3)
|
115
|
+
nenv (~> 0.1)
|
116
|
+
shellany (~> 0.0)
|
86
117
|
overcommit (0.55.0)
|
87
118
|
childprocess (>= 0.6.3, < 5)
|
88
119
|
iniparse (~> 1.4)
|
@@ -98,6 +129,9 @@ GEM
|
|
98
129
|
public_suffix (4.0.6)
|
99
130
|
rainbow (3.0.0)
|
100
131
|
rake (13.0.1)
|
132
|
+
rb-fsevent (0.11.2)
|
133
|
+
rb-inotify (0.10.1)
|
134
|
+
ffi (~> 1.0)
|
101
135
|
regexp_parser (1.7.1)
|
102
136
|
rest-client (2.1.0)
|
103
137
|
http-accept (>= 1.7.0, < 2.0)
|
@@ -139,10 +173,12 @@ GEM
|
|
139
173
|
sentry-ruby-core (4.2.1)
|
140
174
|
concurrent-ruby
|
141
175
|
faraday
|
176
|
+
shellany (0.0.1)
|
142
177
|
simplecov (0.18.5)
|
143
178
|
docile (~> 1.1)
|
144
179
|
simplecov-html (~> 0.11)
|
145
180
|
simplecov-html (0.12.2)
|
181
|
+
thor (1.2.1)
|
146
182
|
timecop (0.9.1)
|
147
183
|
unf (0.1.4)
|
148
184
|
unf_ext
|
@@ -163,6 +199,10 @@ DEPENDENCIES
|
|
163
199
|
byebug (~> 11.1)
|
164
200
|
codecov (~> 0.2)
|
165
201
|
dry-validation (~> 1.1)
|
202
|
+
guard
|
203
|
+
guard-bundler
|
204
|
+
guard-rspec
|
205
|
+
guard-rubocop
|
166
206
|
i18n (~> 1.8)
|
167
207
|
luna_park!
|
168
208
|
overcommit (~> 0.55)
|
data/Guardfile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
ignore(/
|
4
|
+
bin | public | node_modules | tmp | .git
|
5
|
+
/x)
|
6
|
+
|
7
|
+
guard :bundler do
|
8
|
+
watch('Gemfile')
|
9
|
+
watch('Gemfile.lock')
|
10
|
+
end
|
11
|
+
|
12
|
+
group :specs, halt_on_fail: true do
|
13
|
+
guard :rspec,
|
14
|
+
cmd: 'bundle exec rspec --color --format documentation',
|
15
|
+
all_after_pass: false,
|
16
|
+
all_on_start: false,
|
17
|
+
failed_mode: :keep do
|
18
|
+
require 'guard/rspec/dsl'
|
19
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
20
|
+
|
21
|
+
# Feel free to open issues for suggestions and improvements
|
22
|
+
|
23
|
+
# RSpec files
|
24
|
+
rspec = dsl.rspec
|
25
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
26
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
27
|
+
watch(rspec.spec_files)
|
28
|
+
|
29
|
+
# Ruby files
|
30
|
+
ruby = dsl.ruby
|
31
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
32
|
+
|
33
|
+
watch(%r{^config/(.+)\.rb$})
|
34
|
+
|
35
|
+
watch(%r{^spec/factories/(.+)\.rb$})
|
36
|
+
end
|
37
|
+
|
38
|
+
guard :rubocop, all_on_start: false, keep_failed: false do
|
39
|
+
watch(/.+\.rb$/)
|
40
|
+
watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
|
41
|
+
end
|
42
|
+
end
|
@@ -113,6 +113,13 @@ module LunaPark
|
|
113
113
|
# @return Hash
|
114
114
|
attr_reader :cookies
|
115
115
|
|
116
|
+
# Exception of failed request
|
117
|
+
# Can be raised after call (without bang)
|
118
|
+
# Will be raised after call! (with bang)
|
119
|
+
#
|
120
|
+
# @return LunaPark::Errors::Http
|
121
|
+
attr_reader :exception
|
122
|
+
|
116
123
|
# The request that actually initializes the current response
|
117
124
|
#
|
118
125
|
# @example
|
@@ -344,7 +351,7 @@ module LunaPark
|
|
344
351
|
end
|
345
352
|
|
346
353
|
# @example
|
347
|
-
#
|
354
|
+
# response.to_h # => {
|
348
355
|
# :code=>200,
|
349
356
|
# :body=>"John Doe, Marry Ann",
|
350
357
|
# :headers=>{}, :cookies=>{},
|
data/lib/luna_park/http/send.rb
CHANGED
@@ -62,7 +62,7 @@ module LunaPark
|
|
62
62
|
# @return [LunaPark::Http::Response]
|
63
63
|
def call!
|
64
64
|
call.tap do |response|
|
65
|
-
raise
|
65
|
+
raise response.exception unless response.exception.nil?
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
@@ -82,7 +82,7 @@ module LunaPark
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def build_original_response(rest_response)
|
85
|
-
|
85
|
+
build_response(
|
86
86
|
body: rest_response&.body,
|
87
87
|
code: rest_response&.code || 0,
|
88
88
|
headers: rest_response&.headers,
|
@@ -92,11 +92,20 @@ module LunaPark
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def build_timeout_response
|
95
|
-
|
95
|
+
build_response code: 408, request: original_request
|
96
96
|
end
|
97
97
|
|
98
|
+
# ! 503 != ECONNREFUSED (https://www.rfc-editor.org/rfc/rfc7231#section-6.6.4)
|
98
99
|
def build_unavailable_response
|
99
|
-
|
100
|
+
build_response code: 503, request: original_request
|
101
|
+
end
|
102
|
+
|
103
|
+
def build_response(code:, request:, **opts)
|
104
|
+
Response
|
105
|
+
.new(code: code, request: request, **opts)
|
106
|
+
.tap do |response|
|
107
|
+
response.exception = Errors::Http.new(response.status, response: response) unless response.success?
|
108
|
+
end
|
100
109
|
end
|
101
110
|
end
|
102
111
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
require 'pp'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module LunaPark
|
7
|
+
module Notifiers
|
8
|
+
class Log
|
9
|
+
module Formatters
|
10
|
+
# Fomatter - callable object to format log messages. Out of the box there are four types:
|
11
|
+
|
12
|
+
# - SINGLE - output is a single line string message.
|
13
|
+
# notifier = LunaPark::Notifiers::Log.new(formatter: LunaPark::Notifiers::Log::Formatters::SINGLE)
|
14
|
+
# notifier.info('You hear', dog: 'wow', cats: {chloe: 'mow', timmy: 'mow'})
|
15
|
+
#
|
16
|
+
# # I, [2022-09-29T10:51:15.753646 #28763] INFO -- : String - You hear {:dog=>"wow", :cats=>{:chloe=>"mow", :timmy=>"mow"}}
|
17
|
+
#
|
18
|
+
SINGLE = lambda do |klass, message, details = {}|
|
19
|
+
details.empty? ? "#<#{klass}> #{message}" : "#<#{klass}> #{message} #{details}"
|
20
|
+
end
|
21
|
+
|
22
|
+
# - MULTILINE - this format may become more preferred for development mode.
|
23
|
+
# notifier = LunaPark::Notifiers::Log.new(formatter: LunaPark::Notifiers::Log::Formatters::MULTILINE)
|
24
|
+
# notifier.info('You hear', dog: 'wow', cat: {timmy:'purr'}, cow: 'moo', duck: 'quack', horse: 'yell' )
|
25
|
+
#
|
26
|
+
# # I, [2022-09-29T10:56:21.463211 #28763] INFO -- : {:class=>String,
|
27
|
+
# # :message=>"You hear",
|
28
|
+
# # :details=>
|
29
|
+
# # {:dog=>"wow",
|
30
|
+
# # :cat=>{:timmy=>"purr"},
|
31
|
+
# # :cow=>"moo",
|
32
|
+
# # :duck=>"quack",
|
33
|
+
# # :horse=>"yell"}}
|
34
|
+
MULTILINE = lambda do |klass, message, details = {}|
|
35
|
+
PP.pp({ class: klass, message: message, details: details }, '')
|
36
|
+
end
|
37
|
+
|
38
|
+
# - JSON - this format should be good choose for logger which be processed by external logger system
|
39
|
+
# notifier = LunaPark::Notifiers::Log.new(formatter: LunaPark::Notifiers::Log::Formatters::JSON)
|
40
|
+
# notifier.info('You hear', dog: 'wow', cats: {chloe: 'mow', timmy: 'mow'})
|
41
|
+
#
|
42
|
+
# # I, [2022-09-29T12:00:47.600052 #90508] INFO -- : {"class":"String", "message":"You hear",
|
43
|
+
# # "details":{"dog":"wow","cats":{"chloe":"mow","timmy":"mow"}}}
|
44
|
+
JSON = lambda do |klass, message, details = {}|
|
45
|
+
::JSON.generate(class: klass, message: message, details: details)
|
46
|
+
end
|
47
|
+
|
48
|
+
# - PRETTY_JSON - pretty json output
|
49
|
+
# notifier = LunaPark::Notifiers::Log.new(formatter: LunaPark::Notifiers::Log::Formatters::PRETTY_JSON)
|
50
|
+
# notifier.info('You hear', dog: 'wow', cat: {timmy:'purr'}, cow: 'moo', duck: 'quack', horse: 'yell')
|
51
|
+
#
|
52
|
+
# # I, [2022-09-29T12:02:25.236301 #90508] INFO -- : {
|
53
|
+
# # "class": "String",
|
54
|
+
# # "message": "You hear",
|
55
|
+
# # "details": {
|
56
|
+
# # "dog": "wow",
|
57
|
+
# # "cat": {
|
58
|
+
# # "timmy": "purr"
|
59
|
+
# # },
|
60
|
+
# # "cow": "moo",
|
61
|
+
# # "duck": "quack",
|
62
|
+
# # "horse": "yell"
|
63
|
+
# # }
|
64
|
+
PRETTY_JSON = lambda do |klass, message, details = {}|
|
65
|
+
::JSON.pretty_generate(class: klass, message: message, details: details)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -1,9 +1,8 @@
|
|
1
1
|
# frozen_string_literal: false
|
2
2
|
|
3
|
-
require 'json'
|
4
|
-
require 'pp'
|
5
3
|
require 'logger'
|
6
4
|
require 'luna_park/extensions/severity_levels'
|
5
|
+
require 'luna_park/notifiers/log/formatters'
|
7
6
|
require 'luna_park/errors'
|
8
7
|
|
9
8
|
module LunaPark
|
@@ -30,52 +29,14 @@ module LunaPark
|
|
30
29
|
class Log
|
31
30
|
include Extensions::SeverityLevels
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
# Format of log output. Define output format of log message. It can be four types.
|
36
|
-
#
|
37
|
-
# - :single or :string - Then you will get single line string message. This is default
|
38
|
-
# format for the logger.
|
39
|
-
# notifier = LunaPark::Notifiers::Log.new(format: :single)
|
40
|
-
# notifier.message('You hear', dog: 'wow', cats: {chloe: 'mow', timmy: 'mow'})
|
41
|
-
#
|
42
|
-
# # E, [2020-06-13T14:50:22 #20538] ERROR -- : You hear {:dog=>"wow", :cats=>{:chloe=>"mow", :timmy=>"mow"}}
|
43
|
-
#
|
44
|
-
# - :multiline - this format may become more preferred for development mode.
|
45
|
-
# notifier = LunaPark::Notifiers::Log.new(format: :multiline)
|
46
|
-
# notifier.message('You hear', dog: 'wow', cat: {timmy:'purr'}, cow: 'moo', duck: 'quack', horse: 'yell' )
|
47
|
-
#
|
48
|
-
# # E, [2020-06-13T18:24:37.592652 #22786] ERROR -- : {:message=>"You hear",
|
49
|
-
# # :details=>
|
50
|
-
# # {:dog=>"wow",
|
51
|
-
# # :cat=>{:timmy=>"purr"},
|
52
|
-
# # :cow=>"moo",
|
53
|
-
# # :duck=>"quack",
|
54
|
-
# # :horse=>"yell"}}
|
32
|
+
# Callable object to format log messages.
|
55
33
|
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
34
|
+
# pretty_formatter = ->(klass, message, details) { "#{klass} - #{message} - #{details}" }
|
35
|
+
# notifier = LunaPark::Notifiers::Log.new(formatter: pretty_formatter)
|
36
|
+
# notifier.info('You hear', dog: 'wow', cats: {chloe: 'mow', timmy: 'mow'})
|
37
|
+
# => I, [2022-09-29T10:51:15.753646 #28763] INFO -- : String - You hear - {:dog=>"wow", :cats=>{:chloe=>"mow", :timmy=>"mow"}}
|
59
38
|
#
|
60
|
-
|
61
|
-
# # "cats":{"chloe":"mow","timmy":"mow"}}}
|
62
|
-
#
|
63
|
-
# - :pretty_json - pretty json output
|
64
|
-
# notifier = LunaPark::Notifiers::Log.new(format: :pretty_json)
|
65
|
-
# notifier.message('You hear', dog: 'wow', cat: {timmy:'purr'}, cow: 'moo', duck: 'quack', horse: 'yell')
|
66
|
-
#
|
67
|
-
# # E, [2020-06-13T18:30:26.856084 #22786] ERROR -- : {
|
68
|
-
# # "message": "You hear",
|
69
|
-
# # "details": {
|
70
|
-
# # "dog": "wow",
|
71
|
-
# # "cat": {
|
72
|
-
# # "timmy": "purr"
|
73
|
-
# # },
|
74
|
-
# # "cow": "moo",
|
75
|
-
# # "duck": "quack",
|
76
|
-
# # "horse": "yell"
|
77
|
-
# # }
|
78
|
-
attr_reader :format
|
39
|
+
attr_reader :formatter
|
79
40
|
|
80
41
|
# Logger which used for output all notify. Should be instance of Logger class.
|
81
42
|
# You can define it in two ways.
|
@@ -97,14 +58,18 @@ module LunaPark
|
|
97
58
|
|
98
59
|
# Create new log notifier
|
99
60
|
#
|
100
|
-
# @param logger
|
101
|
-
# @param
|
102
|
-
# @param
|
103
|
-
|
104
|
-
|
105
|
-
|
61
|
+
# @param logger - Logger which used for output all notify see #logger
|
62
|
+
# @param formatter - Log messages formatter see #formatter
|
63
|
+
# @param format - Formatter name. Deprecated and will be removed in a future version
|
64
|
+
# @param min_lvl - What level should a message be for it to be processed by a notifier
|
65
|
+
def initialize(logger: nil, format: nil, formatter: nil, min_lvl: :debug)
|
106
66
|
@logger = logger || self.class.default_logger
|
107
|
-
@
|
67
|
+
@formatter = formatter || Formatters::SINGLE
|
68
|
+
# @todo Remove format param in the future version
|
69
|
+
unless format.nil?
|
70
|
+
@formatter = formatter_by_name(format)
|
71
|
+
warn 'warn [DEPRECATION] `format` parameter is deprecated, use `formatter` instead'
|
72
|
+
end
|
108
73
|
self.min_lvl = min_lvl
|
109
74
|
end
|
110
75
|
|
@@ -160,13 +125,15 @@ module LunaPark
|
|
160
125
|
|
161
126
|
def serialize(obj, **details)
|
162
127
|
details = extend(details, with: obj)
|
163
|
-
|
128
|
+
formatter.call(obj.class, String(obj), details)
|
129
|
+
end
|
164
130
|
|
165
|
-
|
166
|
-
|
167
|
-
when :
|
168
|
-
when :
|
169
|
-
|
131
|
+
def formatter_by_name(name)
|
132
|
+
case name
|
133
|
+
when :json then Formatters::JSON
|
134
|
+
when :multiline then Formatters::MULTILINE
|
135
|
+
when :pretty_json then Formatters::PRETTY_JSON
|
136
|
+
else Formatters::SINGLE
|
170
137
|
end
|
171
138
|
end
|
172
139
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
require 'luna_park/values/compound'
|
4
|
+
|
5
|
+
module LunaPark
|
6
|
+
module Notifiers
|
7
|
+
module TaggedLog
|
8
|
+
class Options < LunaPark::Values::Compound
|
9
|
+
attr_reader :default_tag, :app, :app_env, :instance, :min_lvl
|
10
|
+
|
11
|
+
def initialize(attrs = {})
|
12
|
+
logger_conf_error if config_incorrect?(attrs)
|
13
|
+
set_attributes attrs
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param [Notifiers::Log::Options, Hash] other
|
17
|
+
# @return [Notifiers::Log::Options]
|
18
|
+
def merge!(other)
|
19
|
+
other = self.class.wrap(other)
|
20
|
+
|
21
|
+
self.default_tag ||= other.default_tag
|
22
|
+
self.app ||= other.app
|
23
|
+
self.app_env ||= other.app_env
|
24
|
+
self.instance ||= other.instance
|
25
|
+
self.min_lvl ||= other.min_lvl
|
26
|
+
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def merge(other)
|
31
|
+
dup.merge!(other)
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_h
|
35
|
+
{
|
36
|
+
default_tag: default_tag,
|
37
|
+
app: app,
|
38
|
+
app_env: app_env,
|
39
|
+
instance: instance,
|
40
|
+
min_lvl: min_lvl
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def config_incorrect?(attrs)
|
47
|
+
return true if attrs.empty?
|
48
|
+
|
49
|
+
!%i[default_tag app app_env instance min_lvl].all? do |required_key|
|
50
|
+
attrs.keys.include?(required_key)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def logger_conf_error
|
55
|
+
raise ArgumentError, 'TaggedLog not properly configured'
|
56
|
+
end
|
57
|
+
|
58
|
+
def default_tag=(val)
|
59
|
+
logger_conf_error if val.nil? || val.empty?
|
60
|
+
logger_conf_error unless val.is_a?(String) || val.is_a?(Symbol)
|
61
|
+
@default_tag = val
|
62
|
+
end
|
63
|
+
|
64
|
+
def app=(val)
|
65
|
+
logger_conf_error if val.nil? || val.empty? || !val.is_a?(String)
|
66
|
+
@app = val
|
67
|
+
end
|
68
|
+
|
69
|
+
def app_env=(val)
|
70
|
+
logger_conf_error if val.nil? || val.empty? || !val.is_a?(String)
|
71
|
+
@app_env = val
|
72
|
+
end
|
73
|
+
|
74
|
+
def instance=(val)
|
75
|
+
logger_conf_error if val.nil? || val.empty? || !val.is_a?(String)
|
76
|
+
@instance = val
|
77
|
+
end
|
78
|
+
|
79
|
+
def min_lvl=(val)
|
80
|
+
logger_conf_error if val.nil? || val.empty?
|
81
|
+
logger_conf_error unless val.is_a?(String) || val.is_a?(Symbol)
|
82
|
+
@min_lvl = val.to_sym
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module LunaPark
|
6
|
+
module Notifiers
|
7
|
+
module TaggedLog
|
8
|
+
class TaggedFormatter < Logger::Formatter
|
9
|
+
attr_accessor :config
|
10
|
+
|
11
|
+
def call(severity, timestamp, _, msg, tags = nil)
|
12
|
+
payload = common_payload(severity, timestamp, tags)
|
13
|
+
.merge(msg_payload(msg[:original_msg]))
|
14
|
+
|
15
|
+
deep_merge!(payload, details_payload(msg[:details]))
|
16
|
+
|
17
|
+
::JSON.generate(payload) << "\n"
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def details_payload(hash)
|
23
|
+
details = hash.delete(:details)
|
24
|
+
payload = { details: hash }
|
25
|
+
deep_merge!(payload, { details: details }) unless details.nil?
|
26
|
+
payload
|
27
|
+
end
|
28
|
+
|
29
|
+
def common_payload(severity, timestamp, tags)
|
30
|
+
{
|
31
|
+
tags: [@config.default_tag, tags].join(' ').strip,
|
32
|
+
app: @config.app,
|
33
|
+
app_env: @config.app_env,
|
34
|
+
instance: @config.instance,
|
35
|
+
created_at: timestamp.iso8601(3),
|
36
|
+
ok: !%w[FATAL ERROR].include?(severity)
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def msg_payload(msg)
|
41
|
+
case msg
|
42
|
+
when ::Exception
|
43
|
+
error_payload(msg)
|
44
|
+
when Hash
|
45
|
+
hash_payload(msg)
|
46
|
+
else
|
47
|
+
{ details: { message: try_to_json(msg) } }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def error_payload(e)
|
52
|
+
error_hash = {
|
53
|
+
class: e.class,
|
54
|
+
message: e.message
|
55
|
+
}
|
56
|
+
error_hash.merge!(backtrace: "\n" + e.backtrace.join("\n") + "\n") if e.backtrace
|
57
|
+
payload = {
|
58
|
+
error: error_hash,
|
59
|
+
ok: false
|
60
|
+
}
|
61
|
+
payload.merge!(details: e.details) if e.respond_to?(:details)
|
62
|
+
payload
|
63
|
+
end
|
64
|
+
|
65
|
+
def hash_payload(msg)
|
66
|
+
details = msg.delete(:details)
|
67
|
+
payload = { details: msg }
|
68
|
+
deep_merge!(payload, { details: details }) unless details.nil?
|
69
|
+
payload
|
70
|
+
end
|
71
|
+
|
72
|
+
def try_to_json(str)
|
73
|
+
::JSON.parse(str)
|
74
|
+
rescue ::JSON::ParserError
|
75
|
+
str
|
76
|
+
end
|
77
|
+
|
78
|
+
def deep_merge!(hash, other_hash)
|
79
|
+
hash.merge!(other_hash) do |_, this_val, other_val|
|
80
|
+
if this_val.is_a?(Hash) && other_val.is_a?(Hash)
|
81
|
+
deep_merge!(this_val, other_val)
|
82
|
+
else
|
83
|
+
other_val
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
require 'forwardable'
|
5
|
+
require 'luna_park/extensions/severity_levels'
|
6
|
+
require 'luna_park/notifiers/tagged_log/options'
|
7
|
+
require 'luna_park/notifiers/tagged_log/tagged_formatter'
|
8
|
+
|
9
|
+
module LunaPark
|
10
|
+
module Notifiers
|
11
|
+
module TaggedLog
|
12
|
+
include Extensions::SeverityLevels
|
13
|
+
extend Forwardable
|
14
|
+
|
15
|
+
SEVERITY_LEVELS = {
|
16
|
+
unknown: Logger::Severity::UNKNOWN,
|
17
|
+
fatal: Logger::Severity::FATAL,
|
18
|
+
error: Logger::Severity::ERROR,
|
19
|
+
warning: Logger::Severity::WARN,
|
20
|
+
info: Logger::Severity::INFO,
|
21
|
+
debug: Logger::Severity::DEBUG
|
22
|
+
}.freeze
|
23
|
+
|
24
|
+
private_constant :SEVERITY_LEVELS
|
25
|
+
|
26
|
+
def_delegators :formatter, :push_tags, :clear_tags!
|
27
|
+
attr_accessor :output
|
28
|
+
|
29
|
+
module Formatter
|
30
|
+
def call(severity, timestamp, progname, msg)
|
31
|
+
super(severity, timestamp, progname, msg, tags_text)
|
32
|
+
end
|
33
|
+
|
34
|
+
def tagged(*tags)
|
35
|
+
new_tags = push_tags(*tags)
|
36
|
+
yield self
|
37
|
+
ensure
|
38
|
+
pop_tags(new_tags.size)
|
39
|
+
end
|
40
|
+
|
41
|
+
def push_tags(*tags)
|
42
|
+
tags.flatten!
|
43
|
+
tags.reject! { |t| t.respond_to?(:empty?) ? !!t.empty? : !t }
|
44
|
+
current_tags.concat tags
|
45
|
+
tags
|
46
|
+
end
|
47
|
+
|
48
|
+
def pop_tags(size = 1)
|
49
|
+
current_tags.pop(size)
|
50
|
+
end
|
51
|
+
|
52
|
+
def clear_tags!
|
53
|
+
current_tags.clear
|
54
|
+
end
|
55
|
+
|
56
|
+
def current_tags
|
57
|
+
thread_key = @thread_key ||= "tagged_log_tag_store_tags:#{object_id}"
|
58
|
+
Thread.current[thread_key] ||= []
|
59
|
+
end
|
60
|
+
|
61
|
+
def tags_text
|
62
|
+
current_tags.join(' ').strip
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def tagged(*tags)
|
67
|
+
if block_given?
|
68
|
+
formatter.tagged(*tags) { yield self }
|
69
|
+
else
|
70
|
+
logger = LunaPark::Notifiers::TaggedLog.new(
|
71
|
+
output, **formatter.config.to_h
|
72
|
+
)
|
73
|
+
logger.push_tags(*formatter.current_tags, *tags)
|
74
|
+
logger
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def post(msg, lvl: :error, **details)
|
79
|
+
severity = severity(lvl)
|
80
|
+
message = { original_msg: msg, details: details }
|
81
|
+
add severity, message
|
82
|
+
end
|
83
|
+
|
84
|
+
def severity(lvl)
|
85
|
+
severity = SEVERITY_LEVELS[lvl]
|
86
|
+
raise ArgumentError, "Unknown level #{lvl}" if severity.nil?
|
87
|
+
|
88
|
+
severity
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.new(output = $stdout, **options)
|
92
|
+
config = LunaPark::Notifiers::TaggedLog::Options.wrap(options)
|
93
|
+
|
94
|
+
logger = Logger.new(output)
|
95
|
+
logger.formatter = LunaPark::Notifiers::TaggedLog::TaggedFormatter.new
|
96
|
+
logger.formatter.config = config
|
97
|
+
logger.formatter.extend(Formatter)
|
98
|
+
logger.extend(self)
|
99
|
+
logger.output = output
|
100
|
+
logger.min_lvl = config.min_lvl
|
101
|
+
logger
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
data/lib/luna_park/version.rb
CHANGED
data/luna_park.gemspec
CHANGED
@@ -39,6 +39,10 @@ Gem::Specification.new do |spec|
|
|
39
39
|
spec.add_development_dependency 'byebug', '~> 11.1'
|
40
40
|
spec.add_development_dependency 'codecov', '~> 0.2'
|
41
41
|
spec.add_development_dependency 'dry-validation', '~> 1.1'
|
42
|
+
spec.add_development_dependency 'guard'
|
43
|
+
spec.add_development_dependency 'guard-bundler'
|
44
|
+
spec.add_development_dependency 'guard-rspec'
|
45
|
+
spec.add_development_dependency 'guard-rubocop'
|
42
46
|
spec.add_development_dependency 'i18n', '~> 1.8'
|
43
47
|
spec.add_development_dependency 'overcommit', '~> 0.55'
|
44
48
|
spec.add_development_dependency 'pry', '~> 0.13'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: luna_park
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexander Kudrin
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2023-02-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bugsnag
|
@@ -81,6 +81,62 @@ dependencies:
|
|
81
81
|
- - "~>"
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '1.1'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: guard
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: guard-bundler
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: guard-rspec
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: guard-rubocop
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
84
140
|
- !ruby/object:Gem::Dependency
|
85
141
|
name: i18n
|
86
142
|
requirement: !ruby/object:Gem::Requirement
|
@@ -270,7 +326,6 @@ executables: []
|
|
270
326
|
extensions: []
|
271
327
|
extra_rdoc_files: []
|
272
328
|
files:
|
273
|
-
- ".github/gem-push.yml"
|
274
329
|
- ".github/workflows/gem-push.yml"
|
275
330
|
- ".gitignore"
|
276
331
|
- ".overcommit.yml"
|
@@ -282,6 +337,7 @@ files:
|
|
282
337
|
- CHANGELOG.md
|
283
338
|
- Gemfile
|
284
339
|
- Gemfile.lock
|
340
|
+
- Guardfile
|
285
341
|
- LICENSE
|
286
342
|
- LICENSE.txt
|
287
343
|
- README.md
|
@@ -375,7 +431,11 @@ files:
|
|
375
431
|
- lib/luna_park/mappers/simple.rb
|
376
432
|
- lib/luna_park/notifiers/bugsnag.rb
|
377
433
|
- lib/luna_park/notifiers/log.rb
|
434
|
+
- lib/luna_park/notifiers/log/formatters.rb
|
378
435
|
- lib/luna_park/notifiers/sentry.rb
|
436
|
+
- lib/luna_park/notifiers/tagged_log.rb
|
437
|
+
- lib/luna_park/notifiers/tagged_log/options.rb
|
438
|
+
- lib/luna_park/notifiers/tagged_log/tagged_formatter.rb
|
379
439
|
- lib/luna_park/repositories/postgres.rb
|
380
440
|
- lib/luna_park/repositories/sequel.rb
|
381
441
|
- lib/luna_park/repository.rb
|
data/.github/gem-push.yml
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
name: Ruby Gem
|
2
|
-
|
3
|
-
on:
|
4
|
-
push:
|
5
|
-
branches: [ master ]
|
6
|
-
|
7
|
-
jobs:
|
8
|
-
build:
|
9
|
-
name: Build + Publish
|
10
|
-
runs-on: ubuntu-latest
|
11
|
-
permissions:
|
12
|
-
contents: read
|
13
|
-
packages: write
|
14
|
-
|
15
|
-
steps:
|
16
|
-
- uses: actions/checkout@v2
|
17
|
-
- name: Set up Ruby 2.6
|
18
|
-
uses: actions/setup-ruby@v1
|
19
|
-
with:
|
20
|
-
ruby-version: 2.5.x
|
21
|
-
|
22
|
-
- name: Publish to GPR
|
23
|
-
run: |
|
24
|
-
mkdir -p $HOME/.gem
|
25
|
-
touch $HOME/.gem/credentials
|
26
|
-
chmod 0600 $HOME/.gem/credentials
|
27
|
-
printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
28
|
-
gem build *.gemspec
|
29
|
-
gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem
|
30
|
-
env:
|
31
|
-
GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}"
|
32
|
-
OWNER: ${{ github.repository_owner }}
|
33
|
-
|
34
|
-
- name: Publish to RubyGems
|
35
|
-
run: |
|
36
|
-
mkdir -p $HOME/.gem
|
37
|
-
touch $HOME/.gem/credentials
|
38
|
-
chmod 0600 $HOME/.gem/credentials
|
39
|
-
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
40
|
-
gem build *.gemspec
|
41
|
-
gem push *.gem
|
42
|
-
env:
|
43
|
-
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
|