logster 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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