logster 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.
Files changed (245) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/Guardfile +8 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +38 -0
  7. data/Rakefile +18 -0
  8. data/assets/javascript/app.js +377 -0
  9. data/assets/javascript/external/ember.js +44267 -0
  10. data/assets/javascript/external/ember.min.js +19 -0
  11. data/assets/javascript/external/handlebars.min.js +28 -0
  12. data/assets/javascript/external/jquery.min.js +5 -0
  13. data/assets/javascript/external/lodash.min.js +56 -0
  14. data/assets/javascript/external/moment.min.js +6 -0
  15. data/assets/javascript/templates/application.handlebars +1 -0
  16. data/assets/javascript/templates/index.handlebars +48 -0
  17. data/assets/javascript/templates/message.handlebars +7 -0
  18. data/assets/stylesheets/app.css +188 -0
  19. data/bower_components/ember/.bower.json +22 -0
  20. data/bower_components/ember/.gitignore +5 -0
  21. data/bower_components/ember/Makefile +9 -0
  22. data/bower_components/ember/README.md +12 -0
  23. data/bower_components/ember/bower.json +11 -0
  24. data/bower_components/ember/component.json +13 -0
  25. data/bower_components/ember/composer.json +27 -0
  26. data/bower_components/ember/ember-template-compiler.js +320 -0
  27. data/bower_components/ember/ember.js +44267 -0
  28. data/bower_components/ember/ember.min.js +19 -0
  29. data/bower_components/ember/ember.prod.js +42649 -0
  30. data/bower_components/ember/package.json +11 -0
  31. data/bower_components/handlebars/.bower.json +16 -0
  32. data/bower_components/handlebars/.gitignore +2 -0
  33. data/bower_components/handlebars/README.md +11 -0
  34. data/bower_components/handlebars/bower.json +6 -0
  35. data/bower_components/handlebars/component.json +9 -0
  36. data/bower_components/handlebars/composer.json +35 -0
  37. data/bower_components/handlebars/handlebars-source.gemspec +21 -0
  38. data/bower_components/handlebars/handlebars.amd.js +2719 -0
  39. data/bower_components/handlebars/handlebars.amd.min.js +28 -0
  40. data/bower_components/handlebars/handlebars.js +2746 -0
  41. data/bower_components/handlebars/handlebars.js.nuspec +17 -0
  42. data/bower_components/handlebars/handlebars.min.js +28 -0
  43. data/bower_components/handlebars/handlebars.runtime.amd.js +515 -0
  44. data/bower_components/handlebars/handlebars.runtime.amd.min.js +27 -0
  45. data/bower_components/handlebars/handlebars.runtime.js +530 -0
  46. data/bower_components/handlebars/handlebars.runtime.min.js +27 -0
  47. data/bower_components/handlebars/lib/handlebars/source.rb +11 -0
  48. data/bower_components/jquery/.bower.json +37 -0
  49. data/bower_components/jquery/MIT-LICENSE.txt +21 -0
  50. data/bower_components/jquery/bower.json +27 -0
  51. data/bower_components/jquery/dist/jquery.js +9111 -0
  52. data/bower_components/jquery/dist/jquery.min.js +5 -0
  53. data/bower_components/jquery/dist/jquery.min.map +1 -0
  54. data/bower_components/jquery/src/ajax.js +806 -0
  55. data/bower_components/jquery/src/ajax/jsonp.js +89 -0
  56. data/bower_components/jquery/src/ajax/load.js +75 -0
  57. data/bower_components/jquery/src/ajax/parseJSON.js +13 -0
  58. data/bower_components/jquery/src/ajax/parseXML.js +28 -0
  59. data/bower_components/jquery/src/ajax/script.js +64 -0
  60. data/bower_components/jquery/src/ajax/var/nonce.js +5 -0
  61. data/bower_components/jquery/src/ajax/var/rquery.js +3 -0
  62. data/bower_components/jquery/src/ajax/xhr.js +130 -0
  63. data/bower_components/jquery/src/attributes.js +11 -0
  64. data/bower_components/jquery/src/attributes/attr.js +143 -0
  65. data/bower_components/jquery/src/attributes/classes.js +158 -0
  66. data/bower_components/jquery/src/attributes/prop.js +96 -0
  67. data/bower_components/jquery/src/attributes/support.js +35 -0
  68. data/bower_components/jquery/src/attributes/val.js +153 -0
  69. data/bower_components/jquery/src/callbacks.js +205 -0
  70. data/bower_components/jquery/src/core.js +500 -0
  71. data/bower_components/jquery/src/core/access.js +60 -0
  72. data/bower_components/jquery/src/core/init.js +123 -0
  73. data/bower_components/jquery/src/core/parseHTML.js +39 -0
  74. data/bower_components/jquery/src/core/ready.js +96 -0
  75. data/bower_components/jquery/src/core/var/rsingleTag.js +4 -0
  76. data/bower_components/jquery/src/css.js +455 -0
  77. data/bower_components/jquery/src/css/addGetHookIf.js +24 -0
  78. data/bower_components/jquery/src/css/curCSS.js +57 -0
  79. data/bower_components/jquery/src/css/defaultDisplay.js +69 -0
  80. data/bower_components/jquery/src/css/hiddenVisibleSelectors.js +15 -0
  81. data/bower_components/jquery/src/css/support.js +83 -0
  82. data/bower_components/jquery/src/css/swap.js +28 -0
  83. data/bower_components/jquery/src/css/var/cssExpand.js +3 -0
  84. data/bower_components/jquery/src/css/var/getStyles.js +5 -0
  85. data/bower_components/jquery/src/css/var/isHidden.js +13 -0
  86. data/bower_components/jquery/src/css/var/rmargin.js +3 -0
  87. data/bower_components/jquery/src/css/var/rnumnonpx.js +5 -0
  88. data/bower_components/jquery/src/data.js +175 -0
  89. data/bower_components/jquery/src/data/Data.js +181 -0
  90. data/bower_components/jquery/src/data/accepts.js +20 -0
  91. data/bower_components/jquery/src/data/var/data_priv.js +5 -0
  92. data/bower_components/jquery/src/data/var/data_user.js +5 -0
  93. data/bower_components/jquery/src/deferred.js +149 -0
  94. data/bower_components/jquery/src/deprecated.js +13 -0
  95. data/bower_components/jquery/src/dimensions.js +50 -0
  96. data/bower_components/jquery/src/effects.js +642 -0
  97. data/bower_components/jquery/src/effects/Tween.js +114 -0
  98. data/bower_components/jquery/src/effects/animatedSelector.js +13 -0
  99. data/bower_components/jquery/src/event.js +859 -0
  100. data/bower_components/jquery/src/event/alias.js +39 -0
  101. data/bower_components/jquery/src/event/support.js +9 -0
  102. data/bower_components/jquery/src/exports/amd.js +18 -0
  103. data/bower_components/jquery/src/exports/global.js +32 -0
  104. data/bower_components/jquery/src/intro.js +44 -0
  105. data/bower_components/jquery/src/jquery.js +36 -0
  106. data/bower_components/jquery/src/manipulation.js +583 -0
  107. data/bower_components/jquery/src/manipulation/_evalUrl.js +18 -0
  108. data/bower_components/jquery/src/manipulation/support.js +24 -0
  109. data/bower_components/jquery/src/manipulation/var/rcheckableType.js +3 -0
  110. data/bower_components/jquery/src/offset.js +204 -0
  111. data/bower_components/jquery/src/outro.js +1 -0
  112. data/bower_components/jquery/src/queue.js +142 -0
  113. data/bower_components/jquery/src/queue/delay.js +22 -0
  114. data/bower_components/jquery/src/selector-native.js +171 -0
  115. data/bower_components/jquery/src/selector-sizzle.js +14 -0
  116. data/bower_components/jquery/src/selector.js +1 -0
  117. data/bower_components/jquery/src/serialize.js +111 -0
  118. data/bower_components/jquery/src/sizzle/dist/sizzle.js +2015 -0
  119. data/bower_components/jquery/src/sizzle/dist/sizzle.min.js +3 -0
  120. data/bower_components/jquery/src/sizzle/dist/sizzle.min.map +1 -0
  121. data/bower_components/jquery/src/traversing.js +200 -0
  122. data/bower_components/jquery/src/traversing/findFilter.js +100 -0
  123. data/bower_components/jquery/src/traversing/var/rneedsContext.js +6 -0
  124. data/bower_components/jquery/src/var/arr.js +3 -0
  125. data/bower_components/jquery/src/var/class2type.js +4 -0
  126. data/bower_components/jquery/src/var/concat.js +5 -0
  127. data/bower_components/jquery/src/var/hasOwn.js +5 -0
  128. data/bower_components/jquery/src/var/indexOf.js +5 -0
  129. data/bower_components/jquery/src/var/pnum.js +3 -0
  130. data/bower_components/jquery/src/var/push.js +5 -0
  131. data/bower_components/jquery/src/var/rnotwhite.js +3 -0
  132. data/bower_components/jquery/src/var/slice.js +5 -0
  133. data/bower_components/jquery/src/var/strundefined.js +3 -0
  134. data/bower_components/jquery/src/var/support.js +4 -0
  135. data/bower_components/jquery/src/var/toString.js +5 -0
  136. data/bower_components/jquery/src/var/trim.js +3 -0
  137. data/bower_components/jquery/src/wrap.js +78 -0
  138. data/bower_components/lodash/.bower.json +34 -0
  139. data/bower_components/lodash/LICENSE.txt +22 -0
  140. data/bower_components/lodash/bower.json +23 -0
  141. data/bower_components/lodash/dist/lodash.compat.js +7157 -0
  142. data/bower_components/lodash/dist/lodash.compat.min.js +61 -0
  143. data/bower_components/lodash/dist/lodash.js +6785 -0
  144. data/bower_components/lodash/dist/lodash.min.js +56 -0
  145. data/bower_components/lodash/dist/lodash.underscore.js +4979 -0
  146. data/bower_components/lodash/dist/lodash.underscore.min.js +39 -0
  147. data/bower_components/moment/.bower.json +31 -0
  148. data/bower_components/moment/LICENSE +22 -0
  149. data/bower_components/moment/bower.json +20 -0
  150. data/bower_components/moment/lang/ar-ma.js +56 -0
  151. data/bower_components/moment/lang/ar.js +56 -0
  152. data/bower_components/moment/lang/bg.js +86 -0
  153. data/bower_components/moment/lang/br.js +107 -0
  154. data/bower_components/moment/lang/bs.js +139 -0
  155. data/bower_components/moment/lang/ca.js +66 -0
  156. data/bower_components/moment/lang/cs.js +155 -0
  157. data/bower_components/moment/lang/cv.js +59 -0
  158. data/bower_components/moment/lang/cy.js +77 -0
  159. data/bower_components/moment/lang/da.js +56 -0
  160. data/bower_components/moment/lang/de.js +71 -0
  161. data/bower_components/moment/lang/el.js +79 -0
  162. data/bower_components/moment/lang/en-au.js +62 -0
  163. data/bower_components/moment/lang/en-ca.js +59 -0
  164. data/bower_components/moment/lang/en-gb.js +63 -0
  165. data/bower_components/moment/lang/eo.js +65 -0
  166. data/bower_components/moment/lang/es.js +75 -0
  167. data/bower_components/moment/lang/et.js +76 -0
  168. data/bower_components/moment/lang/eu.js +60 -0
  169. data/bower_components/moment/lang/fa.js +97 -0
  170. data/bower_components/moment/lang/fi.js +103 -0
  171. data/bower_components/moment/lang/fo.js +56 -0
  172. data/bower_components/moment/lang/fr-ca.js +54 -0
  173. data/bower_components/moment/lang/fr.js +58 -0
  174. data/bower_components/moment/lang/gl.js +71 -0
  175. data/bower_components/moment/lang/he.js +77 -0
  176. data/bower_components/moment/lang/hi.js +105 -0
  177. data/bower_components/moment/lang/hr.js +140 -0
  178. data/bower_components/moment/lang/hu.js +105 -0
  179. data/bower_components/moment/lang/hy-am.js +113 -0
  180. data/bower_components/moment/lang/id.js +67 -0
  181. data/bower_components/moment/lang/is.js +124 -0
  182. data/bower_components/moment/lang/it.js +59 -0
  183. data/bower_components/moment/lang/ja.js +58 -0
  184. data/bower_components/moment/lang/ka.js +108 -0
  185. data/bower_components/moment/lang/km.js +55 -0
  186. data/bower_components/moment/lang/ko.js +63 -0
  187. data/bower_components/moment/lang/lb.js +160 -0
  188. data/bower_components/moment/lang/lt.js +118 -0
  189. data/bower_components/moment/lang/lv.js +77 -0
  190. data/bower_components/moment/lang/mk.js +86 -0
  191. data/bower_components/moment/lang/ml.js +64 -0
  192. data/bower_components/moment/lang/mr.js +104 -0
  193. data/bower_components/moment/lang/ms-my.js +66 -0
  194. data/bower_components/moment/lang/nb.js +57 -0
  195. data/bower_components/moment/lang/ne.js +105 -0
  196. data/bower_components/moment/lang/nl.js +67 -0
  197. data/bower_components/moment/lang/nn.js +56 -0
  198. data/bower_components/moment/lang/pl.js +98 -0
  199. data/bower_components/moment/lang/pt-br.js +56 -0
  200. data/bower_components/moment/lang/pt.js +60 -0
  201. data/bower_components/moment/lang/ro.js +72 -0
  202. data/bower_components/moment/lang/ru.js +163 -0
  203. data/bower_components/moment/lang/sk.js +156 -0
  204. data/bower_components/moment/lang/sl.js +144 -0
  205. data/bower_components/moment/lang/sq.js +61 -0
  206. data/bower_components/moment/lang/sr-cyr.js +106 -0
  207. data/bower_components/moment/lang/sr.js +106 -0
  208. data/bower_components/moment/lang/sv.js +63 -0
  209. data/bower_components/moment/lang/ta.js +112 -0
  210. data/bower_components/moment/lang/th.js +58 -0
  211. data/bower_components/moment/lang/tl-ph.js +58 -0
  212. data/bower_components/moment/lang/tr.js +93 -0
  213. data/bower_components/moment/lang/tzm-la.js +55 -0
  214. data/bower_components/moment/lang/tzm.js +55 -0
  215. data/bower_components/moment/lang/uk.js +157 -0
  216. data/bower_components/moment/lang/uz.js +55 -0
  217. data/bower_components/moment/lang/vi.js +62 -0
  218. data/bower_components/moment/lang/zh-cn.js +108 -0
  219. data/bower_components/moment/lang/zh-tw.js +84 -0
  220. data/bower_components/moment/min/langs.js +5991 -0
  221. data/bower_components/moment/min/langs.min.js +3 -0
  222. data/bower_components/moment/min/moment-with-langs.js +7993 -0
  223. data/bower_components/moment/min/moment-with-langs.min.js +9 -0
  224. data/bower_components/moment/min/moment.min.js +6 -0
  225. data/bower_components/moment/moment.js +2489 -0
  226. data/bower_components/moment/readme.md +368 -0
  227. data/lib/logster.rb +9 -0
  228. data/lib/logster/logger.rb +31 -0
  229. data/lib/logster/message.rb +42 -0
  230. data/lib/logster/middleware/reporter.rb +13 -0
  231. data/lib/logster/middleware/viewer.rb +122 -0
  232. data/lib/logster/rails/railtie.rb +39 -0
  233. data/lib/logster/redis_store.rb +124 -0
  234. data/lib/logster/version.rb +3 -0
  235. data/logster.gemspec +30 -0
  236. data/test/logster/middleware/test_viewer.rb +34 -0
  237. data/test/logster/test_redis_store.rb +112 -0
  238. data/test/test_helper.rb +6 -0
  239. data/website/Gemfile +6 -0
  240. data/website/config.ru +2 -0
  241. data/website/data/data.json +1 -0
  242. data/website/docker_container/logster.yml +95 -0
  243. data/website/sample.rb +85 -0
  244. data/website/scripts/persist_logs.rb +13 -0
  245. metadata +375 -0
@@ -0,0 +1,13 @@
1
+ module Logster
2
+ module Middleware
3
+ class Reporter
4
+ def initialize(app, config={})
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ @app.call(env)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,122 @@
1
+ require 'json'
2
+
3
+ module Logster
4
+ module Middleware
5
+ class Viewer
6
+
7
+ PATH_INFO = "PATH_INFO".freeze
8
+
9
+ def initialize(app, config)
10
+ @app = app
11
+ @logs_path = config[:path] || "/logs"
12
+ @path_regex = Regexp.new("(#{@logs_path}$)|(#{@logs_path}(/.*))$")
13
+
14
+ @store = config[:store] or raise ArgumentError.new("store")
15
+
16
+ @assets_path = File.expand_path("../../../../assets", __FILE__)
17
+ @fileserver = Rack::File.new(@assets_path)
18
+ end
19
+
20
+ def call(env)
21
+ path = env[PATH_INFO]
22
+
23
+ if resource = resolve_path(path)
24
+
25
+ if resource =~ /\.js$|\.handlebars$|\.css$/
26
+ env[PATH_INFO] = resource
27
+ @fileserver.call(env)
28
+ elsif resource.start_with?("/messages.json")
29
+ serve_messages(Rack::Request.new(env))
30
+ elsif resource == "/"
31
+ [200, {"Content-Type" => "text/html; charset=utf-8"}, [body(preload_json)]]
32
+ else
33
+ [404, {}, ["Not found"]]
34
+ end
35
+ else
36
+ @app.call(env)
37
+ end
38
+ end
39
+
40
+ protected
41
+
42
+ def serve_messages(req)
43
+ opts = {
44
+ before: req["before"],
45
+ after: req["after"]
46
+ }
47
+
48
+ if(filter = req["filter"])
49
+ filter = filter.split("_").map{|s| s.to_i}
50
+ opts[:severity] = filter
51
+ end
52
+
53
+ payload = {
54
+ messages: @store.latest(opts),
55
+ total: @store.count
56
+ }
57
+
58
+ json = JSON.generate(payload)
59
+ [200, {"Content-Type" => "application/json"}, [json]]
60
+ end
61
+
62
+ def resolve_path(path)
63
+ if path =~ @path_regex
64
+ $3 || "/"
65
+ end
66
+ end
67
+
68
+ def preload_json
69
+ end
70
+
71
+ def css(name, attrs={})
72
+ attrs = attrs.map do |k,v|
73
+ "#{k}='#{v}'"
74
+ end.join(" ")
75
+
76
+ "<link rel='stylesheet' type='text/css' href='#{@logs_path}/stylesheets/#{name}' #{attrs}>"
77
+ end
78
+
79
+ def script(prod, dev=nil)
80
+ name = ENV['DEBUG_JS'] == "1" && dev ? dev : prod
81
+ "<script src='#{@logs_path}/javascript/#{name}'></script>"
82
+ end
83
+
84
+ def handlebars(name)
85
+ val = File.read("#{@assets_path}/javascript/templates/#{name}.handlebars")
86
+ <<JS
87
+ <script>
88
+ Ember.TEMPLATES[#{name.inspect}] = Ember.Handlebars.compile(#{val.inspect});
89
+ </script>
90
+ JS
91
+ end
92
+
93
+ def body(preload)
94
+ <<HTML
95
+ <html>
96
+ <head>
97
+ #{css("app.css")}
98
+ #{script("external/moment.min.js")}
99
+ #{script("external/jquery.min.js")}
100
+ #{script("external/handlebars.min.js")}
101
+ #{script("external/lodash.min.js")}
102
+ #{script("external/ember.min.js", "external/ember.js")}
103
+ #{handlebars("application")}
104
+ #{handlebars("index")}
105
+ #{handlebars("message")}
106
+ <script>
107
+ window.Logger = {
108
+ rootPath: "#{@logs_path}"
109
+ };
110
+ </script>
111
+ </head>
112
+ <body>
113
+ #{script("app.js")}
114
+ </body>
115
+ </html>
116
+ HTML
117
+ end
118
+
119
+ end
120
+ end
121
+
122
+ end
@@ -0,0 +1,39 @@
1
+ module Logster::Rails
2
+
3
+ def self.set_logger(config)
4
+ return unless Rails.env.development?
5
+
6
+ if defined?(Redis)
7
+ require 'logster/middleware/viewer'
8
+ require 'logster/redis_store'
9
+
10
+ store = Logster::RedisStore.new
11
+ logger = Logster::Logger.new(store)
12
+
13
+ ::Rails.logger = config.logger = logger
14
+ else
15
+ Rails.logger.warn "Not loading logster, Redis missing"
16
+ end
17
+ end
18
+
19
+ def self.initialize!(app)
20
+ return unless Rails.env.development?
21
+
22
+ if Logster::Logger === Rails.logger
23
+ app.middleware.use Logster::Middleware::Viewer, store: Rails.logger.store
24
+
25
+ app.config.colorize_logging = false
26
+ end
27
+ end
28
+
29
+ class Railtie < ::Rails::Railtie
30
+
31
+ config.before_initialize do
32
+ Logster::Rails.set_logger(config)
33
+ end
34
+
35
+ initializer "logster.configure_rails_initialization" do |app|
36
+ Logster::Rails.initialize!(app)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,124 @@
1
+ require 'json'
2
+
3
+ module Logster
4
+ class RedisStore
5
+
6
+ attr_accessor :max_backlog, :dedup, :max_retention, :skip_empty
7
+
8
+ def initialize(redis = nil)
9
+ @redis = redis || Redis.new
10
+ @max_backlog = 1000
11
+ @dedup = false
12
+ @max_retention = 60 * 60 * 24 * 7
13
+ @skip_empty = true
14
+ end
15
+
16
+
17
+ def report(severity, progname, message)
18
+ return if (!message || (String === message && message.empty?)) && skip_empty
19
+
20
+ message = Message.new(severity, progname, message)
21
+ @redis.rpush(list_key, message.to_json)
22
+
23
+ # TODO make it atomic
24
+ if @redis.llen(list_key) > @max_backlog
25
+ @redis.lpop(list_key)
26
+ end
27
+
28
+ nil
29
+ end
30
+
31
+ def count
32
+ @redis.llen(list_key)
33
+ end
34
+
35
+ def latest(opts={})
36
+ limit = opts[:limit] || 50
37
+ severity = opts[:severity]
38
+ before = opts[:before]
39
+ after = opts[:after]
40
+ start = -limit
41
+ finish = -1
42
+
43
+ if before || after
44
+ # inefficient may change to sorted list, also timing issues
45
+ found = nil
46
+ find = before || after
47
+
48
+ while !found
49
+ items = @redis.lrange(list_key, start, finish)
50
+
51
+ break unless items && items.length > 0
52
+
53
+ found = items.index do |i|
54
+ Message.from_json(i).key == find
55
+ end
56
+
57
+ if items.length < limit
58
+ found += limit - items.length if found
59
+ break
60
+ end
61
+ break if found
62
+ start -= limit
63
+ finish -= limit
64
+ end
65
+
66
+ if found
67
+ if before
68
+ offset = -(limit - found)
69
+ else
70
+ offset = found + 1
71
+ end
72
+
73
+ start += offset
74
+ finish += offset
75
+
76
+ finish = -1 if finish > -1
77
+ return [] if start > -1
78
+ end
79
+ end
80
+
81
+ results = []
82
+
83
+ direction = after ? 1 : -1
84
+
85
+ begin
86
+ rows = @redis.lrange(list_key, start, finish) || []
87
+
88
+ temp = []
89
+
90
+ rows.each do |s|
91
+ row = Message.from_json(s)
92
+ break if before && before == row.key
93
+ row = nil if severity && !severity.include?(row.severity)
94
+ temp << row if row
95
+ end
96
+
97
+ if direction == -1
98
+ results = temp + results
99
+ else
100
+ results += temp
101
+ end
102
+
103
+ start += limit * direction
104
+ finish += limit * direction
105
+
106
+ finish = -1 if finish > -1
107
+ end while rows.length > 0 && results.length < limit && start < 0
108
+
109
+ results
110
+ end
111
+
112
+ def clear(severities=nil)
113
+ @redis.del(list_key)
114
+ end
115
+
116
+ protected
117
+
118
+
119
+ def list_key
120
+ @list_key ||= "__LOGSTER__LOG"
121
+ end
122
+
123
+ end
124
+ end
@@ -0,0 +1,3 @@
1
+ module Logster
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'logster/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "logster"
8
+ spec.version = Logster::VERSION
9
+ spec.authors = ["UI for viewing logs in Rack"]
10
+ spec.email = ["sam.saffron@gmail.com"]
11
+ spec.summary = %q{UI for viewing logs in Rack}
12
+ spec.description = %q{UI for viewing logs in Rack}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ # NOTE dependency on rack is not explicit, this enables us to use
22
+ # logster outside of rack (for reporting)
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.6"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rack"
27
+ spec.add_development_dependency "redis"
28
+ spec.add_development_dependency "guard"
29
+ spec.add_development_dependency "guard-minitest"
30
+ end
@@ -0,0 +1,34 @@
1
+ require_relative '../../test_helper'
2
+ require 'rack'
3
+ require 'logster/redis_store'
4
+ require 'logster/middleware/viewer'
5
+
6
+ class TestViewer < Minitest::Test
7
+
8
+ def teardown
9
+ end
10
+
11
+ def viewer
12
+ @viewer ||= begin
13
+ store = Logster::RedisStore.new
14
+ Logster::Middleware::Viewer.new(nil, store: store, path: "/logsie")
15
+ end
16
+ end
17
+
18
+ def test_path_resolution
19
+ assert_nil(viewer.send(:resolve_path, "/logs"))
20
+ assert_equal("/",viewer.send(:resolve_path, "/logsie"))
21
+ assert_equal("/",viewer.send(:resolve_path, "/logsie/"))
22
+ assert_equal("/hello/world",viewer.send(:resolve_path, "/logsie/hello/world"))
23
+ end
24
+
25
+ def test_assets
26
+ env = {}
27
+ env["PATH_INFO"] = "/logsie/javascript/external/jquery.min.js"
28
+ env["REQUEST_METHOD"] = "GET"
29
+
30
+ result, = viewer.call(env)
31
+ assert_equal(200, result)
32
+ end
33
+
34
+ end
@@ -0,0 +1,112 @@
1
+ require_relative '../test_helper'
2
+ require 'logster/redis_store'
3
+
4
+ class TestRedisStore < Minitest::Test
5
+
6
+ def setup
7
+ @store = Logster::RedisStore.new(Redis.new)
8
+ @store.clear
9
+ end
10
+
11
+ def teardown
12
+ @store.clear
13
+ end
14
+
15
+ def test_latest
16
+ @store.report(Logger::WARN, "test", "IGNORE")
17
+ @store.report(Logger::WARN, "test", "This is a warning")
18
+ @store.report(Logger::WARN, "test", "This is another warning")
19
+
20
+ latest = @store.latest(limit: 2)
21
+
22
+ assert_equal(2, latest.length)
23
+ assert_equal("This is a warning", latest[0].message)
24
+ assert_equal("This is another warning", latest[1].message)
25
+ assert_equal(Logger::WARN, latest[1].severity)
26
+ assert_equal("test", latest[1].progname)
27
+ assert(!latest[1].key.nil?)
28
+ end
29
+
30
+ def test_latest_after
31
+ 10.times do |i|
32
+ @store.report(Logger::WARN, "test", "A#{i}")
33
+ end
34
+
35
+ message = @store.latest[-1]
36
+
37
+ 3.times do |i|
38
+ @store.report(Logger::WARN, "test", i.to_s)
39
+ end
40
+
41
+ message = @store.latest(after: message.key, limit: 3)[0]
42
+
43
+ assert_equal("0", message.message)
44
+ end
45
+
46
+ def test_latest_before
47
+ 10.times do
48
+ @store.report(Logger::WARN, "test", "A")
49
+ end
50
+ 10.times do
51
+ @store.report(Logger::WARN, "test", "B")
52
+ end
53
+ 10.times do
54
+ @store.report(Logger::WARN, "test", "C")
55
+ end
56
+
57
+ messages = @store.latest(limit: 10)
58
+ assert_equal("C", messages[0].message)
59
+ assert_equal(10, messages.length)
60
+
61
+ messages = @store.latest(limit: 10, before: messages[0].key)
62
+ assert_equal("B", messages[0].message)
63
+ assert_equal(10, messages.length)
64
+
65
+ messages = @store.latest(limit: 10, before: messages[0].key)
66
+ assert_equal("A", messages[0].message)
67
+ assert_equal(10, messages.length)
68
+
69
+ end
70
+
71
+ def test_backlog
72
+ @store.max_backlog = 1
73
+ @store.report(Logger::WARN, "test", "A")
74
+ @store.report(Logger::WARN, "test", "B")
75
+
76
+ latest = @store.latest
77
+
78
+ assert_equal(1, latest.length)
79
+ assert_equal("B", latest[0].message)
80
+ end
81
+
82
+ def test_filter_latest
83
+ @store.report(Logger::INFO, "test", "A")
84
+ @store.report(Logger::WARN, "test", "B")
85
+
86
+ messages = @store.latest
87
+ assert_equal(2, messages.length)
88
+
89
+ messages = @store.latest(after: messages.last.key)
90
+ assert_equal(0, messages.length)
91
+
92
+ 10.times do
93
+ @store.report(Logger::INFO, "test", "A")
94
+ end
95
+ @store.report(Logger::ERROR, "test", "C")
96
+ 10.times do
97
+ @store.report(Logger::INFO, "test", "A")
98
+ end
99
+
100
+ latest = @store.latest(severity: [Logger::ERROR, Logger::WARN], limit: 2)
101
+
102
+ assert_equal(2, latest.length)
103
+ assert_equal("B", latest[0].message)
104
+ assert_equal("C", latest[1].message)
105
+
106
+ @store.report(Logger::ERROR, "test", "E")
107
+ # respects after
108
+ latest = @store.latest(severity: [Logger::ERROR, Logger::WARN], limit: 2, after: latest[1].key)
109
+ assert_equal(1, latest.length);
110
+ end
111
+
112
+ end