nuggets 0.9.9 → 1.0.0

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 (222) hide show
  1. checksums.yaml +4 -4
  2. data/COPYING +663 -0
  3. data/ChangeLog +7 -0
  4. data/README +74 -0
  5. data/Rakefile +50 -0
  6. data/lib/nuggets.rb +73 -0
  7. data/lib/nuggets/all.rb +35 -0
  8. data/lib/nuggets/all_mixins.rb +33 -0
  9. data/lib/nuggets/ansicolor2css.rb +124 -0
  10. data/lib/nuggets/argv/option.rb +3 -0
  11. data/lib/nuggets/argv/option_mixin.rb +84 -0
  12. data/lib/nuggets/array/boost.rb +5 -0
  13. data/lib/nuggets/array/boost_mixin.rb +77 -0
  14. data/lib/nuggets/array/combination.rb +62 -0
  15. data/lib/nuggets/array/correlation.rb +5 -0
  16. data/lib/nuggets/array/correlation_mixin.rb +63 -0
  17. data/lib/nuggets/array/flatten_once.rb +56 -0
  18. data/lib/nuggets/array/flush.rb +5 -0
  19. data/lib/nuggets/array/flush_mixin.rb +46 -0
  20. data/lib/nuggets/array/format.rb +65 -0
  21. data/lib/nuggets/array/hashify.rb +5 -0
  22. data/lib/nuggets/array/hashify_mixin.rb +47 -0
  23. data/lib/nuggets/array/histogram.rb +5 -0
  24. data/lib/nuggets/array/histogram_mixin.rb +169 -0
  25. data/lib/nuggets/array/in_order.rb +50 -0
  26. data/lib/nuggets/array/limit.rb +5 -0
  27. data/lib/nuggets/array/limit_mixin.rb +56 -0
  28. data/lib/nuggets/array/mean.rb +5 -0
  29. data/lib/nuggets/array/mean_mixin.rb +202 -0
  30. data/lib/nuggets/array/median.rb +5 -0
  31. data/lib/nuggets/array/median_mixin.rb +73 -0
  32. data/lib/nuggets/array/mode.rb +5 -0
  33. data/lib/nuggets/array/mode_mixin.rb +69 -0
  34. data/lib/nuggets/array/monotone.rb +83 -0
  35. data/lib/nuggets/array/only.rb +41 -0
  36. data/lib/nuggets/array/rand.rb +44 -0
  37. data/lib/nuggets/array/regression.rb +5 -0
  38. data/lib/nuggets/array/regression_mixin.rb +149 -0
  39. data/lib/nuggets/array/runiq.rb +5 -0
  40. data/lib/nuggets/array/runiq_mixin.rb +52 -0
  41. data/lib/nuggets/array/shuffle.rb +132 -0
  42. data/lib/nuggets/array/standard_deviation.rb +5 -0
  43. data/lib/nuggets/array/standard_deviation_mixin.rb +50 -0
  44. data/lib/nuggets/array/to_hash.rb +64 -0
  45. data/lib/nuggets/array/variance.rb +5 -0
  46. data/lib/nuggets/array/variance_mixin.rb +81 -0
  47. data/lib/nuggets/content_type.rb +97 -0
  48. data/lib/nuggets/dotted_decimal.rb +59 -0
  49. data/lib/nuggets/enumerable/agrep.rb +79 -0
  50. data/lib/nuggets/enumerable/all_any_extended.rb +66 -0
  51. data/lib/nuggets/enumerable/minmax.rb +102 -0
  52. data/lib/nuggets/env/set.rb +3 -0
  53. data/lib/nuggets/env/set_mixin.rb +67 -0
  54. data/lib/nuggets/env/user_encoding.rb +3 -0
  55. data/lib/nuggets/env/user_encoding_mixin.rb +54 -0
  56. data/lib/nuggets/env/user_home.rb +3 -0
  57. data/lib/nuggets/env/user_home_mixin.rb +56 -0
  58. data/lib/nuggets/file/ext.rb +5 -0
  59. data/lib/nuggets/file/ext_mixin.rb +87 -0
  60. data/lib/nuggets/file/replace.rb +5 -0
  61. data/lib/nuggets/file/replace_mixin.rb +55 -0
  62. data/lib/nuggets/file/sub.rb +5 -0
  63. data/lib/nuggets/file/sub_mixin.rb +95 -0
  64. data/lib/nuggets/file/which.rb +5 -0
  65. data/lib/nuggets/file/which_mixin.rb +72 -0
  66. data/lib/nuggets/hash/at.rb +68 -0
  67. data/lib/nuggets/hash/deep_fetch.rb +5 -0
  68. data/lib/nuggets/hash/deep_fetch_mixin.rb +74 -0
  69. data/lib/nuggets/hash/deep_merge.rb +5 -0
  70. data/lib/nuggets/hash/deep_merge_mixin.rb +53 -0
  71. data/lib/nuggets/hash/idmap.rb +5 -0
  72. data/lib/nuggets/hash/idmap_mixin.rb +41 -0
  73. data/lib/nuggets/hash/in_order.rb +43 -0
  74. data/lib/nuggets/hash/insert.rb +53 -0
  75. data/lib/nuggets/hash/nest.rb +5 -0
  76. data/lib/nuggets/hash/nest_mixin.rb +78 -0
  77. data/lib/nuggets/hash/only.rb +52 -0
  78. data/lib/nuggets/hash/seen.rb +5 -0
  79. data/lib/nuggets/hash/seen_mixin.rb +58 -0
  80. data/lib/nuggets/hash/unroll.rb +5 -0
  81. data/lib/nuggets/hash/unroll_mixin.rb +88 -0
  82. data/lib/nuggets/hash/zip.rb +5 -0
  83. data/lib/nuggets/hash/zip_mixin.rb +159 -0
  84. data/lib/nuggets/i18n.rb +155 -0
  85. data/lib/nuggets/integer/factorial.rb +56 -0
  86. data/lib/nuggets/integer/length.rb +5 -0
  87. data/lib/nuggets/integer/length_mixin.rb +49 -0
  88. data/lib/nuggets/integer/map.rb +5 -0
  89. data/lib/nuggets/integer/map_mixin.rb +42 -0
  90. data/lib/nuggets/integer/to_binary_s.rb +38 -0
  91. data/lib/nuggets/io/agrep.rb +43 -0
  92. data/lib/nuggets/io/interact.rb +5 -0
  93. data/lib/nuggets/io/interact_mixin.rb +159 -0
  94. data/lib/nuggets/io/modes.rb +121 -0
  95. data/lib/nuggets/io/null.rb +5 -0
  96. data/lib/nuggets/io/null_mixin.rb +40 -0
  97. data/lib/nuggets/io/redirect.rb +5 -0
  98. data/lib/nuggets/io/redirect_mixin.rb +50 -0
  99. data/lib/nuggets/lazy_attr.rb +44 -0
  100. data/lib/nuggets/log_parser.rb +70 -0
  101. data/lib/nuggets/log_parser/apache.rb +101 -0
  102. data/lib/nuggets/log_parser/rails.rb +219 -0
  103. data/lib/nuggets/net/success.rb +59 -0
  104. data/lib/nuggets/numeric/between.rb +2 -0
  105. data/lib/nuggets/numeric/duration.rb +100 -0
  106. data/lib/nuggets/numeric/limit.rb +62 -0
  107. data/lib/nuggets/numeric/signum.rb +52 -0
  108. data/lib/nuggets/numeric/to_multiple.rb +61 -0
  109. data/lib/nuggets/object/blank.rb +20 -0
  110. data/lib/nuggets/object/blank_mixin.rb +99 -0
  111. data/lib/nuggets/object/boolean.rb +5 -0
  112. data/lib/nuggets/object/boolean_mixin.rb +61 -0
  113. data/lib/nuggets/object/eigenclass.rb +2 -0
  114. data/lib/nuggets/object/ghost_class.rb +2 -0
  115. data/lib/nuggets/object/metaclass.rb +2 -0
  116. data/lib/nuggets/object/msend.rb +5 -0
  117. data/lib/nuggets/object/msend_mixin.rb +43 -0
  118. data/lib/nuggets/object/silence.rb +5 -0
  119. data/lib/nuggets/object/silence_mixin.rb +44 -0
  120. data/lib/nuggets/object/singleton_class.rb +5 -0
  121. data/lib/nuggets/object/singleton_class_mixin.rb +95 -0
  122. data/lib/nuggets/object/uniclass.rb +2 -0
  123. data/lib/nuggets/object/virtual_class.rb +2 -0
  124. data/lib/nuggets/pluggable.rb +91 -0
  125. data/lib/nuggets/proc/bind.rb +5 -0
  126. data/lib/nuggets/proc/bind_mixin.rb +51 -0
  127. data/lib/nuggets/range/quantile.rb +5 -0
  128. data/lib/nuggets/range/quantile_mixin.rb +42 -0
  129. data/lib/nuggets/ruby.rb +235 -0
  130. data/lib/nuggets/statistics.rb +12 -0
  131. data/lib/nuggets/statistics_mixins.rb +12 -0
  132. data/lib/nuggets/string/camelscore.rb +5 -0
  133. data/lib/nuggets/string/camelscore_mixin.rb +116 -0
  134. data/lib/nuggets/string/capitalize_first.rb +46 -0
  135. data/lib/nuggets/string/case.rb +81 -0
  136. data/lib/nuggets/string/evaluate.rb +5 -0
  137. data/lib/nuggets/string/evaluate_mixin.rb +47 -0
  138. data/lib/nuggets/string/msub.rb +84 -0
  139. data/lib/nuggets/string/nsub.rb +65 -0
  140. data/lib/nuggets/string/sub_with_md.rb +111 -0
  141. data/lib/nuggets/string/wc.rb +5 -0
  142. data/lib/nuggets/string/wc_mixin.rb +95 -0
  143. data/lib/nuggets/string/word_wrap.rb +76 -0
  144. data/lib/nuggets/string/xor.rb +5 -0
  145. data/lib/nuggets/string/xor_mixin.rb +59 -0
  146. data/lib/nuggets/tempfile/open.rb +57 -0
  147. data/lib/nuggets/uri/content_type.rb +5 -0
  148. data/lib/nuggets/uri/content_type_mixin.rb +47 -0
  149. data/lib/nuggets/uri/exist.rb +5 -0
  150. data/lib/nuggets/uri/exist_mixin.rb +56 -0
  151. data/lib/nuggets/uri/redirect.rb +5 -0
  152. data/lib/nuggets/uri/redirect_mixin.rb +101 -0
  153. data/lib/nuggets/version.rb +27 -0
  154. data/spec/nuggets/array/boost_spec.rb +50 -0
  155. data/spec/nuggets/array/combination_spec.rb +25 -0
  156. data/spec/nuggets/array/correlation_spec.rb +81 -0
  157. data/spec/nuggets/array/flatten_once_spec.rb +16 -0
  158. data/spec/nuggets/array/flush_spec.rb +43 -0
  159. data/spec/nuggets/array/format_spec.rb +52 -0
  160. data/spec/nuggets/array/hashify_spec.rb +41 -0
  161. data/spec/nuggets/array/histogram_spec.rb +87 -0
  162. data/spec/nuggets/array/in_order_spec.rb +13 -0
  163. data/spec/nuggets/array/limit_spec.rb +62 -0
  164. data/spec/nuggets/array/mean_spec.rb +203 -0
  165. data/spec/nuggets/array/median_spec.rb +77 -0
  166. data/spec/nuggets/array/mode_spec.rb +57 -0
  167. data/spec/nuggets/array/monotone_spec.rb +30 -0
  168. data/spec/nuggets/array/only_spec.rb +26 -0
  169. data/spec/nuggets/array/regression_spec.rb +54 -0
  170. data/spec/nuggets/array/runiq_spec.rb +25 -0
  171. data/spec/nuggets/array/standard_deviation_spec.rb +33 -0
  172. data/spec/nuggets/array/to_hash_spec.rb +28 -0
  173. data/spec/nuggets/array/variance_spec.rb +106 -0
  174. data/spec/nuggets/dotted_decimal_spec.rb +27 -0
  175. data/spec/nuggets/enumerable/all_any_extended_spec.rb +31 -0
  176. data/spec/nuggets/enumerable/minmax_spec.rb +21 -0
  177. data/spec/nuggets/env/set_spec.rb +29 -0
  178. data/spec/nuggets/env/user_encoding_spec.rb +38 -0
  179. data/spec/nuggets/env/user_home_spec.rb +42 -0
  180. data/spec/nuggets/file/ext_spec.rb +38 -0
  181. data/spec/nuggets/file/replace_spec.rb +95 -0
  182. data/spec/nuggets/file/sub_spec.rb +149 -0
  183. data/spec/nuggets/file/which_spec.rb +22 -0
  184. data/spec/nuggets/hash/at_spec.rb +19 -0
  185. data/spec/nuggets/hash/deep_fetch_spec.rb +159 -0
  186. data/spec/nuggets/hash/deep_merge_spec.rb +78 -0
  187. data/spec/nuggets/hash/in_order_spec.rb +12 -0
  188. data/spec/nuggets/hash/insert_spec.rb +13 -0
  189. data/spec/nuggets/hash/nest_spec.rb +102 -0
  190. data/spec/nuggets/hash/only_spec.rb +29 -0
  191. data/spec/nuggets/hash/seen_spec.rb +36 -0
  192. data/spec/nuggets/hash/unroll_spec.rb +68 -0
  193. data/spec/nuggets/i18n_spec.rb +13 -0
  194. data/spec/nuggets/integer/factorial_spec.rb +10 -0
  195. data/spec/nuggets/integer/length_spec.rb +18 -0
  196. data/spec/nuggets/integer/map_spec.rb +19 -0
  197. data/spec/nuggets/integer/to_binary_s_spec.rb +19 -0
  198. data/spec/nuggets/numeric/duration_spec.rb +25 -0
  199. data/spec/nuggets/numeric/limit_spec.rb +16 -0
  200. data/spec/nuggets/numeric/signum_spec.rb +16 -0
  201. data/spec/nuggets/numeric/to_multiple_spec.rb +16 -0
  202. data/spec/nuggets/object/blank_spec.rb +34 -0
  203. data/spec/nuggets/object/boolean_spec.rb +23 -0
  204. data/spec/nuggets/object/msend_spec.rb +25 -0
  205. data/spec/nuggets/object/silence_spec.rb +36 -0
  206. data/spec/nuggets/object/singleton_class_spec.rb +51 -0
  207. data/spec/nuggets/proc/bind_spec.rb +28 -0
  208. data/spec/nuggets/range/quantile_spec.rb +33 -0
  209. data/spec/nuggets/string/camelscore_spec.rb +114 -0
  210. data/spec/nuggets/string/capitalize_first_spec.rb +13 -0
  211. data/spec/nuggets/string/case_spec.rb +31 -0
  212. data/spec/nuggets/string/evaluate_spec.rb +24 -0
  213. data/spec/nuggets/string/msub_spec.rb +20 -0
  214. data/spec/nuggets/string/nsub_spec.rb +13 -0
  215. data/spec/nuggets/string/sub_with_md_spec.rb +25 -0
  216. data/spec/nuggets/string/wc_spec.rb +73 -0
  217. data/spec/nuggets/string/word_wrap_spec.rb +81 -0
  218. data/spec/nuggets/string/xor_spec.rb +57 -0
  219. data/spec/nuggets/uri/content_type_spec.rb +42 -0
  220. data/spec/nuggets/uri/exist_spec.rb +49 -0
  221. data/spec/spec_helper.rb +36 -0
  222. metadata +309 -17
@@ -0,0 +1,5 @@
1
+ require 'nuggets/io/null_mixin'
2
+
3
+ class IO
4
+ include Nuggets::IO::NullMixin
5
+ end
@@ -0,0 +1,40 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # nuggets -- Extending Ruby #
5
+ # #
6
+ # Copyright (C) 2007-2011 Jens Wille #
7
+ # #
8
+ # Authors: #
9
+ # Jens Wille <jens.wille@gmail.com> #
10
+ # #
11
+ # nuggets is free software; you can redistribute it and/or modify it under #
12
+ # the terms of the GNU Affero General Public License as published by the Free #
13
+ # Software Foundation; either version 3 of the License, or (at your option) #
14
+ # any later version. #
15
+ # #
16
+ # nuggets is distributed in the hope that it will be useful, but WITHOUT ANY #
17
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
18
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
19
+ # more details. #
20
+ # #
21
+ # You should have received a copy of the GNU Affero General Public License #
22
+ # along with nuggets. If not, see <http://www.gnu.org/licenses/>. #
23
+ # #
24
+ ###############################################################################
25
+ #++
26
+
27
+ module Nuggets
28
+ class IO
29
+ module NullMixin
30
+
31
+ NULL = case ::RUBY_PLATFORM
32
+ when /mswin|mingw/i then 'NUL'
33
+ when /openvms/i then 'NL:'
34
+ when /amiga/i then 'NIL:'
35
+ else '/dev/null'
36
+ end.freeze
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,5 @@
1
+ require 'nuggets/io/redirect_mixin'
2
+
3
+ class IO
4
+ include Nuggets::IO::RedirectMixin
5
+ end
@@ -0,0 +1,50 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # nuggets -- Extending Ruby #
5
+ # #
6
+ # Copyright (C) 2007-2012 Jens Wille #
7
+ # #
8
+ # Authors: #
9
+ # Jens Wille <jens.wille@gmail.com> #
10
+ # #
11
+ # nuggets is free software; you can redistribute it and/or modify it under #
12
+ # the terms of the GNU Affero General Public License as published by the Free #
13
+ # Software Foundation; either version 3 of the License, or (at your option) #
14
+ # any later version. #
15
+ # #
16
+ # nuggets is distributed in the hope that it will be useful, but WITHOUT ANY #
17
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
18
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
19
+ # more details. #
20
+ # #
21
+ # You should have received a copy of the GNU Affero General Public License #
22
+ # along with nuggets. If not, see <http://www.gnu.org/licenses/>. #
23
+ # #
24
+ ###############################################################################
25
+ #++
26
+
27
+ require 'nuggets/io/null_mixin'
28
+
29
+ module Nuggets
30
+ class IO
31
+ module RedirectMixin
32
+
33
+ def redirect(target = NullMixin::NULL, mode = 'w')
34
+ unless target.is_a?(self.class)
35
+ target = ::File.open(target, mode)
36
+ close_target = true
37
+ end
38
+
39
+ prev = dup
40
+ reopen(target)
41
+
42
+ yield
43
+ ensure
44
+ reopen(prev) if prev
45
+ target.close if close_target
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,44 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # nuggets -- Extending Ruby #
5
+ # #
6
+ # Copyright (C) 2007-2012 Jens Wille #
7
+ # #
8
+ # Authors: #
9
+ # Jens Wille <jens.wille@gmail.com> #
10
+ # #
11
+ # nuggets is free software; you can redistribute it and/or modify it under #
12
+ # the terms of the GNU Affero General Public License as published by the Free #
13
+ # Software Foundation; either version 3 of the License, or (at your option) #
14
+ # any later version. #
15
+ # #
16
+ # nuggets is distributed in the hope that it will be useful, but WITHOUT ANY #
17
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
18
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
19
+ # more details. #
20
+ # #
21
+ # You should have received a copy of the GNU Affero General Public License #
22
+ # along with nuggets. If not, see <http://www.gnu.org/licenses/>. #
23
+ # #
24
+ ###############################################################################
25
+ #++
26
+
27
+ module Nuggets
28
+
29
+ module LazyAttr
30
+
31
+ private
32
+
33
+ def lazy_attr(attr, freeze = true)
34
+ class << self; self; end.class_eval { attr_reader attr }
35
+
36
+ value = instance_variable_get(name = "@#{attr}") ||
37
+ instance_variable_set(name, yield)
38
+
39
+ freeze ? value.freeze : value
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,70 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # nuggets -- Extending Ruby #
5
+ # #
6
+ # Copyright (C) 2007-2012 Jens Wille #
7
+ # #
8
+ # Authors: #
9
+ # Jens Wille <jens.wille@gmail.com> #
10
+ # #
11
+ # nuggets is free software; you can redistribute it and/or modify it under #
12
+ # the terms of the GNU Affero General Public License as published by the Free #
13
+ # Software Foundation; either version 3 of the License, or (at your option) #
14
+ # any later version. #
15
+ # #
16
+ # nuggets is distributed in the hope that it will be useful, but WITHOUT ANY #
17
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
18
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
19
+ # more details. #
20
+ # #
21
+ # You should have received a copy of the GNU Affero General Public License #
22
+ # along with nuggets. If not, see <http://www.gnu.org/licenses/>. #
23
+ # #
24
+ ###############################################################################
25
+ #++
26
+
27
+ require 'zlib'
28
+
29
+ module Nuggets
30
+ module LogParser
31
+
32
+ extend self
33
+
34
+ GZ_EXT_RE = %r{\.gz\z}
35
+
36
+ def self.register(base, *modules)
37
+ base.send(:include, *modules << self)
38
+ base.extend(base)
39
+ end
40
+
41
+ def parse(input)
42
+ entry = {}
43
+
44
+ input.each { |line| parse_line(line, entry) {
45
+ unless entry.empty?
46
+ yield entry.dup
47
+ entry.clear
48
+ end
49
+ } }
50
+
51
+ yield entry unless entry.empty?
52
+ end
53
+
54
+ def parse_line(line, entry = {})
55
+ # Yield when entry complete. Preferrably return +entry+.
56
+ raise NotImplementedError, 'must be implemented by type'
57
+ end
58
+
59
+ def parse_file(file, &block)
60
+ block ||= (entries = []; lambda { |entry| entries << entry })
61
+
62
+ (file =~ GZ_EXT_RE ? Zlib::GzipReader : ::File).open(file) { |f|
63
+ block.arity == 1 ? parse(f, &block) : block[f, method(:parse)]
64
+ }
65
+
66
+ entries
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,101 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # nuggets -- Extending Ruby #
5
+ # #
6
+ # Copyright (C) 2007-2012 Jens Wille #
7
+ # #
8
+ # Authors: #
9
+ # Jens Wille <jens.wille@gmail.com> #
10
+ # #
11
+ # nuggets is free software; you can redistribute it and/or modify it under #
12
+ # the terms of the GNU Affero General Public License as published by the Free #
13
+ # Software Foundation; either version 3 of the License, or (at your option) #
14
+ # any later version. #
15
+ # #
16
+ # nuggets is distributed in the hope that it will be useful, but WITHOUT ANY #
17
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
18
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
19
+ # more details. #
20
+ # #
21
+ # You should have received a copy of the GNU Affero General Public License #
22
+ # along with nuggets. If not, see <http://www.gnu.org/licenses/>. #
23
+ # #
24
+ ###############################################################################
25
+ #++
26
+
27
+ require 'nuggets/log_parser'
28
+
29
+ module Nuggets
30
+ module LogParser
31
+ module Apache
32
+
33
+ extend self
34
+
35
+ DEFAULT_RE = %r{(.*?)}
36
+
37
+ DIRECTIVES = {
38
+ 'h' => [:ip, %r{(\d+(?:\.\d+){3}|[\w.-]+)}],
39
+ 'l' => [:auth, DEFAULT_RE],
40
+ 'u' => [:username, DEFAULT_RE],
41
+ 't' => [:datetime, %r{\[(.*?)\]}],
42
+ 'r' => [:request, DEFAULT_RE],
43
+ 'R' => [:request, %r{(.*?)(?:"|\z)}],
44
+ 's' => [:status, %r{(\d+)}],
45
+ 'b' => [:bytecount, %r{(-|\d+)}],
46
+ 'v' => [:domain, DEFAULT_RE],
47
+ 'i' => [nil, DEFAULT_RE],
48
+ }
49
+
50
+ DIRECTIVES_RE = %r{%.*?(?:\{(.*?)\})?([#{DIRECTIVES.keys.join}])([\s\\"]*)}
51
+
52
+ ORDER = []
53
+
54
+ class << self
55
+
56
+ def register(name, format)
57
+ base = const_set(name, Module.new)
58
+
59
+ re, items = parse_format(format)
60
+ base.const_set(:RE, re)
61
+ base.const_set(:ITEMS, items)
62
+
63
+ ORDER << base
64
+ LogParser.register(base, self)
65
+ end
66
+
67
+ def parse_format(format)
68
+ re, items = '\A', []
69
+
70
+ format.scan(DIRECTIVES_RE) { |h, c, e|
71
+ i, r = DIRECTIVES[c]
72
+ re << r.source << e.gsub(/\s/, '\\s')
73
+ items << i ||= h.downcase.tr('-', '_').to_sym
74
+ }
75
+
76
+ [Regexp.new(re), items]
77
+ end
78
+
79
+ def detect_type(line)
80
+ ORDER.find { |type| line =~ type::RE }
81
+ end
82
+
83
+ end
84
+
85
+ [ [:Combined, '%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-agent}i"'],
86
+ [:Common, '%h %l %u %t "%r" %>s %b'],
87
+ [:Minimal, '%h %l %u %t "%R']
88
+ ].each { |name, format| register(name, format) }
89
+
90
+ def parse_line(line, entry = {})
91
+ if md = self::RE.match(line)
92
+ self::ITEMS.each_with_index { |k, i| entry[k] = md[i + 1] }
93
+ yield if block_given?
94
+ end
95
+
96
+ entry
97
+ end
98
+
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,219 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # nuggets -- Extending Ruby #
5
+ # #
6
+ # Copyright (C) 2007-2012 Jens Wille #
7
+ # #
8
+ # Authors: #
9
+ # Jens Wille <jens.wille@gmail.com> #
10
+ # #
11
+ # nuggets is free software; you can redistribute it and/or modify it under #
12
+ # the terms of the GNU Affero General Public License as published by the Free #
13
+ # Software Foundation; either version 3 of the License, or (at your option) #
14
+ # any later version. #
15
+ # #
16
+ # nuggets is distributed in the hope that it will be useful, but WITHOUT ANY #
17
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
18
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
19
+ # more details. #
20
+ # #
21
+ # You should have received a copy of the GNU Affero General Public License #
22
+ # along with nuggets. If not, see <http://www.gnu.org/licenses/>. #
23
+ # #
24
+ ###############################################################################
25
+ #++
26
+
27
+ require 'nuggets/log_parser'
28
+
29
+ module Nuggets
30
+ module LogParser
31
+ module Rails
32
+
33
+ LogParser.register(self)
34
+
35
+ # Log line prefix
36
+ PREFIX_RE = %r{
37
+ \A
38
+ (?:
39
+ \[
40
+ (\d+) # pid
41
+ :
42
+ (.*?) # host
43
+ \]
44
+ \s
45
+ )?
46
+ \s*
47
+ }x
48
+
49
+ # Log entry separator
50
+ SEPARATOR_RE = %r{
51
+ \s+\|\s+
52
+ }x
53
+
54
+ # Log line patterns
55
+ ITEMS = [
56
+ [:processing, {
57
+ :re => %r{
58
+ #{PREFIX_RE} # pid, host
59
+ Processing\s+
60
+ (\w+) # controller
61
+ \#
62
+ (\w+) # action
63
+ \s+
64
+ \(
65
+ for\s+
66
+ (.*?) # ip
67
+ \s+at\s+
68
+ (.*?) # datetime
69
+ \)
70
+ \s+
71
+ \[
72
+ (\w+) # request_method
73
+ \]
74
+ }xo,
75
+ :keys => [:controller, :action, :ip, :datetime, :request_method]
76
+ }],
77
+ [:session_id, {
78
+ :re => %r{
79
+ #{PREFIX_RE} # pid, host
80
+ Session\sID:\s+
81
+ (\S+) # sid
82
+ }xo,
83
+ :keys => [:sid]
84
+ }],
85
+ [:parameters, {
86
+ :re => %r{
87
+ #{PREFIX_RE} # pid, host
88
+ Parameters:\s+
89
+ (\{.*\}) # params
90
+ }xo, #}
91
+ :proc => lambda { |entry, md|
92
+ entry[:params_hash] = md[3].hash
93
+ entry[:params] = begin
94
+ eval("$SAFE = 3\n#{md[3].gsub(/#<.*?>/, '%q{\&}')}", nil, __FILE__, __LINE__) # !!!
95
+ rescue SyntaxError, SecurityError
96
+ {}
97
+ end
98
+ }
99
+ }],
100
+ [:client_info, {
101
+ :re => %r{
102
+ #{PREFIX_RE} # pid, host
103
+ Client\sinfo:\s+
104
+ UA\s+=\s+
105
+ (.*?) # user_agent
106
+ #{SEPARATOR_RE}
107
+ LANG\s+=\s+
108
+ (.*) # accept_language
109
+ }xo,
110
+ :keys => [:user_agent, :accept_language]
111
+ }],
112
+ [:referer, {
113
+ :re => %r{
114
+ #{PREFIX_RE} # pid, host
115
+ Referer:\s+
116
+ (.*) # referer
117
+ }xo,
118
+ :keys => [:referer]
119
+ }],
120
+ [:meta, {
121
+ :re => %r{
122
+ #{PREFIX_RE} # pid, host
123
+ Meta:\s+
124
+ User\s+=\s+
125
+ (.*?) # user_id
126
+ #{SEPARATOR_RE}
127
+ Institution\s+=\s+
128
+ (.*) # institution_id
129
+ }xo,
130
+ :keys => [:user_id, :institution_id]
131
+ }],
132
+ [:stats, {
133
+ :re => %r{
134
+ #{PREFIX_RE} # pid, host
135
+ Stats:\s+
136
+ (.*) # flags
137
+ }xo,
138
+ :proc => lambda { |entry, md|
139
+ entry[:flags] = md[3].split(SEPARATOR_RE)
140
+ }
141
+ }],
142
+ [:oauth, {
143
+ :re => %r{
144
+ #{PREFIX_RE} # pid, host
145
+ OAuth:\s+
146
+ Token\s+=\s+
147
+ (.*?)#(.*?) # token_type, token
148
+ #{SEPARATOR_RE}
149
+ User\s+=\s+
150
+ (.*?) # user_id
151
+ #{SEPARATOR_RE}
152
+ Client\s+=\s+
153
+ (.*) # client_id
154
+ }xo,
155
+ :keys => [:token_type, :token, :user_id, :client_id]
156
+ }],
157
+ [:benchmark, {
158
+ :re => %r{
159
+ #{PREFIX_RE} # pid, host
160
+ Completed\sin\s+
161
+ (\S+) # runtime
162
+ .*?
163
+ (?: #- OPTIONAL
164
+ #{SEPARATOR_RE}
165
+ Rendering:\s+
166
+ (\S+) # rendering_runtime
167
+ .*?
168
+ )?
169
+ (?: #- OPTIONAL
170
+ #{SEPARATOR_RE}
171
+ DB:\s+
172
+ (\S+) # db_runtime
173
+ .*?
174
+ )?
175
+ (?: #- OPTIONAL
176
+ #{SEPARATOR_RE}
177
+ Mem:\s+
178
+ \S+
179
+ .*?
180
+ )?
181
+ #{SEPARATOR_RE}
182
+ (.*?) # status
183
+ \s+
184
+ \[
185
+ (.*) # request_uri
186
+ \]
187
+ }xo,
188
+ :keys => [:runtime, :rendering_runtime, :db_runtime, :status, :request_uri]
189
+ }]
190
+ ]
191
+
192
+ ITEMS.each { |_, item|
193
+ item[:proc] ||= lambda { |entry, md|
194
+ item[:keys].each_with_index { |k, i|
195
+ entry[k] = md[i + 3] # 1 = pid, 2 = host
196
+ }
197
+ }
198
+ }
199
+
200
+ def parse_line(line, entry = {})
201
+ ITEMS.each { |key, item|
202
+ if md = item[:re].match(line)
203
+ if key == :processing
204
+ yield if block_given?
205
+ entry[:pid], entry[:host] = md[1], md[2]
206
+ end
207
+
208
+ item[:proc][entry, md]
209
+
210
+ break
211
+ end
212
+ }
213
+
214
+ entry
215
+ end
216
+
217
+ end
218
+ end
219
+ end