superlogger 0.0.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +82 -0
- data/Rakefile +34 -0
- data/lib/superlogger.rb +54 -0
- data/lib/superlogger/action_controller_log_subscriber.rb +35 -0
- data/lib/superlogger/action_dispatch_debug_exceptions.rb +11 -0
- data/lib/superlogger/action_view_log_subscriber.rb +13 -0
- data/lib/superlogger/active_record_log_subscriber.rb +29 -0
- data/lib/superlogger/logger.rb +79 -0
- data/lib/superlogger/middleware.rb +31 -0
- data/lib/superlogger/rails_rack_logger.rb +11 -0
- data/lib/superlogger/railtie.rb +7 -0
- data/lib/superlogger/version.rb +3 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/controllers/home_controller.rb +5 -0
- data/test/dummy/app/models/something.rb +2 -0
- data/test/dummy/app/views/home/_partial.html.erb +0 -0
- data/test/dummy/app/views/home/index.html.erb +3 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +25 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +41 -0
- data/test/dummy/config/environments/production.rb +79 -0
- data/test/dummy/config/environments/test.rb +42 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +3 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20160120090718_create_somethings.rb +10 -0
- data/test/dummy/db/schema.rb +23 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +294 -0
- data/test/dummy/log/test.log +1672 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +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 +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/DS/DSOLSc6A5RVSmvM415eEWAWG_AgOvZcLZOXQjsXyWQA.cache +2 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/Gy/Gyqn3Ja6WbUSqKnvWm9Xw7FIxFqJIPQ88IlgpguMo1s.cache +1 -0
- 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 +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/K9/K9ZheMi0hi4DNLzmDMRnv9A_lOVz33kNImc16Now42o.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/LH/LHgjtAV8kdldaJ_dX0RCznzjmWYRuLdhU29fZCJ0VmU.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/Nn/NnUCa7jNYx9HCmEB7E7WPWT00DwaM4IYICy1Ju1jjcs.cache +1 -0
- 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 +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/Yr/YrZ0OIHu42cExs1kqngMA6ShVDKhfGmhyW-E9haNo5Y.cache +1 -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 +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/cI/cIaWfk6Nq6ZAr0fhtHGTBtsRITI5n8IJFZbClZ2tExw.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/g3/g3x0V2jnf5A31QMz4xGeQMouu2eChQRpoe0BEWWESeY.cache +1 -0
- 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 +2 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/gp/gpiWtnqpufka8lRtMznM6Ko0aWJrcH_j8cfZwdYmzNI.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/hZ/hZi1k6tpxxCGYxRe7zY74ItcOI8gZrREOpGuA8JSpGg.cache +0 -0
- 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 +1 -0
- 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 +1 -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 +1 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/-Z_pj4kfRj993e_ypawYQUIDIDKcRe569udVq_1drFs.cache +1 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/2G0Z7Q5fvf2xX8ygtwcD9vZq-kwEzoV2MFc1URegs7s.cache +1 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/5Lly_CA8DZvPhQV2jDQx-Y6P_y3Ygra9t5jfSlGhHDA.cache +2 -0
- 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 +2 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/GELqHyWyVR_UvkpZPDb5xjZrCgkKB5G067DYoMwTjEA.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/Gyqn3Ja6WbUSqKnvWm9Xw7FIxFqJIPQ88IlgpguMo1s.cache +1 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/H5fHMceViwaxMKkefsdMmVpBN3rRYZI1obJX5Jn-4jw.cache +1 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/IEJfj4Zwfra6y7iF-BOVR9PPIQeL9L5IiZT8MRqpCXg.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/IordxSS9mOh1mkt2VyfX7Iz4DhZhy73lccOYxcw5aVU.cache +1 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/KgQHhqXCaYHJSJEG6JweQVe1a2rC-mHfkrqD9p9taTU.cache +2 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/Ki_R5uSCGEm1Jn7TSbJOc3eBMn4Q3_IPLG0r_RRn9lA.cache +1 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/NBBjlBjfPdkZkp4G7VCEA9LAeGycMn10CxLbDAbNeHc.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/OI6uxGcnsKavdWTtwDAasU3wPx8QXhzBgV0X2n1KjMQ.cache +2 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/V9m2At1eKJAvbGAFvFTUt8hcdNI-G8xW1AShyPYS4Ys.cache +1 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/XsDQ8X8Klh__7HZNZk8sjYzyFg5TmATqo-_UraArzN8.cache +1 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/ZtbyFLml01tdqcRh4Ocz6XOkbPpmHM6nFRRYY4Nphpc.cache +1 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/_ZNMI9IrCfXNcrwiRGttWiFPcLlCSpkdJSFoLhmUpyg.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/brSVWTme0G1yzUMjrDpklxoQetdFLXdF8ZUkYXFX-sE.cache +1 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/gZp3uXMHuYQC4hzCr7bQfetKNdJAtbQmg3so2KpW1Dw.cache +2 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/hZi1k6tpxxCGYxRe7zY74ItcOI8gZrREOpGuA8JSpGg.cache +2 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/jqyQL40gGhkqnPg3IttXbq8JGHLONBjR0MlrN9HeIvU.cache +1 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/kqQAJDpBuiNJ3XEy8VjtVcyUB9BVlP02oDMdVnlL04w.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/pEhaat2KBd5SrT7szC_8R1_6hK17FTpvoRFkmCRSD3M.cache +2 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/pnW3u_1AN48ig6ngefI89y96xoSlvnJurx-e3J-leoE.cache +2 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/q9kUTJTzJpwJJQ8CoWPFc_eCW76RZgB-R2sc4P84y6c.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/qFlPbNZ3UJs9EnENWVEbNWnrTEcjZkAQUzH55y3Ymi0.cache +1 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/r86oWGkKGjcta2GtxqeESX1w_4FX1c_DWHxPWVKP28A.cache +1 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/ssS2x0Wl67rwXHaVHsh6CO7ayn9fQ5saIwATKN6O-nI.cache +2 -0
- data/test/superlogger_test.rb +134 -0
- data/test/test_helper.rb +19 -0
- metadata +299 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: a8233a0f1140b23ad1a79d954256e9f406e7dbf4
|
|
4
|
+
data.tar.gz: 7fc49063ae14c89e033a224dc619e878401d8f33
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 5bf2ca0272093a2b54928be31590756f57ddb0fb959c0fc4fc37cdd074cdaf51adbc903bfd5d549705708b53269e312afeb20ac04af50dec472ff41e7c4082c8
|
|
7
|
+
data.tar.gz: 1b181052bfb35cc721824dde111d9d87b4aadc0b8605d944b7c1657e0afff478a1b2052c6033b8df04f64f262de53b84744c709c177bed20985f9799ae8cafef
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2016 Soh Yu Ming
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
Superlogger - Machine-readable logging for Rails [](https://travis-ci.org/moexmen/superlogger)
|
|
2
|
+
=======
|
|
3
|
+
|
|
4
|
+
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 key-value pairs for easy parsing and adds useful details like Timestamp and Session ID for tracing purposes.
|
|
5
|
+
|
|
6
|
+
Default rails logging:
|
|
7
|
+
```sh
|
|
8
|
+
Started GET "/home/index" for ::1 at 2016-04-11 16:23:27 +0800
|
|
9
|
+
ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
|
|
10
|
+
Processing by HomeController#index as HTML
|
|
11
|
+
Something Load (0.2ms) SELECT "somethings".* FROM "somethings" WHERE "somethings"."paper" = ? AND "somethings"."stone" = ? ORDER BY "somethings"."id" ASC LIMIT 1 [["paper", "123"], ["stone", "456"]]
|
|
12
|
+
Rendered home/_partial.html.erb (0.2ms)
|
|
13
|
+
Rendered home/index.html.erb within layouts/application (5.2ms)
|
|
14
|
+
Completed 200 OK in 283ms (Views: 271.6ms | ActiveRecord: 0.6ms)
|
|
15
|
+
|
|
16
|
+
Started GET "/assets/application.self-e80e8f2318043e8af94dddc2adad5a4f09739a8ebb323b3ab31cd71d45fd9113.css?body=1" for ::1 at 2016-04-11 16:23:27 +0800
|
|
17
|
+
|
|
18
|
+
Started GET "/assets/application.self-8f06a73c35179188914ab50e057157639fce1401c1cdca640ac9cec33746fc5b.js?body=1" for ::1 at 2016-04-11 16:23:27 +0800
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Machine-readable logging with Superlogger:
|
|
22
|
+
```sh
|
|
23
|
+
2016-04-11 16:18:22.279 | b48534ea049a | I | middleware:28 | method=GET | path=/home/index | ip=::1
|
|
24
|
+
2016-04-11 16:18:22.293 | b48534ea049a | D | action_controller_log_subscriber:9 | controller=HomeController | action=index | params={}
|
|
25
|
+
2016-04-11 16:18:22.305 | b48534ea049a | D | active_record_log_subscriber:24 | sql=SELECT "somethings".* FROM "somethings" WHERE "somethings"."paper" = ? AND "somethings"."stone" = ? ORDER BY "somethings"."id" ASC LIMIT 1 | params=["'123'", "'456'"] | duration=0.48
|
|
26
|
+
2016-04-11 16:18:22.316 | b48534ea049a | D | action_view_log_subscriber:6 | view=_partial.html.erb | duration=0.3
|
|
27
|
+
2016-04-11 16:18:22.316 | b48534ea049a | D | action_view_log_subscriber:6 | view=index.html.erb | duration=5.6
|
|
28
|
+
2016-04-11 16:18:22.541 | b48534ea049a | I | action_controller_log_subscriber:29 | status=200 | total_duration=247.16 | view_duration=235.25 | db_duration=0.78
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Features ##
|
|
32
|
+
- Timestamp (milliseconds)
|
|
33
|
+
- Session ID for logs across requests
|
|
34
|
+
- Key-value pairs for log data
|
|
35
|
+
- Muting of assets logging
|
|
36
|
+
- File and line numbers
|
|
37
|
+
- Recording of IP address
|
|
38
|
+
|
|
39
|
+
## Installation ##
|
|
40
|
+
|
|
41
|
+
Add superlogger to your application's Gemfile
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
gem "superlogger"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
And then execute:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
$ bundle
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Usage ##
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
require 'superlogger'
|
|
57
|
+
|
|
58
|
+
class SomeClass
|
|
59
|
+
include Superlogger
|
|
60
|
+
|
|
61
|
+
def some_method
|
|
62
|
+
Logger.debug name:'john', age: '21'
|
|
63
|
+
Logger.info name:'john', age: '21'
|
|
64
|
+
Logger.warn name:'john', age: '21'
|
|
65
|
+
Logger.error name:'john', age: '21'
|
|
66
|
+
Logger.fatal name:'john', age: '21'
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Output Format ##
|
|
72
|
+
```sh
|
|
73
|
+
2015-03-26 23:37:38.086 | 970298669a40 | I | log_subscriber:24 | status:200 | total:858.35 | view:597.46 | db:34.96
|
|
74
|
+
< timestamp > | < session id > | < severity > | < file >:< line num > | < data you pass in ... >
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Severity Levels ###
|
|
78
|
+
- **D** - Debug
|
|
79
|
+
- **I** - Info
|
|
80
|
+
- **W** - Warn
|
|
81
|
+
- **E** - Error
|
|
82
|
+
- **F** - Fatal
|
data/Rakefile
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
require 'rdoc/task'
|
|
8
|
+
|
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
11
|
+
rdoc.title = 'Superlogger'
|
|
12
|
+
rdoc.options << '--line-numbers'
|
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
Bundler::GemHelper.install_tasks
|
|
23
|
+
|
|
24
|
+
require 'rake/testtask'
|
|
25
|
+
|
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
|
27
|
+
t.libs << 'lib'
|
|
28
|
+
t.libs << 'test'
|
|
29
|
+
t.pattern = 'test/**/*_test.rb'
|
|
30
|
+
t.verbose = false
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
task default: :test
|
data/lib/superlogger.rb
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'superlogger/version'
|
|
2
|
+
require 'superlogger/logger'
|
|
3
|
+
|
|
4
|
+
module Superlogger
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
def setup(app)
|
|
8
|
+
overwrite_rails_rack_logger
|
|
9
|
+
overwrite_action_dispatch_debug_exceptions
|
|
10
|
+
insert_superlogger_middleware(app)
|
|
11
|
+
detach_all_existing_log_subscribers
|
|
12
|
+
attach_superlogger_log_subscribers
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def overwrite_rails_rack_logger
|
|
16
|
+
require 'superlogger/rails_rack_logger'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def overwrite_action_dispatch_debug_exceptions
|
|
20
|
+
require 'superlogger/action_dispatch_debug_exceptions'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def insert_superlogger_middleware(app)
|
|
24
|
+
require 'superlogger/middleware'
|
|
25
|
+
|
|
26
|
+
# important to insert after session middleware so we can get the session id
|
|
27
|
+
app.middleware.use Superlogger::Middleware
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def detach_all_existing_log_subscribers
|
|
31
|
+
# force log subscribers to attach first so we can remove them all
|
|
32
|
+
require 'action_controller/log_subscriber'
|
|
33
|
+
require 'active_record/log_subscriber'
|
|
34
|
+
require 'action_view/log_subscriber'
|
|
35
|
+
require 'action_mailer/log_subscriber'
|
|
36
|
+
|
|
37
|
+
# remove log subscribers
|
|
38
|
+
ActiveSupport::LogSubscriber.log_subscribers.each do |subscriber|
|
|
39
|
+
subscriber.patterns.each do |pattern|
|
|
40
|
+
ActiveSupport::Notifications.unsubscribe pattern
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
ActiveSupport::LogSubscriber.log_subscribers.clear
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def attach_superlogger_log_subscribers
|
|
48
|
+
require 'superlogger/action_controller_log_subscriber'
|
|
49
|
+
require 'superlogger/action_view_log_subscriber'
|
|
50
|
+
require 'superlogger/active_record_log_subscriber'
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
require 'superlogger/railtie' if defined?(Rails)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Superlogger
|
|
2
|
+
class ActionControllerLogSubscriber < ActiveSupport::LogSubscriber
|
|
3
|
+
INTERNAL_PARAMS = %w(controller action format _method only_path)
|
|
4
|
+
|
|
5
|
+
# start of controller action
|
|
6
|
+
def start_processing(event)
|
|
7
|
+
payload = event.payload
|
|
8
|
+
|
|
9
|
+
Logger.debug controller: payload[:controller], action: payload[:action], params: payload[:params].except(*INTERNAL_PARAMS)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# end of controller action
|
|
13
|
+
def process_action(event)
|
|
14
|
+
payload = event.payload
|
|
15
|
+
|
|
16
|
+
if payload[:exception]
|
|
17
|
+
status = ActionDispatch::ExceptionWrapper.status_code_for_exception(payload[:exception][0])
|
|
18
|
+
|
|
19
|
+
Logger.fatal status: status, exception: payload[:exception]
|
|
20
|
+
else
|
|
21
|
+
# Assume status 401 if action finishes without status code and no exception
|
|
22
|
+
# https://github.com/pcg79/devise/commit/1e2dab3c0ce49efe2b5940c15f47388c69d6731b
|
|
23
|
+
payload[:status] ||= 401
|
|
24
|
+
|
|
25
|
+
total_duration = event.duration.to_f.round(2)
|
|
26
|
+
view_duration = payload[:view_runtime].to_f.round(2) if payload.key?(:view_runtime)
|
|
27
|
+
db_duration = payload[:db_runtime].to_f.round(2) if payload.key?(:db_runtime)
|
|
28
|
+
|
|
29
|
+
Logger.info status: payload[:status], total_duration: total_duration, view_duration: view_duration, db_duration: db_duration
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
Superlogger::ActionControllerLogSubscriber.attach_to :action_controller
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class ActionDispatch::DebugExceptions
|
|
2
|
+
alias_method :old_log_error, :log_error
|
|
3
|
+
def log_error(request, wrapper)
|
|
4
|
+
if wrapper.exception.is_a? ActionController::RoutingError
|
|
5
|
+
# Change routing errors to warn instead
|
|
6
|
+
Superlogger::Logger.warn routing_error: request['PATH_INFO'].inspect
|
|
7
|
+
else
|
|
8
|
+
old_log_error request, wrapper
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Superlogger
|
|
2
|
+
class ActionViewLogSubscriber < ActiveSupport::LogSubscriber
|
|
3
|
+
def render_template(event)
|
|
4
|
+
payload = event.payload
|
|
5
|
+
|
|
6
|
+
Logger.debug view: payload[:identifier].split('/').last, duration: event.duration.round(1)
|
|
7
|
+
end
|
|
8
|
+
alias :render_partial :render_template
|
|
9
|
+
alias :render_collection :render_template
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
Superlogger::ActionViewLogSubscriber.attach_to :action_view
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Superlogger
|
|
2
|
+
class ActiveRecordLogSubscriber < ActiveSupport::LogSubscriber
|
|
3
|
+
IGNORE_PAYLOAD_NAMES = ["SCHEMA", "EXPLAIN", "ActiveRecord::SchemaMigration Load"]
|
|
4
|
+
|
|
5
|
+
def self.runtime=(value)
|
|
6
|
+
ActiveRecord::RuntimeRegistry.sql_runtime = value
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.runtime
|
|
10
|
+
ActiveRecord::RuntimeRegistry.sql_runtime ||= 0
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def sql(event)
|
|
14
|
+
self.class.runtime += event.duration
|
|
15
|
+
|
|
16
|
+
return if Rails.env.production?
|
|
17
|
+
|
|
18
|
+
payload = event.payload
|
|
19
|
+
return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
|
|
20
|
+
|
|
21
|
+
sql = payload[:sql]
|
|
22
|
+
params = payload[:binds].map { |_, value| "'#{value}'"}
|
|
23
|
+
|
|
24
|
+
Logger.debug sql: sql, params: params, duration: event.duration.round(2)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
Superlogger::ActiveRecordLogSubscriber.attach_to :active_record
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require 'request_store'
|
|
2
|
+
|
|
3
|
+
module Superlogger
|
|
4
|
+
module Logger
|
|
5
|
+
def self.session_id=(session_id)
|
|
6
|
+
RequestStore.store[:superlogger_session_id] = session_id
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.session_id
|
|
10
|
+
RequestStore.store[:superlogger_session_id] || "NS-#{Thread.current.object_id}"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.debug(*args)
|
|
14
|
+
Rails.logger.debug { format_msg(args) }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.info(*args)
|
|
18
|
+
Rails.logger.info { format_msg(args) }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.warn(*args)
|
|
22
|
+
Rails.logger.warn { format_msg(args) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.error(*args)
|
|
26
|
+
Rails.logger.error { format_msg(args) }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.fatal(*args)
|
|
30
|
+
Rails.logger.fatal { format_msg(args) }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def self.format_msg(args)
|
|
36
|
+
"#{get_caller_location} | #{format_args(args)}"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.get_caller_location
|
|
40
|
+
# Find the last method call on Superlogger::Logger
|
|
41
|
+
count = 0
|
|
42
|
+
location_index = caller_locations(0).find_index do |location|
|
|
43
|
+
count += 1 if location && location.path.include?('superlogger/logger.rb')
|
|
44
|
+
count == 4
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Add 1 to get the caller of the logger
|
|
48
|
+
location = caller_locations(location_index + 1).first
|
|
49
|
+
|
|
50
|
+
# extract filename without file extension from location.path
|
|
51
|
+
# eg. superlogger/lib/superlogger/logger.rb
|
|
52
|
+
file = location.path.split('/').last.split('.').first
|
|
53
|
+
|
|
54
|
+
"#{file}:#{location.lineno}"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def self.format_args(args)
|
|
58
|
+
# format args in key=value pair, separated by pipes
|
|
59
|
+
args.map do |arg|
|
|
60
|
+
arg = {nil: arg} unless arg.is_a?(Hash)
|
|
61
|
+
|
|
62
|
+
arg.map do |key, value|
|
|
63
|
+
"#{key}=#{value}"
|
|
64
|
+
end
|
|
65
|
+
end.flatten.join(' | ')
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# for overriding default Rails Logger format
|
|
71
|
+
class Logger
|
|
72
|
+
def format_message(severity, time, _progname, msg)
|
|
73
|
+
timestamp = time.strftime('%Y-%m-%d %H:%M:%S.%L')
|
|
74
|
+
session_id = Superlogger::Logger.session_id[0..11]
|
|
75
|
+
severity = severity.to_s.upcase[0]
|
|
76
|
+
|
|
77
|
+
"#{timestamp} | #{session_id} | #{severity} | #{msg}\n"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Superlogger
|
|
2
|
+
class Middleware
|
|
3
|
+
def initialize(app)
|
|
4
|
+
@app = app
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def call(env)
|
|
8
|
+
request = ActionDispatch::Request.new(env)
|
|
9
|
+
|
|
10
|
+
# only process the actual request, less the assets
|
|
11
|
+
if request.path.start_with?('/assets/') == false
|
|
12
|
+
process_request(request)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
@app.call(env)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def process_request(request)
|
|
19
|
+
if request.env['rack.session']
|
|
20
|
+
# Session is lazy loaded. Force session to load if it is not already loaded.
|
|
21
|
+
request.env['rack.session'].send(:load!) unless request.env['rack.session'].id
|
|
22
|
+
|
|
23
|
+
# Store session id before any actual logging is done
|
|
24
|
+
Superlogger::Logger.session_id = request.env['rack.session'].id
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Start of request logging
|
|
28
|
+
Logger.info method: request.method, path: request.fullpath, ip: request.ip
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class Rails::Rack::Logger
|
|
2
|
+
# Overwrite the default call_app method to mute the following line:
|
|
3
|
+
# Started GET “/session/new” for 127.0.0.1 at 2012-09-26 14:51:42 -0700
|
|
4
|
+
def call_app(_request, env)
|
|
5
|
+
@app.call(env)
|
|
6
|
+
ensure
|
|
7
|
+
ActiveSupport::LogSubscriber.flush_all!
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
== README
|
|
2
|
+
|
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
|
4
|
+
application up and running.
|
|
5
|
+
|
|
6
|
+
Things you may want to cover:
|
|
7
|
+
|
|
8
|
+
* Ruby version
|
|
9
|
+
|
|
10
|
+
* System dependencies
|
|
11
|
+
|
|
12
|
+
* Configuration
|
|
13
|
+
|
|
14
|
+
* Database creation
|
|
15
|
+
|
|
16
|
+
* Database initialization
|
|
17
|
+
|
|
18
|
+
* How to run the test suite
|
|
19
|
+
|
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
|
21
|
+
|
|
22
|
+
* Deployment instructions
|
|
23
|
+
|
|
24
|
+
* ...
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
|
28
|
+
<tt>rake doc:app</tt>.
|