loggun 0.1.0 → 0.4.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 +4 -4
- data/README.md +95 -28
- data/lib/loggun.rb +14 -1
- data/lib/loggun/config.rb +22 -5
- data/lib/loggun/formatter.rb +19 -6
- data/lib/loggun/helpers.rb +58 -51
- data/lib/loggun/modifiers/active_record.rb +22 -0
- data/lib/loggun/modifiers/active_record/loggun_log_subscriber.rb +22 -0
- data/lib/loggun/modifiers/base.rb +4 -0
- data/lib/loggun/modifiers/sidekiq.rb +12 -2
- data/lib/loggun/modifiers/sidekiq/sidekiq4.rb +39 -0
- data/lib/loggun/modifiers/sidekiq/sidekiq6.rb +25 -0
- data/lib/loggun/version.rb +1 -1
- data/loggun.gemspec +1 -1
- metadata +8 -6
- data/lib/loggun/modifiers/incoming_http.rb +0 -19
- data/lib/loggun/modifiers/incoming_http/log_http_actions.rb +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a78f3c782857269e283aa2f00ef6f5a2002e57c1e0d2fe5d43284a54d5aa106
|
4
|
+
data.tar.gz: fb9d8dad64af86d1f43c510dc34c1fd3acb9a515441315973ab0a5b72d493099
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0d93bbbe8ed26b5c5decc4d88c16876d4db185d5ae415b07fb47a23848149183e56fb0be6128f8c321410d205d19778228888f9cdb7ce57414ba29c380f22db
|
7
|
+
data.tar.gz: '08d78b02426b5b3da9a31b90bf3715c9728de0eaeb40ed9d5b55ccfeab76c3e241146fcdaa9f052b11ee233a40fdb07e68be5f33ff4a104467cbd08b959fe07a'
|
data/README.md
CHANGED
@@ -21,6 +21,23 @@ gem 'loggun'
|
|
21
21
|
$ bundle
|
22
22
|
|
23
23
|
## Использование
|
24
|
+
Вы можете использовать Loggun как обертку для вашего Logger. Для этого необходимо передать
|
25
|
+
ему инстанс вашего логгера и настроить его formatter:
|
26
|
+
```ruby
|
27
|
+
Loggun.logger = Rails.logger
|
28
|
+
Loggun.logger.formatter = Loggun::Formatter.new
|
29
|
+
```
|
30
|
+
|
31
|
+
Теперь вы можете использовать Loggun для логгирования в стандартизированном формате:
|
32
|
+
```ruby
|
33
|
+
Loggun.info('http_request.api.request', user_id: current_user.id)
|
34
|
+
#=> 2020-04-11T22:35:04.225+03:00 - 170715 INFO http_request.api.request - {"user_id": 5465}
|
35
|
+
...
|
36
|
+
Loggun.info('http_request.api.response', user_id: current_user.id, success: true)
|
37
|
+
#=> 2020-04-11T22:35:04.225+03:00 - 170715 INFO http_request.api.response - {"user_id": 5465, "success": true}
|
38
|
+
```
|
39
|
+
|
40
|
+
Подробнее об конфигурации и использовании Loggun ниже.
|
24
41
|
|
25
42
|
### Конфигурация
|
26
43
|
Для успешной конфигурации гема необходимо подгружать файл при инициализации вашего приложения.
|
@@ -32,6 +49,7 @@ Loggun::Config.configure do |config|
|
|
32
49
|
config.precision = :milliseconds
|
33
50
|
config.pattern = '%{time} - %{pid} %{severity} %{type} %{tags_text} %{message}'
|
34
51
|
config.parent_transaction_to_message = false
|
52
|
+
config.message_format = :json
|
35
53
|
|
36
54
|
config.modifiers.rails = true
|
37
55
|
config.modifiers.sidekiq = false
|
@@ -42,14 +60,15 @@ end
|
|
42
60
|
```
|
43
61
|
Все настройки являются опциональными.
|
44
62
|
#### Настройки
|
45
|
-
`precision` - точность отметок времени. По умолчанию - `milliseconds`. Может принимать одно из следующих значений: `sec`, `seconds`, `ms`, `millis`, `milliseconds`, `us`, `micros`, `microseconds`, `ns`, `nanos`, `nanoseconds`
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
`
|
63
|
+
- `precision` - точность отметок времени. По умолчанию - `milliseconds`. Может принимать одно из следующих значений: `sec`, `seconds`, `ms`, `millis`, `milliseconds`, `us`, `micros`, `microseconds`, `ns`, `nanos`, `nanoseconds`
|
64
|
+
- `pattern` - текстовый шаблон для формата вывода данных в лог.
|
65
|
+
Доступные ключи: `time`, `pid`, `severity`, `type`, `tags_text`, `message`, `parent_transaction`
|
66
|
+
- `parent_transaction_to_message` - признак необходимости добавлять значение `parent_transaction` в тело логируемого сообщения.
|
67
|
+
Вне зависимости от данной настройки можно использовать ключ `parent_transaction` в шаблоне `pattern`.
|
68
|
+
- `message_format` - формат переменной message в шаблоне pattern. Доступны два формата:
|
69
|
+
- `:json` - `message` логгируется как json строка
|
70
|
+
- `:key_value` - `message` логгируется в формате `key1=value1 key2=value2`
|
71
|
+
- `modifiers` - модификаторы для переопределения формата логирования указанного компонента. См. далее.
|
53
72
|
|
54
73
|
#### Модификаторы
|
55
74
|
Каждый модифкатор может быть активирован двумя равнозначными способами:
|
@@ -61,16 +80,43 @@ config.modifiers.rails = true
|
|
61
80
|
config.modifiers.rails.enable = true
|
62
81
|
```
|
63
82
|
|
64
|
-
|
83
|
+
##### Rails модификатор
|
84
|
+
`config.modifier.rails` - модифицирует форматирование логгера Rails.
|
65
85
|
|
66
|
-
|
86
|
+
##### Active Record модификатор
|
87
|
+
`config.modifier.active_record` - добавляет (именно добавляет, а не модифицирует) нового подписчика на SQL события.
|
88
|
+
SQL начинает дополнительно логгироваться в Loggun формате, severity - info. Например:
|
89
|
+
```text
|
90
|
+
2020-04-12T20:08:52.913+03:00 - 487257 INFO storage.sql.query - {"sql":"SELECT 1","name":null,"duration":0.837}
|
91
|
+
```
|
92
|
+
Пример настроек:
|
93
|
+
```ruby
|
94
|
+
Loggun::Config.configure do |config|
|
95
|
+
#...
|
96
|
+
config.modifiers.active_record.enable = true
|
97
|
+
config.modifiers.active_record.log_subscriber_class_name = 'MyApp::MyLogSubscriber'
|
98
|
+
config.modifiers.active_record.payload_keys = %i[sql duration]
|
99
|
+
#...
|
100
|
+
end
|
101
|
+
```
|
102
|
+
- `log_subscriber_class_name` - имя класса, реализующего логирование sql события.
|
103
|
+
Необходим метод `#sql`. По-умолчанию `::Loggun::Modifiers::ActiveRecord::LoggunLogSubscriber`
|
104
|
+
|
105
|
+
- `payload_keys` - необходимые ключи в полезной нарзуке. Используется в дефолтном классе. Доступные
|
106
|
+
ключи: ```%i[sql name duration source]```.
|
67
107
|
|
68
|
-
|
108
|
+
##### Sidekiq модификатор
|
109
|
+
`config.modifiers.sidekiq` - модифицирует форматирование логгера Sidekiq.
|
69
110
|
|
70
|
-
|
111
|
+
##### Clockwork модификатор
|
112
|
+
`config.modifiers.clockwork` - модифицирует форматирование логгера Clockwork.
|
113
|
+
|
114
|
+
##### Модификатор исходящих HTTP запросово
|
115
|
+
`config.modifiers.outgoing_http` - добавляет логирование исходящих http запросов.
|
71
116
|
На данный момент поддерживаются только запросы посредством гема `HTTP`.
|
72
117
|
|
73
|
-
|
118
|
+
##### Модификатор входящих запросов в Rails
|
119
|
+
`config.modifiers.incoming_http` - добавляет логирование входящих http запросов для контроллеров Rails.
|
74
120
|
Данный модификатор может иметь дополнительные настройки, которые устанавливаются следующим образом
|
75
121
|
(приведены значения по умолчанию):
|
76
122
|
|
@@ -84,14 +130,24 @@ Loggun::Config.configure do |config|
|
|
84
130
|
#...
|
85
131
|
end
|
86
132
|
```
|
133
|
+
- `controllers` - массив имён базовых контроллеров, для которых необходимо добавить указанное логирование.
|
87
134
|
|
88
|
-
`
|
89
|
-
|
90
|
-
`success_condition` - лямбда, определяющая, содержит ли успех ответ экшена. Например `-> { JSON.parse(response.body)['result'] == 'ok' }`
|
135
|
+
- `success_condition` - лямбда, определяющая, содержит ли успех ответ экшена. Например `-> { JSON.parse(response.body)['result'] == 'ok' }`
|
91
136
|
|
92
|
-
`error_info` - лямбда, позволяющая добавить в лог информацию об ошибке, содержащейся в неуспешном ответе экшена.
|
137
|
+
- `error_info` - лямбда, позволяющая добавить в лог информацию об ошибке, содержащейся в неуспешном ответе экшена.
|
93
138
|
Например `-> { JSON.parse(response.body)['error_code'] }`
|
94
139
|
|
140
|
+
**Для Rails 6 и выше данный модификатор может работать некорректно.**
|
141
|
+
В этом случае можно указать в требуемом базовом контроллере строку:
|
142
|
+
```ruby
|
143
|
+
include Loggun::HttpHelpers
|
144
|
+
```
|
145
|
+
Это делает настройки `enable` и `controllers` модификатора безсполезными,
|
146
|
+
однако позволяет гарантированно логировать входящие http запросы.
|
147
|
+
|
148
|
+
Настройки `success_condition` и `error_info` продолжают использоваться и могут быть установлены требуемым образом.
|
149
|
+
|
150
|
+
##### Персональные модификаторы
|
95
151
|
Помимо указанных модификаторов существует возможность добавить собственный.
|
96
152
|
Необходимо уснаследовать его от `Loggun::Modifiers::Base` и указать в методе `apply` все необходимые действия.
|
97
153
|
```ruby
|
@@ -122,24 +178,35 @@ end
|
|
122
178
|
class SomeClass
|
123
179
|
include Loggun::Helpers
|
124
180
|
|
125
|
-
log_options entity_action: :method_name, as_transaction: true
|
126
|
-
|
127
|
-
def some_action
|
128
|
-
log_info 'type_for_action', 'Information'
|
129
|
-
bar
|
130
|
-
end
|
181
|
+
log_options entity_action: :method_name, as_transaction: true, only: %i[download_data]
|
131
182
|
|
132
|
-
def
|
133
|
-
log_info '
|
183
|
+
def download_data
|
184
|
+
log_info 'http_request', 'Information'
|
185
|
+
# ... make http request here
|
186
|
+
log_info 'http_response', success: true
|
134
187
|
end
|
135
188
|
end
|
136
189
|
```
|
137
|
-
|
190
|
+
При вызове `#download_data` мы получим следующий вывод в лог:
|
138
191
|
```
|
139
|
-
2020-03-04T16:58:38.207+05:00 - 28476 INFO
|
140
|
-
2020-03-04T16:58:38.208+05:00 - 28476 INFO
|
192
|
+
2020-03-04T16:58:38.207+05:00 - 28476 INFO http_request.some_class.download_data#ffg5431_1583323118203 - {"message":["Information"]}
|
193
|
+
2020-03-04T16:58:38.208+05:00 - 28476 INFO http_response.some_class.download_data#ffg5431_1583323118203 - {"success": true}
|
141
194
|
```
|
142
195
|
|
196
|
+
**Важно**, что с хелпером log_options необходимо использовать только методы вида `log_<severity>`.
|
197
|
+
Методы модуля `Loggun` не будут работать.
|
198
|
+
|
199
|
+
Список всех опций хелпера log_options:
|
200
|
+
|
201
|
+
- `entity_name` - имя сущности метода, string
|
202
|
+
- `entity_action` - действие сущности метода, string
|
203
|
+
- `as_transaction` - добавлять уникальный ID транзакции для метода, boolean
|
204
|
+
- `transaction_generator` - собственный генератор ID транзакции, lambda
|
205
|
+
- `log_all_methods` - признак необходимости применения хелпера ко всем методам, boolean
|
206
|
+
- `only` - список методов, для которых необходимо применить хелпер (работает только если `log_all_methods` - false), Array{Symbol}
|
207
|
+
- `except` - список методов, которые надо исключить для хелпера, Array{Symbol}
|
208
|
+
- `log_transaction_except` - список методов, логирование которых не нужно обогащать ID транзакции, Array{Symbol}
|
209
|
+
|
143
210
|
## License
|
144
211
|
|
145
212
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/lib/loggun.rb
CHANGED
@@ -5,6 +5,7 @@ require 'loggun/config'
|
|
5
5
|
require 'loggun/modifiers'
|
6
6
|
require 'loggun/modifiers/base'
|
7
7
|
require 'loggun/helpers'
|
8
|
+
require 'logger'
|
8
9
|
|
9
10
|
module Loggun
|
10
11
|
class Error < StandardError; end
|
@@ -12,10 +13,22 @@ module Loggun
|
|
12
13
|
class << self
|
13
14
|
include Loggun::Helpers
|
14
15
|
|
15
|
-
|
16
|
+
attr_writer :logger
|
16
17
|
|
17
18
|
%i[unknown fatal error warn info debug].each do |method|
|
18
19
|
alias_method method, "log_#{method}"
|
19
20
|
end
|
21
|
+
|
22
|
+
def logger
|
23
|
+
@logger ||= default_logger
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def default_logger
|
29
|
+
logger = Logger.new(STDOUT)
|
30
|
+
logger.formatter = Config.instance.formatter
|
31
|
+
logger
|
32
|
+
end
|
20
33
|
end
|
21
34
|
end
|
data/lib/loggun/config.rb
CHANGED
@@ -6,21 +6,28 @@ module Loggun
|
|
6
6
|
include Singleton
|
7
7
|
|
8
8
|
DEFAULTS = {
|
9
|
-
pattern: '%{time} - %{pid} %{severity} %{type} %{tags_text}
|
9
|
+
pattern: '%{time} - %{pid} %{severity} %{type} %{tags_text} %{message}',
|
10
10
|
parent_transaction_to_message: true,
|
11
|
+
message_format: :json,
|
11
12
|
precision: :milliseconds,
|
12
13
|
incoming_http: {
|
13
14
|
controllers: %w[ApplicationController],
|
14
15
|
success_condition: -> { response.code == '200' },
|
15
16
|
error_info: -> { nil }
|
17
|
+
},
|
18
|
+
active_record: {
|
19
|
+
log_subscriber_class_name: '::Loggun::Modifiers::ActiveRecord::LoggunLogSubscriber',
|
20
|
+
payload_keys: %i[sql name duration source]
|
16
21
|
}
|
17
22
|
}.freeze
|
18
|
-
DEFAULT_MODIFIERS = %i[rails sidekiq clockwork
|
23
|
+
DEFAULT_MODIFIERS = %i[rails active_record sidekiq clockwork outgoing_http].freeze
|
24
|
+
MESSAGE_FORMATS = %i[json key_value].freeze
|
19
25
|
|
20
26
|
attr_accessor(
|
21
27
|
:formatter,
|
22
28
|
:pattern,
|
23
29
|
:parent_transaction_to_message,
|
30
|
+
:message_format,
|
24
31
|
:precision,
|
25
32
|
:modifiers,
|
26
33
|
:custom_modifiers
|
@@ -31,6 +38,7 @@ module Loggun
|
|
31
38
|
@precision = DEFAULTS[:precision]
|
32
39
|
@pattern = DEFAULTS[:pattern]
|
33
40
|
@parent_transaction_to_message = DEFAULTS[:parent_transaction_to_message]
|
41
|
+
@message_format = DEFAULTS[:message_format]
|
34
42
|
@modifiers = Loggun::OrderedOptions.new
|
35
43
|
@custom_modifiers = []
|
36
44
|
set_default_modifiers
|
@@ -40,6 +48,7 @@ module Loggun
|
|
40
48
|
def configure(&block)
|
41
49
|
block.call(instance)
|
42
50
|
use_modifiers
|
51
|
+
check_config
|
43
52
|
instance
|
44
53
|
end
|
45
54
|
|
@@ -55,9 +64,15 @@ module Loggun
|
|
55
64
|
instance.custom_modifiers.each(&:use)
|
56
65
|
end
|
57
66
|
|
58
|
-
def
|
59
|
-
|
60
|
-
|
67
|
+
def check_config
|
68
|
+
return if MESSAGE_FORMATS.include? instance.message_format
|
69
|
+
|
70
|
+
raise FailureConfiguration, 'Unknown value for message_format'
|
71
|
+
end
|
72
|
+
|
73
|
+
def setup_formatter(app, formatter = nil)
|
74
|
+
Loggun.logger = app.logger
|
75
|
+
Loggun.logger.formatter = formatter || instance.formatter
|
61
76
|
end
|
62
77
|
end
|
63
78
|
|
@@ -87,5 +102,7 @@ module Loggun
|
|
87
102
|
3 # milliseconds
|
88
103
|
end
|
89
104
|
end
|
105
|
+
|
106
|
+
class FailureConfiguration < StandardError; end
|
90
107
|
end
|
91
108
|
end
|
data/lib/loggun/formatter.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
require '
|
1
|
+
require 'time'
|
2
|
+
require 'json'
|
2
3
|
|
3
4
|
module Loggun
|
4
5
|
class Formatter
|
5
6
|
DEFAULT_VALUE = '-'.freeze
|
6
7
|
|
7
|
-
def call(severity, time, _program_name, message)
|
8
|
+
def call(severity, time, _program_name, message, loggun_type: nil)
|
8
9
|
data = Hash.new(DEFAULT_VALUE)
|
9
10
|
data[:time] = time.iso8601(config.timestamp_precision)
|
10
11
|
data[:pid] = Process.pid
|
@@ -13,17 +14,18 @@ module Loggun
|
|
13
14
|
if config.parent_transaction_to_message && parent_transaction
|
14
15
|
message[:parent_transaction] = parent_transaction
|
15
16
|
end
|
16
|
-
message =
|
17
|
+
message = format_message(message)
|
17
18
|
end
|
18
19
|
|
19
20
|
data[:message] = message.to_s.tr("\r\n", ' ').strip
|
20
|
-
data[:severity] = severity&.
|
21
|
+
data[:severity] = severity&.to_s || 'INFO'
|
21
22
|
data[:tags_text] = tags_text
|
22
|
-
data[:type] = Loggun.type || DEFAULT_VALUE.dup
|
23
|
+
data[:type] = loggun_type || Loggun.type || DEFAULT_VALUE.dup
|
23
24
|
data[:transaction_id] = Loggun.transaction_id
|
24
25
|
data[:parent_transaction] = parent_transaction if parent_transaction
|
25
26
|
|
26
|
-
if data[:transaction_id]
|
27
|
+
if data[:transaction_id] && data[:type] != DEFAULT_VALUE &&
|
28
|
+
data[:transaction_id].to_i != Process.pid
|
27
29
|
data[:type] = "#{data[:type]}##{data[:transaction_id]}"
|
28
30
|
end
|
29
31
|
|
@@ -76,5 +78,16 @@ module Loggun
|
|
76
78
|
def config
|
77
79
|
Loggun::Config.instance
|
78
80
|
end
|
81
|
+
|
82
|
+
def format_message(message)
|
83
|
+
if config.message_format == :json
|
84
|
+
JSON.generate(message)
|
85
|
+
elsif config.message_format == :key_value
|
86
|
+
message.map { |key, value| "#{key}=#{value}" }.join(' ')
|
87
|
+
else
|
88
|
+
warn('Unknown value for message_format')
|
89
|
+
JSON.generate(message)
|
90
|
+
end
|
91
|
+
end
|
79
92
|
end
|
80
93
|
end
|
data/lib/loggun/helpers.rb
CHANGED
@@ -3,53 +3,65 @@ require 'securerandom'
|
|
3
3
|
module Loggun
|
4
4
|
module Helpers
|
5
5
|
SKIPPED_METHODS = %i[
|
6
|
-
initialize loggun logger
|
6
|
+
initialize loggun logger log_modified_methods loggun_init in_log_transaction with_log_type
|
7
7
|
].freeze
|
8
8
|
DEFAULT_TYPE = 'class'.freeze
|
9
9
|
|
10
10
|
def self.included(klass)
|
11
|
+
klass.extend(InitMethods)
|
12
|
+
klass.loggun_init
|
11
13
|
klass.extend(ClassMethods)
|
12
|
-
klass.init
|
13
14
|
end
|
14
15
|
|
15
|
-
module
|
16
|
+
module InitMethods
|
16
17
|
attr_accessor(
|
17
18
|
:with_log_transaction_id,
|
18
19
|
:log_transaction_generator,
|
19
20
|
:log_entity_name,
|
20
21
|
:log_entity_action,
|
21
|
-
:
|
22
|
-
:
|
22
|
+
:log_modified_methods,
|
23
|
+
:log_skip_methods,
|
24
|
+
:log_only_methods,
|
25
|
+
:log_all_methods,
|
26
|
+
:log_transaction_except
|
23
27
|
)
|
24
28
|
|
29
|
+
def loggun_init
|
30
|
+
@log_modified_methods = []
|
31
|
+
@log_all_methods = false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module ClassMethods
|
25
36
|
def log_options(**options)
|
26
37
|
@log_entity_name = options[:entity_name]
|
27
38
|
@log_entity_action = options[:entity_action]
|
28
39
|
@with_log_transaction_id = options[:as_transaction]
|
29
40
|
@log_transaction_generator = options[:transaction_generator]
|
30
|
-
@
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
@modified_methods = []
|
41
|
+
@log_transaction_except = options[:log_transaction_except]&.map(&:to_sym)
|
42
|
+
@log_skip_methods = options[:except]&.map(&:to_sym)
|
43
|
+
@log_only_methods = options[:only]&.map(&:to_sym)
|
44
|
+
@log_all_methods = options[:log_all_methods]
|
35
45
|
end
|
36
46
|
|
37
47
|
def method_added(method_name)
|
38
48
|
super
|
39
|
-
@
|
40
|
-
return if SKIPPED_METHODS.include?(method_name) ||
|
41
|
-
modified_methods.include?(method_name)
|
49
|
+
@log_modified_methods ||= []
|
42
50
|
|
43
|
-
|
51
|
+
return if !log_all_methods && !log_only_methods&.include?(method_name)
|
52
|
+
return if log_skip_methods&.include?(method_name)
|
53
|
+
return if SKIPPED_METHODS.include?(method_name) || log_modified_methods.include?(method_name)
|
54
|
+
|
55
|
+
log_modified_methods << method_name
|
44
56
|
method = instance_method(method_name)
|
45
57
|
undef_method(method_name)
|
46
58
|
|
47
59
|
define_method(method_name) do |*args, &block|
|
48
|
-
if self.class.
|
60
|
+
if self.class.log_transaction_except&.include?(method_name.to_sym)
|
49
61
|
method.bind(self).call(*args, &block)
|
50
62
|
else
|
51
63
|
type = log_type(nil, method_name)
|
52
|
-
|
64
|
+
in_log_transaction(type) do
|
53
65
|
method.bind(self).call(*args, &block)
|
54
66
|
end
|
55
67
|
end
|
@@ -57,19 +69,15 @@ module Loggun
|
|
57
69
|
end
|
58
70
|
end
|
59
71
|
|
60
|
-
%i[unknown fatal error warn info debug].each do |
|
61
|
-
define_method("log_#{
|
72
|
+
%i[unknown fatal error warn info debug].each do |method_name|
|
73
|
+
define_method("log_#{method_name}") do |*args, **attrs, &block|
|
62
74
|
type = args.shift
|
63
|
-
next
|
64
|
-
attrs.empty?
|
65
|
-
|
66
|
-
method_name = caller_locations.first.label.split(' ').last
|
67
|
-
type = log_type(type, method_name)
|
75
|
+
next logger.send(method_name, type, &block) if args.empty? && attrs.empty?
|
68
76
|
|
69
|
-
|
70
|
-
|
71
|
-
next unless methods.include?(:message) && methods.include?(:backtrace)
|
77
|
+
caller_method_name = caller_locations.first.label.split(' ').last
|
78
|
+
type = log_type(type, caller_method_name)
|
72
79
|
|
80
|
+
if %i[fatal error].include?(method_name) && %i[backtrace message].all? { |m| args.first.respond_to?(m) }
|
73
81
|
error = args.shift
|
74
82
|
attrs[:error] = { class: error.class, msg: error.message }
|
75
83
|
if attrs[:hidden]
|
@@ -78,10 +86,10 @@ module Loggun
|
|
78
86
|
attrs[:hidden] = { error: { backtrace: error.backtrace } }
|
79
87
|
end
|
80
88
|
end
|
81
|
-
attrs[:
|
89
|
+
attrs[:message] = args unless args.empty?
|
82
90
|
|
83
|
-
|
84
|
-
|
91
|
+
with_log_type(type) do
|
92
|
+
logger.send(method_name, **attrs, &block)
|
85
93
|
end
|
86
94
|
end
|
87
95
|
end
|
@@ -98,7 +106,7 @@ module Loggun
|
|
98
106
|
end
|
99
107
|
end
|
100
108
|
|
101
|
-
def
|
109
|
+
def in_log_transaction(current_type = nil, current_transaction_id = nil)
|
102
110
|
current_transaction_id ||= generate_log_transaction_id
|
103
111
|
previous_transaction_id = self.parent_transaction_id
|
104
112
|
previous_type = self.parent_type
|
@@ -117,7 +125,7 @@ module Loggun
|
|
117
125
|
self.parent_type = previous_type
|
118
126
|
end
|
119
127
|
|
120
|
-
def
|
128
|
+
def with_log_type(current_type)
|
121
129
|
previous_type = self.type
|
122
130
|
self.type = current_type
|
123
131
|
yield
|
@@ -126,22 +134,30 @@ module Loggun
|
|
126
134
|
end
|
127
135
|
|
128
136
|
def log_type(type, method_name)
|
137
|
+
klass = self.class
|
129
138
|
type ||= DEFAULT_TYPE.dup
|
130
139
|
type_as_arr = type.split('.')
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
140
|
+
|
141
|
+
if type_as_arr.size == 1
|
142
|
+
log_entity_name = klass.respond_to?(:log_entity_name) ? klass.log_entity_name : underscore(klass.name.dup)
|
143
|
+
type_as_arr << log_entity_name
|
144
|
+
end
|
135
145
|
|
136
146
|
return type unless klass.respond_to?(:log_entity_action)
|
137
147
|
|
138
|
-
if klass.log_entity_action && type_as_arr.size < 3
|
139
|
-
|
140
|
-
type << ".#{method_name}"
|
141
|
-
end
|
148
|
+
if klass.log_entity_action && klass.log_entity_action == :method_name && type_as_arr.size < 3 && method_name
|
149
|
+
type_as_arr << method_name
|
142
150
|
end
|
143
151
|
|
144
|
-
|
152
|
+
type_as_arr.join('.')
|
153
|
+
end
|
154
|
+
|
155
|
+
def generate_log_transaction_id
|
156
|
+
if self.class.log_transaction_generator
|
157
|
+
return self.class.log_transaction_generator.call(self)
|
158
|
+
end
|
159
|
+
|
160
|
+
"#{SecureRandom.uuid[0..7]}_#{DateTime.now.strftime('%Q')}"
|
145
161
|
end
|
146
162
|
|
147
163
|
private
|
@@ -162,17 +178,8 @@ module Loggun
|
|
162
178
|
word
|
163
179
|
end
|
164
180
|
|
165
|
-
def
|
166
|
-
|
167
|
-
if self.class.log_transaction_generator
|
168
|
-
return self.class.log_transaction_generator.call
|
169
|
-
end
|
170
|
-
|
171
|
-
"#{SecureRandom.uuid[0..7]}_#{DateTime.now.strftime('%Q')}"
|
172
|
-
end
|
173
|
-
|
174
|
-
def application
|
175
|
-
Loggun.application
|
181
|
+
def logger
|
182
|
+
Loggun.logger
|
176
183
|
end
|
177
184
|
end
|
178
185
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Loggun
|
2
|
+
module Modifiers
|
3
|
+
class ActiveRecord < Loggun::Modifiers::Base
|
4
|
+
def apply
|
5
|
+
return unless defined?(::ActiveRecord) && defined?(::ActiveRecord::LogSubscriber)
|
6
|
+
|
7
|
+
subscriber_class_name = config.modifiers.active_record.log_subscriber_class_name
|
8
|
+
if subscriber_class_name == ::Loggun::Config::DEFAULTS[:active_record][:log_subscriber_class_name]
|
9
|
+
require 'loggun/modifiers/active_record/loggun_log_subscriber'
|
10
|
+
end
|
11
|
+
klass = Object.const_get(subscriber_class_name)
|
12
|
+
|
13
|
+
return klass.attach_to :active_record if klass.respond_to?(:attach_to)
|
14
|
+
|
15
|
+
Loggun.warn(
|
16
|
+
"Loggun: passed active_record.log_subscriber_class_name `#{subscriber_class_name}`" \
|
17
|
+
"must respond to #attached_to method"
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Loggun
|
2
|
+
module Modifiers
|
3
|
+
class ActiveRecord
|
4
|
+
class LoggunLogSubscriber < ::ActiveRecord::LogSubscriber
|
5
|
+
def sql(event)
|
6
|
+
payload = event.payload
|
7
|
+
return if IGNORE_PAYLOAD_NAMES.include?(payload[:name]) || payload[:cached]
|
8
|
+
|
9
|
+
available_keys = ::Loggun::Config.instance.modifiers.active_record.payload_keys&.map { |k| k.downcase.to_sym }
|
10
|
+
data = { sql: payload[:sql], name: payload[:name], duration: event.duration.round(4) }
|
11
|
+
source = respond_to?(:extract_query_source_location) ? extract_query_source_location(caller) : nil
|
12
|
+
data.merge!(source: source.gsub(/(?<=\.rb)(.*)$/, '')) if source
|
13
|
+
if available_keys&.any?
|
14
|
+
data.each { |k, _| data.delete(k) unless available_keys.include?(k) }
|
15
|
+
end
|
16
|
+
|
17
|
+
Loggun.info 'storage.sql.query', data
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -3,11 +3,21 @@ require 'sidekiq' if defined?(::Sidekiq)
|
|
3
3
|
module Loggun
|
4
4
|
module Modifiers
|
5
5
|
class Sidekiq < Loggun::Modifiers::Base
|
6
|
+
MIN_SIDEKIQ_V = '4.0.0'.freeze
|
7
|
+
|
6
8
|
def apply
|
7
|
-
return unless defined?(::Sidekiq)
|
9
|
+
return unless defined?(::Sidekiq) && ::Sidekiq::VERSION >= MIN_SIDEKIQ_V
|
8
10
|
|
9
11
|
::Sidekiq.configure_server do |config|
|
10
|
-
Loggun::Config.setup_formatter(config)
|
12
|
+
Loggun::Config.setup_formatter(config, LoggunFormatter.new)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
if defined?(::Sidekiq)
|
17
|
+
if ::Sidekiq::VERSION >= '6.0.0'
|
18
|
+
require 'loggun/modifiers/sidekiq/sidekiq6'
|
19
|
+
else
|
20
|
+
require 'loggun/modifiers/sidekiq/sidekiq4'
|
11
21
|
end
|
12
22
|
end
|
13
23
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Loggun
|
2
|
+
module Modifiers
|
3
|
+
class Sidekiq
|
4
|
+
class LoggunFormatter < ::Sidekiq::Logging::Pretty
|
5
|
+
def call(severity, time, _program_name, message)
|
6
|
+
message, loggun_type = prepared_message(message)
|
7
|
+
Loggun::Formatter.new.call(severity, time.utc, nil, message, loggun_type: loggun_type)
|
8
|
+
end
|
9
|
+
|
10
|
+
def prepared_message(message)
|
11
|
+
if %w[start].include?(message) || message[/^(done|fail):\s(.*)\ssec$/]
|
12
|
+
message, elapsed = split_msg_and_time(message)
|
13
|
+
loggun_type = "sidekiq.job.#{message}"
|
14
|
+
message = { tid: "#{Thread.current.object_id.to_s(36)}", context: context.strip }
|
15
|
+
message[:elapsed] = elapsed if elapsed
|
16
|
+
else
|
17
|
+
loggun_type = 'app.sidekiq.control'
|
18
|
+
message = { tid: Thread.current.object_id.to_s(36), message: message }
|
19
|
+
message.merge!(context: context) if context
|
20
|
+
end
|
21
|
+
|
22
|
+
[message, loggun_type]
|
23
|
+
end
|
24
|
+
|
25
|
+
def split_msg_and_time(message)
|
26
|
+
unless message[/^done:\s(.*)\ssec$/] || message[/^fail:\s(.*)\ssec$/]
|
27
|
+
return [message, nil]
|
28
|
+
end
|
29
|
+
|
30
|
+
msg_type = message[/^done:\s(.*)\ssec$/] ? 'done' : 'fail'
|
31
|
+
|
32
|
+
msg = message[/#{msg_type}:\s(.*)\ssec/] ? msg_type : message
|
33
|
+
elapsed = message.gsub(/#{msg_type}:\s/, '').gsub('sec', '').strip
|
34
|
+
[msg, elapsed]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Loggun
|
2
|
+
module Modifiers
|
3
|
+
class Sidekiq
|
4
|
+
class LoggunFormatter < ::Sidekiq::Logger::Formatters::Base
|
5
|
+
def call(severity, time, _program_name, message)
|
6
|
+
message, loggun_type = prepared_message(message)
|
7
|
+
Loggun::Formatter.new.call(severity, time.utc, nil, message, loggun_type: loggun_type)
|
8
|
+
end
|
9
|
+
|
10
|
+
def prepared_message(message)
|
11
|
+
if %w[start done fail].include?(message)
|
12
|
+
loggun_type = "sidekiq.job.#{message}"
|
13
|
+
message = "#{::Sidekiq.dump_json(ctx)}"
|
14
|
+
else
|
15
|
+
loggun_type = 'app.sidekiq.control'
|
16
|
+
message = { tid: tid, message: message }
|
17
|
+
message.merge!(context: format_context) if format_context
|
18
|
+
end
|
19
|
+
|
20
|
+
[message, loggun_type]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/loggun/version.rb
CHANGED
data/loggun.gemspec
CHANGED
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.add_development_dependency 'clockwork', '~> 2.0'
|
33
33
|
spec.add_development_dependency 'http', '~> 4.0'
|
34
34
|
spec.add_development_dependency 'rails', '~> 6.0'
|
35
|
-
spec.add_development_dependency 'rake', '~>
|
35
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
36
36
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
37
37
|
spec.add_development_dependency 'rspec-rails', '~> 3.0'
|
38
38
|
spec.add_development_dependency 'sidekiq', '~> 6.0'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: loggun
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aleksandr Noskov
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-
|
12
|
+
date: 2020-06-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -73,14 +73,14 @@ dependencies:
|
|
73
73
|
requirements:
|
74
74
|
- - "~>"
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: '
|
76
|
+
version: '13.0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
81
|
- - "~>"
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
version: '
|
83
|
+
version: '13.0'
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
85
|
name: rspec
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
@@ -145,17 +145,19 @@ files:
|
|
145
145
|
- lib/loggun/formatter.rb
|
146
146
|
- lib/loggun/helpers.rb
|
147
147
|
- lib/loggun/modifiers.rb
|
148
|
+
- lib/loggun/modifiers/active_record.rb
|
149
|
+
- lib/loggun/modifiers/active_record/loggun_log_subscriber.rb
|
148
150
|
- lib/loggun/modifiers/base.rb
|
149
151
|
- lib/loggun/modifiers/clockwork.rb
|
150
152
|
- lib/loggun/modifiers/clockwork/manager.rb
|
151
153
|
- lib/loggun/modifiers/clockwork/methods.rb
|
152
|
-
- lib/loggun/modifiers/incoming_http.rb
|
153
|
-
- lib/loggun/modifiers/incoming_http/log_http_actions.rb
|
154
154
|
- lib/loggun/modifiers/outgoing_http.rb
|
155
155
|
- lib/loggun/modifiers/outgoing_http/block_logger.rb
|
156
156
|
- lib/loggun/modifiers/rails.rb
|
157
157
|
- lib/loggun/modifiers/rails/railtie.rb
|
158
158
|
- lib/loggun/modifiers/sidekiq.rb
|
159
|
+
- lib/loggun/modifiers/sidekiq/sidekiq4.rb
|
160
|
+
- lib/loggun/modifiers/sidekiq/sidekiq6.rb
|
159
161
|
- lib/loggun/ordered_options.rb
|
160
162
|
- lib/loggun/version.rb
|
161
163
|
- loggun.gemspec
|
@@ -1,19 +0,0 @@
|
|
1
|
-
require_relative 'incoming_http/log_http_actions'
|
2
|
-
|
3
|
-
module Loggun
|
4
|
-
module Modifiers
|
5
|
-
class IncomingHttp < Loggun::Modifiers::Base
|
6
|
-
def apply
|
7
|
-
return unless defined?(ActionPack)
|
8
|
-
|
9
|
-
controllers = Loggun::Config.instance.modifiers.incoming_http.controllers
|
10
|
-
controllers.each do |controller|
|
11
|
-
controller.constantize.class_eval do
|
12
|
-
include LogHttpActions
|
13
|
-
around_action :log_http_actions
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
module LogHttpActions
|
2
|
-
|
3
|
-
private
|
4
|
-
|
5
|
-
def log_http_actions
|
6
|
-
log_action :start
|
7
|
-
yield
|
8
|
-
log_action :response
|
9
|
-
end
|
10
|
-
|
11
|
-
def log_action(action = :start)
|
12
|
-
api = request.path[/\w+/]
|
13
|
-
api_version = request.path[/v./]
|
14
|
-
type = "http_request.#{api}.#{action}"
|
15
|
-
data = { path: clean_pathname, api_version: api_version }
|
16
|
-
return Loggun.info type, data if action == :start
|
17
|
-
|
18
|
-
success = instance_exec(&modifier_config.success_condition)
|
19
|
-
data[:success] = success
|
20
|
-
unless success
|
21
|
-
error = instance_exec(&modifier_config.error_info)
|
22
|
-
data[:error] = error if error
|
23
|
-
end
|
24
|
-
Loggun.info type, data
|
25
|
-
end
|
26
|
-
|
27
|
-
def clean_pathname
|
28
|
-
filtered_params = params.to_unsafe_h
|
29
|
-
filtered_params.delete('action')
|
30
|
-
request.path.gsub(/(#{filtered_params.values.join('|')})/, '').gsub(/\/api\/v./, '')
|
31
|
-
end
|
32
|
-
|
33
|
-
def modifier_config
|
34
|
-
Loggun::Config.instance.modifiers.incoming_http
|
35
|
-
end
|
36
|
-
end
|