loggun 0.1.1 → 0.4.1
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/.travis.yml +0 -2
- data/CHANGELOG.md +36 -0
- data/README.md +189 -51
- data/lib/loggun.rb +0 -1
- data/lib/loggun/config.rb +21 -4
- data/lib/loggun/formatter.rb +14 -3
- data/lib/loggun/helpers.rb +58 -49
- 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
- metadata +10 -7
- data/lib/loggun/http_helpers.rb +0 -48
- data/lib/loggun/modifiers/incoming_http.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cfd41231567df2c15cca3c6ba500fc8228dcf03ac808b2adb452385be59d4217
|
4
|
+
data.tar.gz: 86c26424200b7c443a4160770d7b3f0d22490db5e0ac3c41fffdd2dadd795d9e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '058933cfb04111fe6f0f106e97efde068932b575bfc2be6bdfee0f419db586b07e0a11025eba01b65d12f71a9ef8121dc88e4c53dc39037cd95d5ee6d1ccd90b'
|
7
|
+
data.tar.gz: ebd06ae4867bb4b8cc03fa0ef1815ca73f58af294fab484f3f1207c01d3b4c305cfaa442a6b82771524a909fdb88cb68a8421c760ba8099731957a158c910858
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## 0.4.1 - 2020-07-28
|
4
|
+
* fixes
|
5
|
+
* fill type with class name for empty `log_entity_name`
|
6
|
+
|
7
|
+
## 0.4.0 - 2020-06-02
|
8
|
+
* fixes
|
9
|
+
* fix key_value join character to space
|
10
|
+
* fix dummy dependency alerts
|
11
|
+
* features
|
12
|
+
* add new const MESSAGE_FORMATS and test for checking the value of message_format
|
13
|
+
* add check message_format
|
14
|
+
* boolean flag replace with a whitelist and create method for generating a message
|
15
|
+
* added ability to log messages format k=v
|
16
|
+
|
17
|
+
## 0.3.1 - 2020-04-21
|
18
|
+
* fixes
|
19
|
+
* fix error "modify frozen String" for class name in helpers
|
20
|
+
|
21
|
+
## 0.3.0 - 2020-04-17
|
22
|
+
* fixes
|
23
|
+
* make public #generate_log_transaction_id in helper
|
24
|
+
* removed incoming http modifier
|
25
|
+
|
26
|
+
## 0.2.0 - 2020-04-13
|
27
|
+
* fixes
|
28
|
+
* fix Readme with active_record modifier
|
29
|
+
* fix except option for helper #log_options
|
30
|
+
* refactor helpers #log_type
|
31
|
+
* fix helper define log_methods caller
|
32
|
+
* improve stability of helpers
|
33
|
+
* features
|
34
|
+
* remove legacy agent from default log pattern
|
35
|
+
* new active record modifier
|
36
|
+
* improve sidekiq modifier for difference versions
|
data/README.md
CHANGED
@@ -1,37 +1,70 @@
|
|
1
1
|
# Loggun
|
2
2
|
|
3
|
-
[](https://funbox.ru)
|
4
|
-
|
5
3
|
[](https://badge.fury.io/rb/loggun)
|
6
4
|
[](https://travis-ci.org/funbox/loggun)
|
7
5
|
|
8
|
-
|
9
|
-
|
6
|
+
Приводит логи приложения к единому формату.
|
7
|
+
|
8
|
+
## Содержание
|
9
|
+
|
10
|
+
- [Установка](#установка)
|
11
|
+
- [Использование](#использование)
|
12
|
+
- [Конфигурация](#конфигурация)
|
13
|
+
- [Настройки](#настройки)
|
14
|
+
- [Модификаторы](#модификаторы)
|
15
|
+
- [Rails модификатор](#rails-модификатор)
|
16
|
+
- [Active Record модификатор](#active-record-модификатор)
|
17
|
+
- [Sidekiq модификатор](#sidekiq-модификатор)
|
18
|
+
- [Clockwork модификатор](#clockwork-модификатор)
|
19
|
+
- [Модификатор исходящих HTTP-запросов](#модификатор-исходящих-http-запросов)
|
20
|
+
- [Модификатор входящих запросов в Rails](#модификатор-входящих-запросов-в-rails)
|
21
|
+
- [Пользовательские модификаторы](#пользовательские-модификаторы)
|
22
|
+
- [Хелперы](#хелперы)
|
10
23
|
|
11
24
|
## Установка
|
12
25
|
|
13
|
-
Чтобы установить гем, добавьте в
|
26
|
+
Чтобы установить гем, добавьте его в Gemfile:
|
14
27
|
|
15
28
|
```ruby
|
16
29
|
gem 'loggun'
|
17
30
|
```
|
18
31
|
|
19
|
-
И выполните
|
32
|
+
И выполните команду:
|
20
33
|
|
21
|
-
|
34
|
+
```bash
|
35
|
+
$ bundle
|
36
|
+
```
|
22
37
|
|
23
38
|
## Использование
|
24
39
|
|
25
|
-
|
26
|
-
|
40
|
+
Loggun можно использовать как обертку для вашего `logger`. Для этого необходимо передать
|
41
|
+
ему инстанс логгера и настроить его `formatter`:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
Loggun.logger = Rails.logger
|
45
|
+
Loggun.logger.formatter = Loggun::Formatter.new
|
46
|
+
```
|
47
|
+
|
48
|
+
Теперь можно использовать Loggun для логирования в стандартизированном формате:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
Loggun.info('http_request.api.request', user_id: current_user.id)
|
52
|
+
#=> 2020-04-11T22:35:04.225+03:00 - 170715 INFO http_request.api.request - {"user_id": 5465}
|
53
|
+
...
|
54
|
+
Loggun.info('http_request.api.response', user_id: current_user.id, success: true)
|
55
|
+
#=> 2020-04-11T22:35:04.225+03:00 - 170715 INFO http_request.api.response - {"user_id": 5465, "success": true}
|
56
|
+
```
|
57
|
+
|
58
|
+
## Конфигурация
|
27
59
|
|
28
|
-
|
60
|
+
Конфигурацию гема необходимо производить при инициализации приложения. Например, так:
|
29
61
|
|
30
62
|
```ruby
|
31
63
|
Loggun::Config.configure do |config|
|
32
64
|
config.precision = :milliseconds
|
33
65
|
config.pattern = '%{time} - %{pid} %{severity} %{type} %{tags_text} %{message}'
|
34
66
|
config.parent_transaction_to_message = false
|
67
|
+
config.message_format = :json
|
35
68
|
|
36
69
|
config.modifiers.rails = true
|
37
70
|
config.modifiers.sidekiq = false
|
@@ -40,39 +73,130 @@ Loggun::Config.configure do |config|
|
|
40
73
|
config.modifiers.outgoing_http = false
|
41
74
|
end
|
42
75
|
```
|
43
|
-
Все настройки являются опциональными.
|
44
|
-
#### Настройки
|
45
|
-
`precision` - точность отметок времени. По умолчанию - `milliseconds`. Может принимать одно из следующих значений: `sec`, `seconds`, `ms`, `millis`, `milliseconds`, `us`, `micros`, `microseconds`, `ns`, `nanos`, `nanoseconds`
|
46
76
|
|
47
|
-
|
77
|
+
### Настройки
|
78
|
+
|
79
|
+
Все настройки опциональны.
|
80
|
+
|
81
|
+
- `precision` — точность отметок времени.
|
82
|
+
|
83
|
+
Может принимать одно из следующих значений:
|
84
|
+
`sec`, `seconds`, `ms`, `millis`, `milliseconds`, `us`, `micros`, `microseconds`, `ns`, `nanos`, `nanoseconds`.
|
85
|
+
|
86
|
+
По умолчанию `milliseconds`.
|
87
|
+
|
88
|
+
- `pattern` — текстовый шаблон для формата вывода данных в лог.
|
89
|
+
|
90
|
+
Доступные ключи внутри шаблона: `time`, `pid`, `severity`, `type`, `tags_text`, `message`, `parent_transaction`.
|
91
|
+
|
92
|
+
- `parent_transaction_to_message` — если `true`, то значение `parent_transaction` будет добавлено в тело логируемого сообщения.
|
93
|
+
|
94
|
+
Ключ `parent_transaction` в шаблоне `pattern` можно использовать вне зависимости от значения этой настройки.
|
95
|
+
|
96
|
+
- `message_format` — формат переменной `message` в шаблоне `pattern`.
|
48
97
|
|
49
|
-
|
50
|
-
|
98
|
+
Доступные значения:
|
99
|
+
|
100
|
+
- `:json` — `message` логируется как JSON-строка;
|
101
|
+
- `:key_value` — `message` логируется в формате `key1=value1 key2=value2`.
|
102
|
+
|
103
|
+
- `modifiers` — модификаторы для переопределения формата логирования указанного компонента. См. «[Модификаторы](#модификаторы)».
|
51
104
|
|
52
|
-
|
105
|
+
### Модификаторы
|
53
106
|
|
54
|
-
#### Модификаторы
|
55
107
|
Каждый модифкатор может быть активирован двумя равнозначными способами:
|
108
|
+
|
56
109
|
```ruby
|
57
110
|
config.modifiers.rails = true
|
58
111
|
```
|
112
|
+
|
59
113
|
или
|
114
|
+
|
60
115
|
```ruby
|
61
116
|
config.modifiers.rails.enable = true
|
62
117
|
```
|
63
118
|
|
64
|
-
|
119
|
+
(В качестве примера активируется Rails модификатор, но может быть любой другой.)
|
120
|
+
|
121
|
+
#### Rails модификатор
|
122
|
+
|
123
|
+
`config.modifier.rails`
|
124
|
+
|
125
|
+
Модифицирует форматирование логгера Rails.
|
126
|
+
|
127
|
+
#### Active Record модификатор
|
128
|
+
|
129
|
+
`config.modifier.active_record`
|
130
|
+
|
131
|
+
Добавляет (именно добавляет, а не модифицирует) нового подписчика на SQL-события.
|
132
|
+
|
133
|
+
SQL начинает дополнительно логироваться в Loggun формате, `severity` — `info`. Например:
|
134
|
+
|
135
|
+
```text
|
136
|
+
2020-04-12T20:08:52.913+03:00 - 487257 INFO storage.sql.query - {"sql":"SELECT 1","name":null,"duration":0.837}
|
137
|
+
```
|
138
|
+
|
139
|
+
Дополнительные настройки:
|
140
|
+
|
141
|
+
- `log_subscriber_class_name` — имя класса, реализующего логирование SQL-события.
|
142
|
+
|
143
|
+
Необходим метод `#sql`. По умолчанию: `::Loggun::Modifiers::ActiveRecord::LoggunLogSubscriber`.
|
144
|
+
|
145
|
+
- `payload_keys` — необходимые ключи в полезной нарзуке. Используется в классе по умолчанию.
|
146
|
+
|
147
|
+
Доступные ключи: `%i[sql name duration source]`.
|
148
|
+
|
149
|
+
Пример:
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
Loggun::Config.configure do |config|
|
153
|
+
#...
|
154
|
+
config.modifiers.active_record.enable = true
|
155
|
+
config.modifiers.active_record.log_subscriber_class_name = 'MyApp::MyLogSubscriber'
|
156
|
+
config.modifiers.active_record.payload_keys = %i[sql duration]
|
157
|
+
#...
|
158
|
+
end
|
159
|
+
```
|
160
|
+
|
161
|
+
#### Sidekiq модификатор
|
162
|
+
|
163
|
+
`config.modifiers.sidekiq`
|
164
|
+
|
165
|
+
Модифицирует форматирование логгера Sidekiq.
|
166
|
+
|
167
|
+
#### Clockwork модификатор
|
168
|
+
|
169
|
+
`config.modifiers.clockwork`
|
170
|
+
|
171
|
+
Модифицирует форматирование логгера Clockwork.
|
172
|
+
|
173
|
+
#### Модификатор исходящих HTTP-запросов
|
174
|
+
|
175
|
+
`config.modifiers.outgoing_http`
|
176
|
+
|
177
|
+
Добавляет логирование исходящих HTTP-запросов.
|
178
|
+
На данный момент поддерживаются только запросы, выполненные с помощью гема `HTTP`.
|
179
|
+
|
180
|
+
#### Модификатор входящих запросов в Rails
|
181
|
+
|
182
|
+
`config.modifiers.incoming_http`
|
183
|
+
|
184
|
+
Добавляет логирование входящих HTTP-запросов для контроллеров Rails.
|
185
|
+
|
186
|
+
Может иметь дополнительные настройки:
|
65
187
|
|
66
|
-
`
|
188
|
+
- `controllers` — массив имён базовых контроллеров, для которых необходимо добавить указанное логирование.
|
67
189
|
|
68
|
-
`
|
190
|
+
- `success_condition` — лямбда, определяющая, содержит ли успех ответ экшена.
|
69
191
|
|
70
|
-
|
71
|
-
На данный момент поддерживаются только запросы посредством гема `HTTP`.
|
192
|
+
Например: `-> { JSON.parse(response.body)['result'] == 'ok' }`
|
72
193
|
|
73
|
-
`
|
74
|
-
|
75
|
-
|
194
|
+
- `error_info` — лямбда, позволяющая добавить в лог информацию об ошибке, содержащейся в неуспешном ответе экшена.
|
195
|
+
|
196
|
+
Например: `-> { JSON.parse(response.body)['error_code'] }`
|
197
|
+
|
198
|
+
|
199
|
+
Пример (приведены значения по умолчанию):
|
76
200
|
|
77
201
|
```ruby
|
78
202
|
Loggun::Config.configure do |config|
|
@@ -85,25 +209,24 @@ Loggun::Config.configure do |config|
|
|
85
209
|
end
|
86
210
|
```
|
87
211
|
|
88
|
-
|
212
|
+
**Для Rails 6 и выше данный модификатор может работать некорректно.**
|
89
213
|
|
90
|
-
|
214
|
+
В этом случае можно добавить в требуемый базовый контроллер строку:
|
91
215
|
|
92
|
-
`error_info` - лямбда, позволяющая добавить в лог информацию об ошибке, содержащейся в неуспешном ответе экшена.
|
93
|
-
Например `-> { JSON.parse(response.body)['error_code'] }`
|
94
|
-
|
95
|
-
Для Rails 6 и выше данный модификатор может работать некорректно.
|
96
|
-
В этом случае можно указать в требуемом базовом контроллере строку:
|
97
216
|
```ruby
|
98
217
|
include Loggun::HttpHelpers
|
99
218
|
```
|
219
|
+
|
100
220
|
Это делает настройки `enable` и `controllers` модификатора безсполезными,
|
101
|
-
однако позволяет гарантированно логировать входящие
|
221
|
+
однако позволяет гарантированно логировать входящие HTTP-запросы.
|
102
222
|
|
103
|
-
Настройки `success_condition` и `error_info` продолжают использоваться и
|
223
|
+
Настройки `success_condition` и `error_info` продолжают использоваться и могут быть установлены требуемым образом.
|
224
|
+
|
225
|
+
#### Пользовательские модификаторы
|
104
226
|
|
105
227
|
Помимо указанных модификаторов существует возможность добавить собственный.
|
106
|
-
Необходимо уснаследовать его от `Loggun::Modifiers::Base` и указать в методе `apply` все необходимые
|
228
|
+
Необходимо уснаследовать его от `Loggun::Modifiers::Base` и указать в методе `apply` все необходимые действия:
|
229
|
+
|
107
230
|
```ruby
|
108
231
|
require 'sinatra/custom_logger'
|
109
232
|
|
@@ -113,7 +236,9 @@ class NewModifier < Loggun::Modifiers::Base
|
|
113
236
|
end
|
114
237
|
end
|
115
238
|
```
|
116
|
-
|
239
|
+
|
240
|
+
Затем необходимо добавить его при конфигурации гема:
|
241
|
+
|
117
242
|
|
118
243
|
```ruby
|
119
244
|
Loggun::Config.configure do |config|
|
@@ -124,32 +249,45 @@ end
|
|
124
249
|
```
|
125
250
|
|
126
251
|
### Хелперы
|
127
|
-
|
252
|
+
|
253
|
+
Подключение хэлперов в класс позволяет использовать методы логирования `log_info` и `log_error`,
|
128
254
|
а также генерировать идентификатор транзации для каждого метода класса.
|
129
255
|
|
130
256
|
Например:
|
257
|
+
|
131
258
|
```ruby
|
132
259
|
class SomeClass
|
133
260
|
include Loggun::Helpers
|
134
261
|
|
135
|
-
log_options entity_action: :method_name, as_transaction: true
|
136
|
-
|
137
|
-
def some_action
|
138
|
-
log_info 'type_for_action', 'Information'
|
139
|
-
bar
|
140
|
-
end
|
262
|
+
log_options entity_action: :method_name, as_transaction: true, only: %i[download_data]
|
141
263
|
|
142
|
-
def
|
143
|
-
log_info '
|
264
|
+
def download_data
|
265
|
+
log_info 'http_request', 'Information'
|
266
|
+
# ... make http request here
|
267
|
+
log_info 'http_response', success: true
|
144
268
|
end
|
145
269
|
end
|
146
270
|
```
|
147
|
-
|
271
|
+
|
272
|
+
При вызове `#download_data` будет следующий вывод в лог:
|
273
|
+
|
148
274
|
```
|
149
|
-
2020-03-04T16:58:38.207+05:00 - 28476 INFO
|
150
|
-
2020-03-04T16:58:38.208+05:00 - 28476 INFO
|
275
|
+
2020-03-04T16:58:38.207+05:00 - 28476 INFO http_request.some_class.download_data#ffg5431_1583323118203 - {"message":["Information"]}
|
276
|
+
2020-03-04T16:58:38.208+05:00 - 28476 INFO http_response.some_class.download_data#ffg5431_1583323118203 - {"success": true}
|
151
277
|
```
|
152
278
|
|
153
|
-
|
279
|
+
**Важно**, что с хэлпером `log_options` необходимо использовать только методы вида `log_<severity>`.
|
280
|
+
Методы модуля `Loggun` не будут работать.
|
281
|
+
|
282
|
+
Список всех опций хэлпера `log_options`:
|
283
|
+
|
284
|
+
- `entity_name` — имя сущности метода, `string`;
|
285
|
+
- `entity_action` — действие сущности метода, `string`;
|
286
|
+
- `as_transaction` — добавлять ли уникальный ID транзакции для метода, `boolean`;
|
287
|
+
- `transaction_generator` — собственный генератор ID транзакции, `lambda`;
|
288
|
+
- `log_all_methods` — применять ли хэлпер ко всем методам, `boolean`;
|
289
|
+
- `only` — список методов, для которых необходимо применить хэлпер (работает только когда `log_all_methods = false`), `Array{Symbol}`;
|
290
|
+
- `except` — список методов, которые надо исключить для хэлпера, `Array{Symbol}`;
|
291
|
+
- `log_transaction_except` — список методов, логирование которых не нужно обогащать ID транзакции, `Array{Symbol}`.
|
154
292
|
|
155
|
-
|
293
|
+
[](https://funbox.ru)
|
data/lib/loggun.rb
CHANGED
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
|
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)
|
59
74
|
Loggun.logger = app.logger
|
60
|
-
Loggun.logger.formatter = instance.formatter
|
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
@@ -5,7 +5,7 @@ module Loggun
|
|
5
5
|
class Formatter
|
6
6
|
DEFAULT_VALUE = '-'.freeze
|
7
7
|
|
8
|
-
def call(severity, time, _program_name, message)
|
8
|
+
def call(severity, time, _program_name, message, loggun_type: nil)
|
9
9
|
data = Hash.new(DEFAULT_VALUE)
|
10
10
|
data[:time] = time.iso8601(config.timestamp_precision)
|
11
11
|
data[:pid] = Process.pid
|
@@ -14,13 +14,13 @@ module Loggun
|
|
14
14
|
if config.parent_transaction_to_message && parent_transaction
|
15
15
|
message[:parent_transaction] = parent_transaction
|
16
16
|
end
|
17
|
-
message =
|
17
|
+
message = format_message(message)
|
18
18
|
end
|
19
19
|
|
20
20
|
data[:message] = message.to_s.tr("\r\n", ' ').strip
|
21
21
|
data[:severity] = severity&.to_s || 'INFO'
|
22
22
|
data[:tags_text] = tags_text
|
23
|
-
data[:type] = Loggun.type || DEFAULT_VALUE.dup
|
23
|
+
data[:type] = loggun_type || Loggun.type || DEFAULT_VALUE.dup
|
24
24
|
data[:transaction_id] = Loggun.transaction_id
|
25
25
|
data[:parent_transaction] = parent_transaction if parent_transaction
|
26
26
|
|
@@ -78,5 +78,16 @@ module Loggun
|
|
78
78
|
def config
|
79
79
|
Loggun::Config.instance
|
80
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
|
81
92
|
end
|
82
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
|
-
|
41
|
-
|
49
|
+
@log_modified_methods ||= []
|
50
|
+
|
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)
|
42
54
|
|
43
|
-
|
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 logger.send(
|
64
|
-
attrs.empty?
|
75
|
+
next logger.send(method_name, type, &block) if args.empty? && attrs.empty?
|
65
76
|
|
66
|
-
|
67
|
-
type = log_type(type,
|
68
|
-
|
69
|
-
if %i[fatal error].include?(method)
|
70
|
-
methods = args.first.methods
|
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
|
-
logger.send(
|
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,32 @@ 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.log_entity_name if klass.respond_to?(:log_entity_name)
|
143
|
+
|
144
|
+
log_entity_name ||= underscore(klass.name.dup)
|
145
|
+
type_as_arr << log_entity_name
|
146
|
+
end
|
135
147
|
|
136
148
|
return type unless klass.respond_to?(:log_entity_action)
|
137
149
|
|
138
|
-
if klass.log_entity_action && type_as_arr.size < 3
|
139
|
-
|
140
|
-
type << ".#{method_name}"
|
141
|
-
end
|
150
|
+
if klass.log_entity_action && klass.log_entity_action == :method_name && type_as_arr.size < 3 && method_name
|
151
|
+
type_as_arr << method_name
|
142
152
|
end
|
143
153
|
|
144
|
-
|
154
|
+
type_as_arr.join('.')
|
155
|
+
end
|
156
|
+
|
157
|
+
def generate_log_transaction_id
|
158
|
+
if self.class.log_transaction_generator
|
159
|
+
return self.class.log_transaction_generator.call(self)
|
160
|
+
end
|
161
|
+
|
162
|
+
"#{SecureRandom.uuid[0..7]}_#{DateTime.now.strftime('%Q')}"
|
145
163
|
end
|
146
164
|
|
147
165
|
private
|
@@ -162,15 +180,6 @@ module Loggun
|
|
162
180
|
word
|
163
181
|
end
|
164
182
|
|
165
|
-
def generate_log_transaction_id
|
166
|
-
return unless self.class.with_log_transaction_id
|
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
183
|
def logger
|
175
184
|
Loggun.logger
|
176
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
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: loggun
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aleksandr Noskov
|
8
8
|
- Sergey Nesterov
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-
|
12
|
+
date: 2020-07-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -134,6 +134,7 @@ files:
|
|
134
134
|
- ".gitignore"
|
135
135
|
- ".rspec"
|
136
136
|
- ".travis.yml"
|
137
|
+
- CHANGELOG.md
|
137
138
|
- Gemfile
|
138
139
|
- LICENSE.txt
|
139
140
|
- README.md
|
@@ -144,18 +145,20 @@ files:
|
|
144
145
|
- lib/loggun/config.rb
|
145
146
|
- lib/loggun/formatter.rb
|
146
147
|
- lib/loggun/helpers.rb
|
147
|
-
- lib/loggun/http_helpers.rb
|
148
148
|
- lib/loggun/modifiers.rb
|
149
|
+
- lib/loggun/modifiers/active_record.rb
|
150
|
+
- lib/loggun/modifiers/active_record/loggun_log_subscriber.rb
|
149
151
|
- lib/loggun/modifiers/base.rb
|
150
152
|
- lib/loggun/modifiers/clockwork.rb
|
151
153
|
- lib/loggun/modifiers/clockwork/manager.rb
|
152
154
|
- lib/loggun/modifiers/clockwork/methods.rb
|
153
|
-
- lib/loggun/modifiers/incoming_http.rb
|
154
155
|
- lib/loggun/modifiers/outgoing_http.rb
|
155
156
|
- lib/loggun/modifiers/outgoing_http/block_logger.rb
|
156
157
|
- lib/loggun/modifiers/rails.rb
|
157
158
|
- lib/loggun/modifiers/rails/railtie.rb
|
158
159
|
- lib/loggun/modifiers/sidekiq.rb
|
160
|
+
- lib/loggun/modifiers/sidekiq/sidekiq4.rb
|
161
|
+
- lib/loggun/modifiers/sidekiq/sidekiq6.rb
|
159
162
|
- lib/loggun/ordered_options.rb
|
160
163
|
- lib/loggun/version.rb
|
161
164
|
- loggun.gemspec
|
@@ -165,7 +168,7 @@ licenses:
|
|
165
168
|
metadata:
|
166
169
|
homepage_uri: https://github.com/funbox/loggun
|
167
170
|
source_code_uri: https://github.com/funbox/loggun
|
168
|
-
post_install_message:
|
171
|
+
post_install_message:
|
169
172
|
rdoc_options: []
|
170
173
|
require_paths:
|
171
174
|
- lib
|
@@ -181,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
181
184
|
version: '0'
|
182
185
|
requirements: []
|
183
186
|
rubygems_version: 3.0.6
|
184
|
-
signing_key:
|
187
|
+
signing_key:
|
185
188
|
specification_version: 4
|
186
189
|
summary: Loggun
|
187
190
|
test_files: []
|
data/lib/loggun/http_helpers.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
module Loggun
|
2
|
-
module HttpHelpers
|
3
|
-
def self.included(klass)
|
4
|
-
klass.class_eval do
|
5
|
-
around_action :log_http_actions
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
private
|
10
|
-
|
11
|
-
def log_http_actions
|
12
|
-
log_action :start
|
13
|
-
yield
|
14
|
-
log_action :response
|
15
|
-
rescue StandardError => e
|
16
|
-
log_action :response, fail: e
|
17
|
-
raise e
|
18
|
-
end
|
19
|
-
|
20
|
-
def log_action(action = :start, fail: nil)
|
21
|
-
api = request.path[/\w+/]
|
22
|
-
api_version = request.path[/v./]
|
23
|
-
type = "http_request.#{api}.#{action}"
|
24
|
-
data = { path: clean_pathname }
|
25
|
-
data[:api_version] = api_version if api_version
|
26
|
-
|
27
|
-
return Loggun.info type, data if action == :start
|
28
|
-
|
29
|
-
success = fail.nil? && instance_exec(&modifier_config.success_condition)
|
30
|
-
data[:success] = success
|
31
|
-
unless success
|
32
|
-
error = instance_exec(&modifier_config.error_info)
|
33
|
-
data[:error] = error if error
|
34
|
-
end
|
35
|
-
Loggun.info type, data
|
36
|
-
end
|
37
|
-
|
38
|
-
def clean_pathname
|
39
|
-
filtered_params = params.to_unsafe_h
|
40
|
-
filtered_params.delete('action')
|
41
|
-
request.path.gsub(/(#{filtered_params.values.join('|')})/, '').gsub(/\/api\/v./, '')
|
42
|
-
end
|
43
|
-
|
44
|
-
def modifier_config
|
45
|
-
Loggun::Config.instance.modifiers.incoming_http
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
module Loggun
|
2
|
-
module Modifiers
|
3
|
-
class IncomingHttp < Loggun::Modifiers::Base
|
4
|
-
def apply
|
5
|
-
return unless defined?(ActionPack)
|
6
|
-
|
7
|
-
controllers = Loggun::Config.instance.modifiers.incoming_http.controllers
|
8
|
-
controllers.each do |controller|
|
9
|
-
controller.constantize.class_eval do
|
10
|
-
include Loggun::HttpHelpers
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|