loggun 0.1.1 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Sponsored by FunBox](https://funbox.ru/badges/sponsored_by_funbox_compact.svg)](https://funbox.ru)
|
4
|
-
|
5
3
|
[![Gem Version](https://badge.fury.io/rb/loggun.svg)](https://badge.fury.io/rb/loggun)
|
6
4
|
[![Build Status](https://travis-ci.org/funbox/loggun.svg?branch=master)](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
|
+
[![Sponsored by FunBox](https://funbox.ru/badges/sponsored_by_funbox_centered.svg)](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
|