superlogger 0.2.1 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +23 -48
- data/lib/superlogger/action_controller_log_subscriber.rb +3 -11
- data/lib/superlogger/action_view_log_subscriber.rb +1 -1
- data/lib/superlogger/active_record_log_subscriber.rb +5 -3
- data/lib/superlogger/logger.rb +13 -27
- data/lib/superlogger/superlogger_middleware.rb +8 -9
- data/lib/superlogger/version.rb +1 -1
- data/lib/superlogger.rb +20 -5
- data/test/dummy/app/assets/config/manifest.js +3 -0
- data/test/dummy/config/application.rb +3 -2
- data/test/superlogger_test.rb +30 -58
- metadata +10 -181
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +0 -545
- data/test/dummy/log/test.log +0 -1732
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/-H/-HJqDF0cY1IQQf6G35SzwnWhdJwbb0rjsilAS1uSnC0.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/1e/1eeMDHdcXM5QG6315g0Uj656M_FVD0teimYul97xBzQ.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/38/38YtaoIS3EsFiiaKJPIWZKoxwdIGtUeAuwIBAuuQ8Mg.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/5L/5Lly_CA8DZvPhQV2jDQx-Y6P_y3Ygra9t5jfSlGhHDA.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/7J/7JXLU3kClrFYffhxcnNaLGjYz8LFI700NBjNiBOifaU.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/C_/C_C8IqUQirTZx1bt5Ewm3QJvhVbwm66pxvcH0maphFY.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/Ch/Ch2bQFHkYziI9Erdkuj8uoPJyw0W2aA5prtYAqlccww.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/Cq/Cq4V3OyOOk4eTJXISTKVc4MbIHDmq4eu3lSNh85i78k.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/DS/DSOLSc6A5RVSmvM415eEWAWG_AgOvZcLZOXQjsXyWQA.cache +0 -2
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/EC/EC4O6KSVM5bCKFeBl2j8bzAbnhklqssWQ-6XEqM_tC4.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/Gy/Gyqn3Ja6WbUSqKnvWm9Xw7FIxFqJIPQ88IlgpguMo1s.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/H3/H3tvaQM-yTy-25oSLlfjToAa74LSJHBDUpji-8C-eLg.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/Iv/IvDM1j8-H1H6kEjVCsyIW8N2zla-aIp9q_OE9PVZtVw.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/Jj/JjqPODxMglZzjE6lolNyoEiFCULPe-AH8rndpgamPPk.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/K9/K9ZheMi0hi4DNLzmDMRnv9A_lOVz33kNImc16Now42o.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/LH/LHgjtAV8kdldaJ_dX0RCznzjmWYRuLdhU29fZCJ0VmU.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/Nn/NnUCa7jNYx9HCmEB7E7WPWT00DwaM4IYICy1Ju1jjcs.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/O5/O5UdaBuHdxmEoYz3AFZsm3rh7MWtRFXwHOryps7b5tE.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/OI/OI6uxGcnsKavdWTtwDAasU3wPx8QXhzBgV0X2n1KjMQ.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/Ol/OlBX9JIv9SAOmK2t35x1SYDx1sxCXF0yvqpna3WMyH0.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/Pg/PgSSsdzJcNT1S4NDynUSIcj_YZXO_IKpcmyafopOamk.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/SG/SGLQX80_DB28A_mjz_Eh9ZQxVU85Dz1YSRz0Xf3T6qE.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/T4/T4WYRrwWhIVaINf3NmLDXIAI3bybsjl0y4P1KQgM-Qs.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/Yr/YrZ0OIHu42cExs1kqngMA6ShVDKhfGmhyW-E9haNo5Y.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/ZQ/ZQkA-jIm0iNMfDDgK-M4OcgHPKRo-uBuEEowd_5_6Rg.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/ZU/ZUokoeZcfmoTFE9YAHZRhTgceOUGJTDGH__SCqPfkqU.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/_I/_IocgQl8XVm84HohovEBj-GxsSeBkOpqN-94yHgY-K8.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/bJ/bJVgCoQDvMv4iocjEuC3z3WqSeK7LXgxDJ-eXaHl0l4.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/b_/b_-O1DwVvDk3vPJ-GHDgGWR9Zth9CYblcXbBe6aiTf0.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/br/brSVWTme0G1yzUMjrDpklxoQetdFLXdF8ZUkYXFX-sE.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/cI/cIaWfk6Nq6ZAr0fhtHGTBtsRITI5n8IJFZbClZ2tExw.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/f-/f-gxq-RYinlir2WGpHfXu4C3r6M4aidyokcd7ZnBOao.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/fE/fEpQwSnNzL1JpFhnElwxvX6YuOxn_vv_QuOTJNrl21M.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/g3/g3x0V2jnf5A31QMz4xGeQMouu2eChQRpoe0BEWWESeY.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/gV/gVVPZef0xfm7t9Jyesa7ZVdnpzMpw2QtOyYUoEXO7fk.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/gZ/gZp3uXMHuYQC4hzCr7bQfetKNdJAtbQmg3so2KpW1Dw.cache +0 -2
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/gb/gbunrAFVOHPwl2npUgKv_C3f_qiJnZDd9zG5-h3jrpo.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/gp/gpiWtnqpufka8lRtMznM6Ko0aWJrcH_j8cfZwdYmzNI.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/hZ/hZi1k6tpxxCGYxRe7zY74ItcOI8gZrREOpGuA8JSpGg.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/hl/hlDmEHZNeRDjBO6WJNb8ftVgfvCQubblXCEJw_MO3ow.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/i7/i7v4b6OSQUj-1r9vUWRiOHjAVksSTpUfilZTpk0ACLc.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/kz/kzdSvu57G4i6eTuarsZCAfbhbICnkRa0Xhi0b9ua6qk.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/mv/mvqN6PphkrOOC8zbUEhpC_9E_4ybdO25MRy_gG6dq3Y.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/nm/nmcUZlKAIwyJ_35Nm9P8pukLeRX5aApP6NFj5MpNPgc.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/pE/pEhaat2KBd5SrT7szC_8R1_6hK17FTpvoRFkmCRSD3M.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/rC/rCO5-bHVJ6Y_GsPBmOPUL23pfjvc2Gw2zt_ODmZsygw.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/rg/RgmbeHiCGDMtbXGovkyp2kHJljF3k6_21IfxBUqa2GQ.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/rg/rghMLGUpm1Uy3OPgfILHnVwLCycV9Rd9kSpEbxdwVV4.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/vm/vm9zMjZUFULeJsYWRoDd3cvnEpLGK-E5XTk30_NQTEs.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/wD/wDDl7jzOUTDgFcG1JlpN6jVHavfzB8Smsjtl3d8WDx0.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/xd/xdBKQyhEAlDIstGvXw945PWJoEWi23rKuY7elOcWqHc.cache +0 -1
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/ys/ysosYWYA283HXmg_f6HoIzLi86SIIm3aVUwWF7tZJHY.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/-Z_pj4kfRj993e_ypawYQUIDIDKcRe569udVq_1drFs.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/2G0Z7Q5fvf2xX8ygtwcD9vZq-kwEzoV2MFc1URegs7s.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/5Lly_CA8DZvPhQV2jDQx-Y6P_y3Ygra9t5jfSlGhHDA.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/66bWF3byFzdKpXZsrn5Vy9CJBaDlkJKkoyqeLRRbBZY.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/9NtfUddiu2UU8sqL-bYq-NPAx8NGp5m5AYiAWAcKQQ4.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/DSOLSc6A5RVSmvM415eEWAWG_AgOvZcLZOXQjsXyWQA.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/GELqHyWyVR_UvkpZPDb5xjZrCgkKB5G067DYoMwTjEA.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/Gyqn3Ja6WbUSqKnvWm9Xw7FIxFqJIPQ88IlgpguMo1s.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/H5fHMceViwaxMKkefsdMmVpBN3rRYZI1obJX5Jn-4jw.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/IEJfj4Zwfra6y7iF-BOVR9PPIQeL9L5IiZT8MRqpCXg.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/IordxSS9mOh1mkt2VyfX7Iz4DhZhy73lccOYxcw5aVU.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/KgQHhqXCaYHJSJEG6JweQVe1a2rC-mHfkrqD9p9taTU.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/Ki_R5uSCGEm1Jn7TSbJOc3eBMn4Q3_IPLG0r_RRn9lA.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/NBBjlBjfPdkZkp4G7VCEA9LAeGycMn10CxLbDAbNeHc.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/OI6uxGcnsKavdWTtwDAasU3wPx8QXhzBgV0X2n1KjMQ.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/V9m2At1eKJAvbGAFvFTUt8hcdNI-G8xW1AShyPYS4Ys.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/XsDQ8X8Klh__7HZNZk8sjYzyFg5TmATqo-_UraArzN8.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/ZtbyFLml01tdqcRh4Ocz6XOkbPpmHM6nFRRYY4Nphpc.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/_ZNMI9IrCfXNcrwiRGttWiFPcLlCSpkdJSFoLhmUpyg.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/brSVWTme0G1yzUMjrDpklxoQetdFLXdF8ZUkYXFX-sE.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/gZp3uXMHuYQC4hzCr7bQfetKNdJAtbQmg3so2KpW1Dw.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/hZi1k6tpxxCGYxRe7zY74ItcOI8gZrREOpGuA8JSpGg.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/jqyQL40gGhkqnPg3IttXbq8JGHLONBjR0MlrN9HeIvU.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/kqQAJDpBuiNJ3XEy8VjtVcyUB9BVlP02oDMdVnlL04w.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/pEhaat2KBd5SrT7szC_8R1_6hK17FTpvoRFkmCRSD3M.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/pnW3u_1AN48ig6ngefI89y96xoSlvnJurx-e3J-leoE.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/q9kUTJTzJpwJJQ8CoWPFc_eCW76RZgB-R2sc4P84y6c.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/qFlPbNZ3UJs9EnENWVEbNWnrTEcjZkAQUzH55y3Ymi0.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/r86oWGkKGjcta2GtxqeESX1w_4FX1c_DWHxPWVKP28A.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/ssS2x0Wl67rwXHaVHsh6CO7ayn9fQ5saIwATKN6O-nI.cache +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: '082cbc716a6f0432e73617a883fd03584bd8f3de5a1f3f32afd6a48882d05f76'
|
4
|
+
data.tar.gz: c85c50a9e182a78c3c281a427b5fd351c4c01b9181dbeffe81a6831bc51f7b39
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f5eb670792f8cb1abf4a4b3830b7b0e415b9f0849d9339bf8ddce091dc71dd7f2cc455813f7c6ca64fafba40ab8de59f32c6fd1a6c5cec74d24968caecc3624
|
7
|
+
data.tar.gz: bc3c65ddb32e7e5eec96de1028d86a12557fda30643797eb71e863db4dac24fcf82dd5434a8c72639a9eb78b1168e60fc4c2dc3fbbd71fffb6a0dcbf08cc3f13
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
Superlogger - Machine-readable logging for Rails
|
6
6
|
=======
|
7
7
|
|
8
|
-
Rails' default request logging is easy to read for humans but difficult for log aggregators such as Kibana, Graylog and Splunk. Superlogger transforms the logs into
|
8
|
+
Rails' default request logging is easy to read for humans but difficult for log aggregators such as Kibana, Graylog and Splunk. Superlogger transforms the logs into JSON for easy parsing and adds useful details like Timestamp, Session ID and Request ID for tracing purposes.
|
9
9
|
|
10
10
|
Default rails logging:
|
11
11
|
```sh
|
@@ -23,34 +23,18 @@ Started GET "/assets/application.self-8f06a73c35179188914ab50e057157639fce1401c1
|
|
23
23
|
|
24
24
|
```
|
25
25
|
|
26
|
-
|
26
|
+
With Superlogger:
|
27
27
|
```sh
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
# second request
|
38
|
-
2016-04-29 17:39:54.879 | 12dc0e484869 | e463d380fb63 | I | superlogger_middleware:30 | method=GET | path=/home/show | ip=::1
|
39
|
-
2016-04-29 17:39:54.879 | 12dc0e484869 | e463d380fb63 | D | action_controller_log_subscriber:9 | controller=HomeController | action=show | params={}
|
40
|
-
2016-04-29 17:39:54.882 | 12dc0e484869 | e463d380fb63 | D | action_view_log_subscriber:6 | view=show.html.erb | duration=0.2
|
41
|
-
2016-04-29 17:39:54.884 | 12dc0e484869 | e463d380fb63 | I | action_controller_log_subscriber:29 | status=200 | total_duration=4.64 | view_duration=4.55 | db_duration=0.0
|
42
|
-
2016-04-29 17:39:54.884 | 12dc0e484869 | e463d380fb63 | I | superlogger_middleware:30 | method=GET | path=/home/index | total_duration=4.64
|
28
|
+
{"level":"debug","ts":1590972589.522784,"caller":"superlogger/active_record_log_subscriber:21","sql":"SELECT \"schema_migrations\".\"version\" FROM \"schema_migrations\" ORDER BY \"schema_migrations\".\"version\" ASC","params":[],"duration":0.13}
|
29
|
+
{"level":"info","ts":1590972589.526133,"caller":"superlogger/superlogger_middleware:21","session_id":"90e90c75c72c","request_id":"34432478c89b4d8591e02e0169b40a56","method":"GET","path":"/home/index"}
|
30
|
+
{"level":"debug","ts":1590972589.546272,"caller":"superlogger/action_controller_log_subscriber:8","session_id":"90e90c75c72c","request_id":"34432478c89b4d8591e02e0169b40a56","controller":"HomeController","action":"index","params":{}}
|
31
|
+
{"level":"debug","ts":1590972589.55092,"caller":"superlogger/active_record_log_subscriber:21","session_id":"90e90c75c72c","request_id":"34432478c89b4d8591e02e0169b40a56","sql":"SELECT \"somethings\".* FROM \"somethings\" WHERE \"somethings\".\"paper\" = ? AND \"somethings\".\"stone\" = ? ORDER BY \"somethings\".\"id\" ASC LIMIT ?","params":["123","456","1"],"duration":0.22}
|
32
|
+
{"level":"debug","ts":1590972589.574199,"caller":"superlogger/action_view_log_subscriber:6","session_id":"90e90c75c72c","request_id":"34432478c89b4d8591e02e0169b40a56","view":"_partial.html.erb","duration":0.33}
|
33
|
+
{"level":"debug","ts":1590972589.574795,"caller":"superlogger/action_view_log_subscriber:6","session_id":"90e90c75c72c","request_id":"34432478c89b4d8591e02e0169b40a56","view":"index.html.erb","duration":2.95}
|
34
|
+
{"level":"info","ts":1590972589.61165,"caller":"superlogger/action_controller_log_subscriber:20","session_id":"90e90c75c72c","request_id":"34432478c89b4d8591e02e0169b40a56","view_duration":54.59,"db_duration":0.85}
|
35
|
+
{"level":"info","ts":1590972589.611928,"caller":"superlogger/superlogger_middleware:30","session_id":"90e90c75c72c","request_id":"34432478c89b4d8591e02e0169b40a56","method":"GET","path":"/home/index","response_time":85.65,"status":200}
|
43
36
|
```
|
44
37
|
|
45
|
-
## Features ##
|
46
|
-
- Timestamp (milliseconds)
|
47
|
-
- Session ID for logs belonging to the same user session (notice above that both the requests have the same session id)
|
48
|
-
- Request ID for logs belonging to the same page request (notice above that each request have a different request id)
|
49
|
-
- Hashes will be logged as key-value pairs automatically
|
50
|
-
- Requests for assets will not be logged
|
51
|
-
- File and line numbers
|
52
|
-
- IP address of request
|
53
|
-
|
54
38
|
## Installation ##
|
55
39
|
|
56
40
|
Add superlogger to your application's Gemfile
|
@@ -63,37 +47,28 @@ Execute:
|
|
63
47
|
$ bundle
|
64
48
|
```
|
65
49
|
|
66
|
-
And add the following in `config/
|
50
|
+
And add the following in `config/environment/production.rb`
|
67
51
|
```ruby
|
68
52
|
config.logger = Superlogger::Logger.new(STDOUT)
|
69
53
|
```
|
70
54
|
|
55
|
+
By default, Superlogger is only enabled in production environment because JSON is easy for machines to parse but difficult for humans to read. To forcefully enable Superlogger in non-production environment, set in `config/application.rb`:
|
56
|
+
```ruby
|
57
|
+
Superlogger.enabled = true
|
58
|
+
```
|
59
|
+
|
71
60
|
## Usage ##
|
72
61
|
|
73
62
|
Log as per normal using `Rails.logger`.
|
74
63
|
|
75
64
|
```ruby
|
76
|
-
|
77
|
-
|
78
|
-
Rails.logger.debug foo:'true', bar: 'false'
|
79
|
-
Rails.logger.info foo:'true', bar: 'false'
|
80
|
-
Rails.logger.warn foo:'true', bar: 'false'
|
81
|
-
Rails.logger.error foo:'true', bar: 'false'
|
82
|
-
Rails.logger.fatal foo:'true', bar: 'false'
|
83
|
-
end
|
84
|
-
end
|
65
|
+
Rails.logger.info foo:'true', bar: 'false'
|
66
|
+
Rails.logger.info "Meatball"
|
85
67
|
```
|
86
68
|
|
87
69
|
## Log Format ##
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
### Severity Levels ###
|
95
|
-
- **D** - Debug
|
96
|
-
- **I** - Info
|
97
|
-
- **W** - Warn
|
98
|
-
- **E** - Error
|
99
|
-
- **F** - Fatal
|
70
|
+
- `ts` = Unix Epoch timestamp
|
71
|
+
- `session_id` = Truncated to 12 characters
|
72
|
+
- `request_id` = 32 characters
|
73
|
+
- `msg` = If values given is not a hash, it is treated as `{"msg":<value>"}`
|
74
|
+
- All duration related fields are in milliseconds
|
@@ -5,27 +5,19 @@ module Superlogger
|
|
5
5
|
# start of controller action
|
6
6
|
def start_processing(event)
|
7
7
|
payload = event.payload
|
8
|
-
|
9
|
-
logger.debug controller: payload[:controller], action: payload[:action], params: payload[:params].except(*INTERNAL_PARAMS)
|
8
|
+
logger.debug {{ controller: payload[:controller], action: payload[:action], params: payload[:params].except(*INTERNAL_PARAMS) }}
|
10
9
|
end
|
11
10
|
|
12
11
|
# end of controller action
|
13
12
|
def process_action(event)
|
14
13
|
payload = event.payload
|
15
|
-
total_duration = event.duration.to_f.round(2)
|
16
14
|
view_duration = payload[:view_runtime].to_f.round(2) if payload.key?(:view_runtime)
|
17
15
|
db_duration = payload[:db_runtime].to_f.round(2) if payload.key?(:db_runtime)
|
18
16
|
|
19
17
|
if payload[:exception]
|
20
|
-
|
21
|
-
|
22
|
-
logger.fatal status: status, total_duration: total_duration, view_duration: view_duration, db_duration: db_duration, exception: payload[:exception]
|
18
|
+
logger.fatal view_duration: view_duration, db_duration: db_duration, exception: payload[:exception]
|
23
19
|
else
|
24
|
-
|
25
|
-
# https://github.com/pcg79/devise/commit/1e2dab3c0ce49efe2b5940c15f47388c69d6731b
|
26
|
-
payload[:status] ||= 401
|
27
|
-
|
28
|
-
logger.info status: payload[:status], total_duration: total_duration, view_duration: view_duration, db_duration: db_duration
|
20
|
+
logger.info view_duration: view_duration, db_duration: db_duration
|
29
21
|
end
|
30
22
|
end
|
31
23
|
end
|
@@ -3,7 +3,7 @@ module Superlogger
|
|
3
3
|
def render_template(event)
|
4
4
|
payload = event.payload
|
5
5
|
|
6
|
-
logger.debug view: payload[:identifier].split('/').last, duration: event.duration.round(
|
6
|
+
logger.debug {{ view: payload[:identifier].split('/').last, duration: event.duration.round(2) }}
|
7
7
|
end
|
8
8
|
alias :render_partial :render_template
|
9
9
|
alias :render_collection :render_template
|
@@ -18,10 +18,12 @@ module Superlogger
|
|
18
18
|
payload = event.payload
|
19
19
|
return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
logger.debug do
|
22
|
+
sql = payload[:sql]
|
23
|
+
params = payload[:binds].map { |b| b.value.to_s }
|
23
24
|
|
24
|
-
|
25
|
+
{ sql: sql, params: params, duration: event.duration.round(2) }
|
26
|
+
end
|
25
27
|
end
|
26
28
|
end
|
27
29
|
end
|
data/lib/superlogger/logger.rb
CHANGED
@@ -2,26 +2,25 @@ require 'request_store'
|
|
2
2
|
|
3
3
|
module Superlogger
|
4
4
|
class Logger < ActiveSupport::Logger
|
5
|
-
def initialize(*args)
|
6
|
-
super
|
7
|
-
@formatter = SimpleFormatter.new
|
8
|
-
end
|
9
|
-
|
10
5
|
def format_message(severity, time, _progname, msg)
|
11
6
|
return nil if msg.blank? # Silence nil and empty msg
|
12
7
|
return nil if is_rails_rack_logger_msg?(msg) # Silence rack logger msg
|
13
8
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
9
|
+
msg = {msg: msg} unless msg.is_a?(Hash)
|
10
|
+
|
11
|
+
h = {}
|
12
|
+
h[:level] = severity.downcase
|
13
|
+
h[:ts] = time.to_f
|
14
|
+
h[:caller] = get_caller_location
|
15
|
+
h[:session_id] = Superlogger.session_id[0..11] unless Superlogger.session_id.nil?
|
16
|
+
h[:request_id] = Superlogger.request_id unless Superlogger.request_id.nil?
|
17
|
+
h.merge!(msg)
|
20
18
|
|
21
|
-
|
19
|
+
h.to_json + "\n"
|
22
20
|
end
|
23
21
|
|
24
22
|
def is_rails_rack_logger_msg?(msg)
|
23
|
+
return false unless msg.is_a?(String)
|
25
24
|
msg =~ /Started (GET|POST|PUT|PATCH|DELETE)/
|
26
25
|
end
|
27
26
|
|
@@ -30,25 +29,12 @@ module Superlogger
|
|
30
29
|
location = caller_locations(index, 1).first
|
31
30
|
|
32
31
|
# Extract filename without file extension from location.path
|
33
|
-
# eg. superlogger/lib/superlogger/logger.rb
|
34
|
-
file = location.path.split('/').last.split('.').first
|
32
|
+
# eg. superlogger/lib/superlogger/logger.rb => superlogger/logger
|
33
|
+
file = location.path.split('/').last(2).join('/').split('.').first
|
35
34
|
|
36
35
|
"#{file}:#{location.lineno}"
|
37
36
|
end
|
38
37
|
|
39
|
-
def format_args(args)
|
40
|
-
output = if args.is_a?(Hash)
|
41
|
-
# Format args in key=value pair, separated by pipes
|
42
|
-
args.map do |key, value|
|
43
|
-
"#{key}=#{value}"
|
44
|
-
end.join(' | ')
|
45
|
-
else
|
46
|
-
args.to_s
|
47
|
-
end
|
48
|
-
|
49
|
-
output.gsub("\n", '\\n') # Escape newlines
|
50
|
-
end
|
51
|
-
|
52
38
|
# To silence double logging when running `rails server` in development mode
|
53
39
|
# See: https://github.com/rails/rails/commit/3d10d9d6c3b831fe9632c43a0ffec46104f912a7
|
54
40
|
if Rails.env.development?
|
@@ -6,7 +6,7 @@ module Superlogger
|
|
6
6
|
|
7
7
|
def call(env)
|
8
8
|
request = ActionDispatch::Request.new(env)
|
9
|
-
|
9
|
+
|
10
10
|
if request.path.start_with?('/assets/') == false
|
11
11
|
process_request(request) { @app.call(env) }
|
12
12
|
else
|
@@ -18,27 +18,26 @@ module Superlogger
|
|
18
18
|
setup_logging(request)
|
19
19
|
|
20
20
|
# Start of request
|
21
|
-
Rails.logger.info method: request.method, path: request.fullpath
|
21
|
+
Rails.logger.info method: request.method, path: request.fullpath
|
22
22
|
|
23
23
|
t1 = Time.now
|
24
|
-
|
24
|
+
status, _headers, _response = yield
|
25
25
|
ensure
|
26
26
|
t2 = Time.now
|
27
27
|
|
28
28
|
# End of request
|
29
29
|
duration = ((t2 - t1) * 1000).to_f.round(2)
|
30
|
-
Rails.logger.info method: request.method, path: request.fullpath,
|
30
|
+
Rails.logger.info method: request.method, path: request.fullpath, response_time: duration, status: status
|
31
31
|
|
32
|
-
|
32
|
+
[status, _headers, _response]
|
33
33
|
end
|
34
34
|
|
35
35
|
def setup_logging(request)
|
36
36
|
if request.env['rack.session']
|
37
|
-
# Session is lazy loaded. Force session to load if it is not already loaded.
|
38
|
-
request.env['rack.session'].send(:load!) unless request.env['rack.session'].id
|
39
|
-
|
40
37
|
# Store session id before any actual logging is done
|
41
|
-
|
38
|
+
if request.env['rack.session'].id
|
39
|
+
Superlogger.session_id = request.env['rack.session'].id.to_s
|
40
|
+
end
|
42
41
|
end
|
43
42
|
|
44
43
|
Superlogger.request_id = request.uuid.try(:gsub, '-', '')
|
data/lib/superlogger/version.rb
CHANGED
data/lib/superlogger.rb
CHANGED
@@ -2,9 +2,13 @@ require 'superlogger/version'
|
|
2
2
|
require 'superlogger/logger'
|
3
3
|
|
4
4
|
module Superlogger
|
5
|
+
@@enabled = false
|
6
|
+
|
5
7
|
module_function
|
6
8
|
|
7
9
|
def setup(app)
|
10
|
+
return unless (Rails.env.production? || enabled)
|
11
|
+
|
8
12
|
insert_superlogger_middleware(app)
|
9
13
|
detach_existing_log_subscribers
|
10
14
|
attach_superlogger_log_subscribers
|
@@ -24,7 +28,7 @@ module Superlogger
|
|
24
28
|
require 'action_view/log_subscriber'
|
25
29
|
|
26
30
|
# remove log subscribers
|
27
|
-
|
31
|
+
remove_patterns = %w(sql.active_record
|
28
32
|
start_processing.action_controller
|
29
33
|
process_action.action_controller
|
30
34
|
render_template.action_view
|
@@ -32,8 +36,11 @@ module Superlogger
|
|
32
36
|
render_collection.action_view)
|
33
37
|
|
34
38
|
ActiveSupport::LogSubscriber.log_subscribers.each do |subscriber|
|
35
|
-
subscriber.patterns
|
36
|
-
|
39
|
+
patterns = subscriber.patterns
|
40
|
+
patterns = patterns.is_a?(Hash) ? patterns.keys : patterns
|
41
|
+
|
42
|
+
patterns.each do |pattern|
|
43
|
+
ActiveSupport::Notifications.unsubscribe pattern if remove_patterns.include?(pattern)
|
37
44
|
end
|
38
45
|
end
|
39
46
|
end
|
@@ -49,7 +56,7 @@ module Superlogger
|
|
49
56
|
end
|
50
57
|
|
51
58
|
def session_id
|
52
|
-
RequestStore.store[:superlogger_session_id]
|
59
|
+
RequestStore.store[:superlogger_session_id]
|
53
60
|
end
|
54
61
|
|
55
62
|
def request_id=(request_id)
|
@@ -57,7 +64,15 @@ module Superlogger
|
|
57
64
|
end
|
58
65
|
|
59
66
|
def request_id
|
60
|
-
RequestStore.store[:superlogger_request_id]
|
67
|
+
RequestStore.store[:superlogger_request_id]
|
68
|
+
end
|
69
|
+
|
70
|
+
def enabled=(enabled)
|
71
|
+
@@enabled=enabled
|
72
|
+
end
|
73
|
+
|
74
|
+
def enabled
|
75
|
+
@@enabled
|
61
76
|
end
|
62
77
|
end
|
63
78
|
|
@@ -19,8 +19,9 @@ module Dummy
|
|
19
19
|
# config.i18n.default_locale = :de
|
20
20
|
|
21
21
|
# Do not swallow errors in after_commit/after_rollback callbacks.
|
22
|
-
config.active_record.raise_in_transactional_callbacks = true
|
23
|
-
|
22
|
+
# config.active_record.raise_in_transactional_callbacks = true
|
23
|
+
|
24
|
+
Superlogger.enabled = true
|
24
25
|
config.logger = Superlogger::Logger.new(STDOUT)
|
25
26
|
end
|
26
27
|
end
|
data/test/superlogger_test.rb
CHANGED
@@ -25,7 +25,7 @@ class SuperloggerTest < ActiveSupport::TestCase
|
|
25
25
|
|
26
26
|
def output
|
27
27
|
@parsed_output ||= @output.string.split("\n").map do |line|
|
28
|
-
|
28
|
+
JSON.parse(line)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -37,128 +37,100 @@ class SuperloggerTest < ActiveSupport::TestCase
|
|
37
37
|
request('home/index')
|
38
38
|
|
39
39
|
fields = output.first
|
40
|
-
assert fields
|
41
|
-
assert fields
|
42
|
-
assert fields
|
43
|
-
assert fields
|
44
|
-
|
40
|
+
assert fields.key?("level")
|
41
|
+
assert fields.key?("ts")
|
42
|
+
assert fields.key?("caller")
|
43
|
+
assert fields.key?("session_id")
|
44
|
+
assert fields.key?("request_id")
|
45
45
|
end
|
46
46
|
|
47
47
|
test 'timestamp' do
|
48
48
|
request('home/index')
|
49
|
-
|
49
|
+
assert_equal Time.at(output[0]["ts"]).to_date, Date.today
|
50
50
|
end
|
51
51
|
|
52
52
|
test 'with session_id' do
|
53
53
|
env = request('home/index')
|
54
|
-
assert_match env['rack.session'].id[0..11], output[0][
|
54
|
+
assert_match env['rack.session'].id.to_s[0..11], output[0]["session_id"]
|
55
55
|
end
|
56
56
|
|
57
57
|
test 'without session_id' do
|
58
58
|
Rails.logger.debug var: 'test'
|
59
|
-
|
59
|
+
assert_equal output[0].key?("session_id"), false
|
60
60
|
end
|
61
61
|
|
62
62
|
test 'with request_id' do
|
63
63
|
request('home/index')
|
64
|
-
assert_no_match(/^NR-[[:alnum:]]+$/, output[0][
|
64
|
+
assert_no_match(/^NR-[[:alnum:]]+$/, output[0]["request_id"])
|
65
65
|
end
|
66
66
|
|
67
67
|
test 'without request_id' do
|
68
68
|
Rails.logger.debug var: 'test'
|
69
|
-
|
70
|
-
end
|
71
|
-
|
72
|
-
test 'log levels' do
|
73
|
-
Rails.logger.debug var: 'test'
|
74
|
-
Rails.logger.info var: 'test'
|
75
|
-
Rails.logger.warn var: 'test'
|
76
|
-
Rails.logger.error var: 'test'
|
77
|
-
Rails.logger.fatal var: 'test'
|
78
|
-
|
79
|
-
assert output[0][3] == 'D'
|
80
|
-
assert output[1][3] == 'I'
|
81
|
-
assert output[2][3] == 'W'
|
82
|
-
assert output[3][3] == 'E'
|
83
|
-
assert output[4][3] == 'F'
|
69
|
+
assert_equal output[0].key?("request_id"), false
|
84
70
|
end
|
85
71
|
|
86
72
|
test 'caller location' do
|
87
73
|
Rails.logger.debug var: 'test'
|
88
|
-
|
74
|
+
assert_equal output[0]["caller"], "test/superlogger_test:#{__LINE__ - 1}"
|
89
75
|
end
|
90
76
|
|
91
77
|
test 'silence_rails_rack_logger' do
|
92
78
|
request('home/index')
|
93
|
-
assert_no_match 'Started GET', output[0][
|
79
|
+
assert_no_match 'Started GET', output[0]["msg"]
|
94
80
|
end
|
95
81
|
|
96
82
|
test 'middleware start' do
|
97
83
|
request('home/index', 'REMOTE_ADDR' => '::1')
|
98
84
|
|
99
85
|
fields = output[0]
|
100
|
-
assert_match '
|
101
|
-
assert_match '
|
102
|
-
assert_match 'ip=::1', fields[7]
|
86
|
+
assert_match 'GET', fields["method"]
|
87
|
+
assert_match '/home/index', fields["path"]
|
103
88
|
end
|
104
89
|
|
105
90
|
test 'middleware end' do
|
106
91
|
request('home/index', 'REMOTE_ADDR' => '::1')
|
107
92
|
|
108
93
|
fields = output.last
|
109
|
-
assert_match '
|
110
|
-
assert_match '
|
111
|
-
|
112
|
-
assert_operator fields[7].split('=').last.to_f, :>, 0
|
94
|
+
assert_match 'GET', fields["method"]
|
95
|
+
assert_match '/home/index', fields["path"]
|
96
|
+
assert_operator fields["response_time"], :>, 0
|
113
97
|
end
|
114
98
|
|
115
99
|
test 'action_controller_log_subscriber.start_processing' do
|
116
100
|
request('home/index?a=1')
|
117
101
|
|
118
102
|
fields = output[1]
|
119
|
-
assert_match '
|
120
|
-
assert_match '
|
121
|
-
|
103
|
+
assert_match 'HomeController', fields["controller"]
|
104
|
+
assert_match 'index', fields["action"]
|
105
|
+
assert_equal Hash.new.tap {|h| h["a"] ="1"}, fields["params"]
|
122
106
|
end
|
123
107
|
|
124
108
|
test 'action_controller_log_subscriber.process_action' do
|
125
109
|
request('home/index')
|
126
110
|
|
127
111
|
fields = output[5]
|
128
|
-
|
129
|
-
|
130
|
-
assert_operator fields[6].split('=').last.to_f, :>, 0
|
131
|
-
assert_match(/^view_duration=\d+.\d+$/, fields[7])
|
132
|
-
assert_operator fields[7].split('=').last.to_f, :>, 0
|
133
|
-
assert_match(/^db_duration=\d+.\d+$/, fields[8])
|
134
|
-
assert_operator fields[8].split('=').last.to_f, :>, 0
|
112
|
+
assert_operator fields["view_duration"], :>, 0
|
113
|
+
assert_operator fields["db_duration"], :>, 0
|
135
114
|
end
|
136
115
|
|
137
116
|
test 'action_view_log_subscriber.render_template.render_partial.render_collection' do
|
138
117
|
request('home/index')
|
139
118
|
|
140
119
|
fields = output[3]
|
141
|
-
assert_match '
|
142
|
-
|
120
|
+
assert_match 'partial.html.erb', fields["view"]
|
121
|
+
assert fields.key?("duration")
|
143
122
|
|
144
123
|
fields = output[4]
|
145
|
-
assert_match '
|
146
|
-
|
124
|
+
assert_match 'index.html.erb', fields["view"]
|
125
|
+
assert fields.key?("duration")
|
147
126
|
end
|
148
127
|
|
149
128
|
test 'active_record_log_subscriber.sql' do
|
150
129
|
request('home/index')
|
151
130
|
|
152
131
|
fields = output[2]
|
153
|
-
assert_match '
|
154
|
-
|
155
|
-
|
156
|
-
assert_operator fields[7].split('=').last.to_f, :>, 0
|
157
|
-
end
|
158
|
-
|
159
|
-
test 'escape new lines' do
|
160
|
-
Rails.logger.debug var: 'first\nsecond'
|
161
|
-
|
162
|
-
assert_match 'first\\nsecond', output[0].last
|
132
|
+
assert_match 'SELECT', fields["sql"]
|
133
|
+
assert_equal ["123", "456", "1"], fields["params"]
|
134
|
+
assert_operator fields["duration"], :>, 0
|
163
135
|
end
|
164
136
|
end
|