binnacle 0.4.8

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 (449) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +8 -0
  6. data/Gemfile.lock +138 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.asc +264 -0
  9. data/Rakefile +48 -0
  10. data/bin/binnacle +5 -0
  11. data/binnacle.gemspec +49 -0
  12. data/lib/binnacle.rb +112 -0
  13. data/lib/binnacle/client.rb +115 -0
  14. data/lib/binnacle/commands/commands.rb +20 -0
  15. data/lib/binnacle/commands/help.rb +21 -0
  16. data/lib/binnacle/commands/tail.rb +187 -0
  17. data/lib/binnacle/configuration.rb +278 -0
  18. data/lib/binnacle/connection.rb +66 -0
  19. data/lib/binnacle/errors.rb +4 -0
  20. data/lib/binnacle/http_logging/adapters/ethon.rb +44 -0
  21. data/lib/binnacle/http_logging/adapters/excon.rb +62 -0
  22. data/lib/binnacle/http_logging/adapters/http.rb +63 -0
  23. data/lib/binnacle/http_logging/adapters/httpclient.rb +93 -0
  24. data/lib/binnacle/http_logging/adapters/net_http.rb +54 -0
  25. data/lib/binnacle/http_logging/adapters/patron.rb +24 -0
  26. data/lib/binnacle/http_logging/adapters/typhoeus.rb +20 -0
  27. data/lib/binnacle/http_logging/http_logger.rb +83 -0
  28. data/lib/binnacle/logging/formatter.rb +62 -0
  29. data/lib/binnacle/logging/logging.rb +36 -0
  30. data/lib/binnacle/logging/request_log_subscriber.rb +120 -0
  31. data/lib/binnacle/resource.rb +54 -0
  32. data/lib/binnacle/resources/event.rb +100 -0
  33. data/lib/binnacle/trap/backtrace.rb +130 -0
  34. data/lib/binnacle/trap/exception_event.rb +176 -0
  35. data/lib/binnacle/trap/middleware.rb +45 -0
  36. data/lib/binnacle/trap/railtie.rb +28 -0
  37. data/lib/binnacle/version.rb +3 -0
  38. data/lib/generators/binnacle/binnacle_generator.rb +78 -0
  39. data/lib/generators/binnacle/templates/firebase-messaging-sw.js.erb +35 -0
  40. data/spec/adapters/ethon_adapter.rb +19 -0
  41. data/spec/adapters/excon_adapter.rb +10 -0
  42. data/spec/adapters/faraday_adapter.rb +46 -0
  43. data/spec/adapters/http_adapter.rb +14 -0
  44. data/spec/adapters/http_base_adapter.rb +37 -0
  45. data/spec/adapters/httparty_adapter.rb +10 -0
  46. data/spec/adapters/httpclient_adapter.rb +21 -0
  47. data/spec/adapters/net_http_adapter.rb +14 -0
  48. data/spec/adapters/open_uri_adapter.rb +17 -0
  49. data/spec/adapters/patron_adapter.rb +29 -0
  50. data/spec/adapters/typhoeus_adapter.rb +25 -0
  51. data/spec/backtrace_spec.rb +197 -0
  52. data/spec/binnacle_spec.rb +33 -0
  53. data/spec/client_spec.rb +128 -0
  54. data/spec/commands_spec.rb +91 -0
  55. data/spec/configuration_spec.rb +139 -0
  56. data/spec/connection_spec.rb +34 -0
  57. data/spec/exception_event_spec.rb +72 -0
  58. data/spec/http_logger_spec.rb +77 -0
  59. data/spec/logger_spec.rb +60 -0
  60. data/spec/spec_helper.rb +117 -0
  61. data/spec/support/index.html +8 -0
  62. data/spec/support/index.html.gz +0 -0
  63. data/spec/support/test.bin +0 -0
  64. data/spec/support/test_server.rb +31 -0
  65. data/spec/support/utf8-invalid.html +0 -0
  66. data/spec/support/utf8.html +8 -0
  67. data/spec/vcr/binnacle/configure_can_be_configured_via_a_hash_of_options.yml +42 -0
  68. data/spec/vcr/binnacle/configure_creates_a_module_level_instance_of_a_binnacle_client.yml +42 -0
  69. data/spec/vcr/binnacle_client/events_invokes_the_events_api.yml +124 -0
  70. data/spec/vcr/binnacle_client/events_returns_a_collection_of_event_objects.yml +124 -0
  71. data/spec/vcr/binnacle_client/recents_invokes_the_events_api_recents.yml +83 -0
  72. data/spec/vcr/binnacle_client/recents_returns_a_collection_of_event_objects.yml +83 -0
  73. data/spec/vcr/binnacle_client/report_exception_invokes_the_events_api_signal.yml +121 -0
  74. data/spec/vcr/binnacle_client/signal_asynch_invokes_the_events_api_signal.yml +74 -0
  75. data/spec/vcr/binnacle_client/signal_invokes_the_events_api_signal.yml +74 -0
  76. data/spec/vcr/binnacle_client_ready_/returns_true_if_a_connection_has_been_successfully_established.yml +42 -0
  77. data/spec/vcr/binnacle_command/tail_command_with_n_flag_returns_recent_events.yml +81 -0
  78. data/spec/vcr/binnacle_connection/initialize_fails_with_incorrect_credentials.yml +40 -0
  79. data/spec/vcr/binnacle_connection/initialize_retrieves_available_endpoints_upon_successful_connection.yml +42 -0
  80. data/spec/vcr/binnacle_http_logger/_htt_party_adapter_should_log__ge_t_requests.yml +122 -0
  81. data/spec/vcr/binnacle_http_logger/_http_adapter_should_log__ge_t_requests.yml +165 -0
  82. data/spec/vcr/binnacle_http_logger/_http_client_adapter_should_log__ge_t_requests.yml +274 -0
  83. data/spec/vcr/binnacle_http_logger/ethon_adapter_should_log__ge_t_requests.yml +87 -0
  84. data/spec/vcr/binnacle_http_logger/excon_adapter_should_log__ge_t_requests.yml +204 -0
  85. data/spec/vcr/binnacle_http_logger/faraday_adapter_should_log__ge_t_requests.yml +200 -0
  86. data/spec/vcr/binnacle_http_logger/net_http_adapter_should_log__ge_t_requests.yml +827 -0
  87. data/spec/vcr/binnacle_http_logger/open_uri_adapter_should_log__ge_t_requests.yml +751 -0
  88. data/spec/vcr/binnacle_http_logger/patron_adapter_should_log__ge_t_requests.yml +124 -0
  89. data/spec/vcr/binnacle_http_logger/typhoeus_adapter_should_log__ge_t_requests.yml +124 -0
  90. data/spec/vcr/binnacle_logging/logging_allows_passing_other_parameters_using_a_hash.yml +119 -0
  91. data/spec/vcr/binnacle_logging/logging_invokes_the_events_api_signal.yml +75 -0
  92. data/spec/vcr/binnacle_logging/logging_respects_the_logger_severity.yml +81 -0
  93. data/vendor/assets/javascripts/atmosphere/atmosphere.js +3487 -0
  94. data/vendor/assets/javascripts/base64/base64.js +61 -0
  95. data/vendor/assets/javascripts/binnacle.js +5 -0
  96. data/vendor/assets/javascripts/binnacle/binnacle.js +9090 -0
  97. data/vendor/assets/javascripts/firebase/firebase-app-externs.js +261 -0
  98. data/vendor/assets/javascripts/firebase/firebase-app.js +35 -0
  99. data/vendor/assets/javascripts/firebase/firebase-auth-externs.js +1300 -0
  100. data/vendor/assets/javascripts/firebase/firebase-auth.js +241 -0
  101. data/vendor/assets/javascripts/firebase/firebase-database-externs.js +1700 -0
  102. data/vendor/assets/javascripts/firebase/firebase-database.js +260 -0
  103. data/vendor/assets/javascripts/firebase/firebase-messaging-externs.js +164 -0
  104. data/vendor/assets/javascripts/firebase/firebase-messaging.js +35 -0
  105. data/vendor/assets/javascripts/firebase/firebase-storage-externs.js +663 -0
  106. data/vendor/assets/javascripts/firebase/firebase-storage.js +52 -0
  107. data/vendor/assets/javascripts/firebase/firebase.js +611 -0
  108. data/vendor/assets/javascripts/moment/locale/af.js +73 -0
  109. data/vendor/assets/javascripts/moment/locale/ar-dz.js +59 -0
  110. data/vendor/assets/javascripts/moment/locale/ar-kw.js +59 -0
  111. data/vendor/assets/javascripts/moment/locale/ar-ly.js +126 -0
  112. data/vendor/assets/javascripts/moment/locale/ar-ma.js +60 -0
  113. data/vendor/assets/javascripts/moment/locale/ar-sa.js +105 -0
  114. data/vendor/assets/javascripts/moment/locale/ar-tn.js +59 -0
  115. data/vendor/assets/javascripts/moment/locale/ar.js +142 -0
  116. data/vendor/assets/javascripts/moment/locale/az.js +105 -0
  117. data/vendor/assets/javascripts/moment/locale/be.js +134 -0
  118. data/vendor/assets/javascripts/moment/locale/bg.js +90 -0
  119. data/vendor/assets/javascripts/moment/locale/bn.js +119 -0
  120. data/vendor/assets/javascripts/moment/locale/bo.js +119 -0
  121. data/vendor/assets/javascripts/moment/locale/br.js +108 -0
  122. data/vendor/assets/javascripts/moment/locale/bs.js +143 -0
  123. data/vendor/assets/javascripts/moment/locale/ca.js +88 -0
  124. data/vendor/assets/javascripts/moment/locale/cs.js +172 -0
  125. data/vendor/assets/javascripts/moment/locale/cv.js +63 -0
  126. data/vendor/assets/javascripts/moment/locale/cy.js +81 -0
  127. data/vendor/assets/javascripts/moment/locale/da.js +60 -0
  128. data/vendor/assets/javascripts/moment/locale/de-at.js +79 -0
  129. data/vendor/assets/javascripts/moment/locale/de-ch.js +78 -0
  130. data/vendor/assets/javascripts/moment/locale/de.js +78 -0
  131. data/vendor/assets/javascripts/moment/locale/dv.js +100 -0
  132. data/vendor/assets/javascripts/moment/locale/el.js +100 -0
  133. data/vendor/assets/javascripts/moment/locale/en-au.js +67 -0
  134. data/vendor/assets/javascripts/moment/locale/en-ca.js +63 -0
  135. data/vendor/assets/javascripts/moment/locale/en-gb.js +67 -0
  136. data/vendor/assets/javascripts/moment/locale/en-ie.js +67 -0
  137. data/vendor/assets/javascripts/moment/locale/en-nz.js +67 -0
  138. data/vendor/assets/javascripts/moment/locale/eo.js +73 -0
  139. data/vendor/assets/javascripts/moment/locale/es-do.js +82 -0
  140. data/vendor/assets/javascripts/moment/locale/es.js +83 -0
  141. data/vendor/assets/javascripts/moment/locale/et.js +80 -0
  142. data/vendor/assets/javascripts/moment/locale/eu.js +66 -0
  143. data/vendor/assets/javascripts/moment/locale/fa.js +107 -0
  144. data/vendor/assets/javascripts/moment/locale/fi.js +107 -0
  145. data/vendor/assets/javascripts/moment/locale/fo.js +60 -0
  146. data/vendor/assets/javascripts/moment/locale/fr-ca.js +74 -0
  147. data/vendor/assets/javascripts/moment/locale/fr-ch.js +78 -0
  148. data/vendor/assets/javascripts/moment/locale/fr.js +83 -0
  149. data/vendor/assets/javascripts/moment/locale/fy.js +75 -0
  150. data/vendor/assets/javascripts/moment/locale/gd.js +76 -0
  151. data/vendor/assets/javascripts/moment/locale/gl.js +77 -0
  152. data/vendor/assets/javascripts/moment/locale/gom-latn.js +122 -0
  153. data/vendor/assets/javascripts/moment/locale/he.js +99 -0
  154. data/vendor/assets/javascripts/moment/locale/hi.js +124 -0
  155. data/vendor/assets/javascripts/moment/locale/hr.js +145 -0
  156. data/vendor/assets/javascripts/moment/locale/hu.js +109 -0
  157. data/vendor/assets/javascripts/moment/locale/hy-am.js +95 -0
  158. data/vendor/assets/javascripts/moment/locale/id.js +83 -0
  159. data/vendor/assets/javascripts/moment/locale/is.js +127 -0
  160. data/vendor/assets/javascripts/moment/locale/it.js +70 -0
  161. data/vendor/assets/javascripts/moment/locale/ja.js +80 -0
  162. data/vendor/assets/javascripts/moment/locale/jv.js +83 -0
  163. data/vendor/assets/javascripts/moment/locale/ka.js +89 -0
  164. data/vendor/assets/javascripts/moment/locale/kk.js +87 -0
  165. data/vendor/assets/javascripts/moment/locale/km.js +58 -0
  166. data/vendor/assets/javascripts/moment/locale/kn.js +126 -0
  167. data/vendor/assets/javascripts/moment/locale/ko.js +69 -0
  168. data/vendor/assets/javascripts/moment/locale/ky.js +88 -0
  169. data/vendor/assets/javascripts/moment/locale/lb.js +137 -0
  170. data/vendor/assets/javascripts/moment/locale/lo.js +70 -0
  171. data/vendor/assets/javascripts/moment/locale/lt.js +117 -0
  172. data/vendor/assets/javascripts/moment/locale/lv.js +97 -0
  173. data/vendor/assets/javascripts/moment/locale/me.js +111 -0
  174. data/vendor/assets/javascripts/moment/locale/mi.js +64 -0
  175. data/vendor/assets/javascripts/moment/locale/mk.js +90 -0
  176. data/vendor/assets/javascripts/moment/locale/ml.js +81 -0
  177. data/vendor/assets/javascripts/moment/locale/mr.js +159 -0
  178. data/vendor/assets/javascripts/moment/locale/ms-my.js +83 -0
  179. data/vendor/assets/javascripts/moment/locale/ms.js +82 -0
  180. data/vendor/assets/javascripts/moment/locale/my.js +96 -0
  181. data/vendor/assets/javascripts/moment/locale/nb.js +63 -0
  182. data/vendor/assets/javascripts/moment/locale/ne.js +123 -0
  183. data/vendor/assets/javascripts/moment/locale/nl-be.js +88 -0
  184. data/vendor/assets/javascripts/moment/locale/nl.js +88 -0
  185. data/vendor/assets/javascripts/moment/locale/nn.js +60 -0
  186. data/vendor/assets/javascripts/moment/locale/pa-in.js +124 -0
  187. data/vendor/assets/javascripts/moment/locale/pl.js +107 -0
  188. data/vendor/assets/javascripts/moment/locale/pt-br.js +61 -0
  189. data/vendor/assets/javascripts/moment/locale/pt.js +65 -0
  190. data/vendor/assets/javascripts/moment/locale/ro.js +75 -0
  191. data/vendor/assets/javascripts/moment/locale/ru.js +183 -0
  192. data/vendor/assets/javascripts/moment/locale/sd.js +98 -0
  193. data/vendor/assets/javascripts/moment/locale/se.js +61 -0
  194. data/vendor/assets/javascripts/moment/locale/si.js +71 -0
  195. data/vendor/assets/javascripts/moment/locale/sk.js +150 -0
  196. data/vendor/assets/javascripts/moment/locale/sl.js +162 -0
  197. data/vendor/assets/javascripts/moment/locale/sq.js +70 -0
  198. data/vendor/assets/javascripts/moment/locale/sr-cyrl.js +110 -0
  199. data/vendor/assets/javascripts/moment/locale/sr.js +110 -0
  200. data/vendor/assets/javascripts/moment/locale/ss.js +89 -0
  201. data/vendor/assets/javascripts/moment/locale/sv.js +69 -0
  202. data/vendor/assets/javascripts/moment/locale/sw.js +59 -0
  203. data/vendor/assets/javascripts/moment/locale/ta.js +130 -0
  204. data/vendor/assets/javascripts/moment/locale/te.js +89 -0
  205. data/vendor/assets/javascripts/moment/locale/tet.js +68 -0
  206. data/vendor/assets/javascripts/moment/locale/th.js +67 -0
  207. data/vendor/assets/javascripts/moment/locale/tl-ph.js +62 -0
  208. data/vendor/assets/javascripts/moment/locale/tlh.js +120 -0
  209. data/vendor/assets/javascripts/moment/locale/tr.js +90 -0
  210. data/vendor/assets/javascripts/moment/locale/tzl.js +91 -0
  211. data/vendor/assets/javascripts/moment/locale/tzm-latn.js +58 -0
  212. data/vendor/assets/javascripts/moment/locale/tzm.js +58 -0
  213. data/vendor/assets/javascripts/moment/locale/uk.js +151 -0
  214. data/vendor/assets/javascripts/moment/locale/ur.js +99 -0
  215. data/vendor/assets/javascripts/moment/locale/uz-latn.js +58 -0
  216. data/vendor/assets/javascripts/moment/locale/uz.js +58 -0
  217. data/vendor/assets/javascripts/moment/locale/vi.js +79 -0
  218. data/vendor/assets/javascripts/moment/locale/x-pseudo.js +68 -0
  219. data/vendor/assets/javascripts/moment/locale/yo.js +60 -0
  220. data/vendor/assets/javascripts/moment/locale/zh-cn.js +111 -0
  221. data/vendor/assets/javascripts/moment/locale/zh-hk.js +105 -0
  222. data/vendor/assets/javascripts/moment/locale/zh-tw.js +104 -0
  223. data/vendor/assets/javascripts/moment/min/locales.js +9252 -0
  224. data/vendor/assets/javascripts/moment/min/moment-with-locales.js +13700 -0
  225. data/vendor/assets/javascripts/moment/min/moment.min.js +7 -0
  226. data/vendor/assets/javascripts/moment/min/tests.js +78265 -0
  227. data/vendor/assets/javascripts/moment/moment.js +4463 -0
  228. data/vendor/assets/javascripts/moment/src/lib/create/check-overflow.js +34 -0
  229. data/vendor/assets/javascripts/moment/src/lib/create/date-from-array.js +21 -0
  230. data/vendor/assets/javascripts/moment/src/lib/create/from-anything.js +110 -0
  231. data/vendor/assets/javascripts/moment/src/lib/create/from-array.js +140 -0
  232. data/vendor/assets/javascripts/moment/src/lib/create/from-object.js +16 -0
  233. data/vendor/assets/javascripts/moment/src/lib/create/from-string-and-array.js +50 -0
  234. data/vendor/assets/javascripts/moment/src/lib/create/from-string-and-format.js +113 -0
  235. data/vendor/assets/javascripts/moment/src/lib/create/from-string.js +202 -0
  236. data/vendor/assets/javascripts/moment/src/lib/create/local.js +5 -0
  237. data/vendor/assets/javascripts/moment/src/lib/create/parsing-flags.js +26 -0
  238. data/vendor/assets/javascripts/moment/src/lib/create/utc.js +5 -0
  239. data/vendor/assets/javascripts/moment/src/lib/create/valid.js +49 -0
  240. data/vendor/assets/javascripts/moment/src/lib/duration/abs.js +18 -0
  241. data/vendor/assets/javascripts/moment/src/lib/duration/add-subtract.js +21 -0
  242. data/vendor/assets/javascripts/moment/src/lib/duration/as.js +61 -0
  243. data/vendor/assets/javascripts/moment/src/lib/duration/bubble.js +61 -0
  244. data/vendor/assets/javascripts/moment/src/lib/duration/constructor.js +44 -0
  245. data/vendor/assets/javascripts/moment/src/lib/duration/create.js +122 -0
  246. data/vendor/assets/javascripts/moment/src/lib/duration/duration.js +16 -0
  247. data/vendor/assets/javascripts/moment/src/lib/duration/get.js +25 -0
  248. data/vendor/assets/javascripts/moment/src/lib/duration/humanize.js +85 -0
  249. data/vendor/assets/javascripts/moment/src/lib/duration/iso-string.js +56 -0
  250. data/vendor/assets/javascripts/moment/src/lib/duration/prototype.js +50 -0
  251. data/vendor/assets/javascripts/moment/src/lib/duration/valid.js +35 -0
  252. data/vendor/assets/javascripts/moment/src/lib/format/format.js +92 -0
  253. data/vendor/assets/javascripts/moment/src/lib/locale/base-config.js +44 -0
  254. data/vendor/assets/javascripts/moment/src/lib/locale/calendar.js +15 -0
  255. data/vendor/assets/javascripts/moment/src/lib/locale/constructor.js +5 -0
  256. data/vendor/assets/javascripts/moment/src/lib/locale/en.js +15 -0
  257. data/vendor/assets/javascripts/moment/src/lib/locale/formats.js +23 -0
  258. data/vendor/assets/javascripts/moment/src/lib/locale/invalid.js +5 -0
  259. data/vendor/assets/javascripts/moment/src/lib/locale/lists.js +93 -0
  260. data/vendor/assets/javascripts/moment/src/lib/locale/locale.js +39 -0
  261. data/vendor/assets/javascripts/moment/src/lib/locale/locales.js +186 -0
  262. data/vendor/assets/javascripts/moment/src/lib/locale/ordinal.js +7 -0
  263. data/vendor/assets/javascripts/moment/src/lib/locale/pre-post-format.js +3 -0
  264. data/vendor/assets/javascripts/moment/src/lib/locale/prototype.js +69 -0
  265. data/vendor/assets/javascripts/moment/src/lib/locale/relative.js +30 -0
  266. data/vendor/assets/javascripts/moment/src/lib/locale/set.js +49 -0
  267. data/vendor/assets/javascripts/moment/src/lib/moment/add-subtract.js +55 -0
  268. data/vendor/assets/javascripts/moment/src/lib/moment/calendar.js +26 -0
  269. data/vendor/assets/javascripts/moment/src/lib/moment/clone.js +5 -0
  270. data/vendor/assets/javascripts/moment/src/lib/moment/compare.js +59 -0
  271. data/vendor/assets/javascripts/moment/src/lib/moment/constructor.js +77 -0
  272. data/vendor/assets/javascripts/moment/src/lib/moment/creation-data.js +9 -0
  273. data/vendor/assets/javascripts/moment/src/lib/moment/diff.js +62 -0
  274. data/vendor/assets/javascripts/moment/src/lib/moment/format.js +57 -0
  275. data/vendor/assets/javascripts/moment/src/lib/moment/from.js +17 -0
  276. data/vendor/assets/javascripts/moment/src/lib/moment/get-set.js +55 -0
  277. data/vendor/assets/javascripts/moment/src/lib/moment/locale.js +34 -0
  278. data/vendor/assets/javascripts/moment/src/lib/moment/min-max.js +63 -0
  279. data/vendor/assets/javascripts/moment/src/lib/moment/moment.js +28 -0
  280. data/vendor/assets/javascripts/moment/src/lib/moment/now.js +3 -0
  281. data/vendor/assets/javascripts/moment/src/lib/moment/prototype.js +150 -0
  282. data/vendor/assets/javascripts/moment/src/lib/moment/start-end-of.js +59 -0
  283. data/vendor/assets/javascripts/moment/src/lib/moment/to-type.js +34 -0
  284. data/vendor/assets/javascripts/moment/src/lib/moment/to.js +17 -0
  285. data/vendor/assets/javascripts/moment/src/lib/moment/valid.js +15 -0
  286. data/vendor/assets/javascripts/moment/src/lib/parse/regex.js +54 -0
  287. data/vendor/assets/javascripts/moment/src/lib/parse/token.js +33 -0
  288. data/vendor/assets/javascripts/moment/src/lib/units/aliases.js +30 -0
  289. data/vendor/assets/javascripts/moment/src/lib/units/constants.js +9 -0
  290. data/vendor/assets/javascripts/moment/src/lib/units/day-of-month.js +39 -0
  291. data/vendor/assets/javascripts/moment/src/lib/units/day-of-week.js +364 -0
  292. data/vendor/assets/javascripts/moment/src/lib/units/day-of-year.js +36 -0
  293. data/vendor/assets/javascripts/moment/src/lib/units/hour.js +144 -0
  294. data/vendor/assets/javascripts/moment/src/lib/units/millisecond.js +69 -0
  295. data/vendor/assets/javascripts/moment/src/lib/units/minute.js +29 -0
  296. data/vendor/assets/javascripts/moment/src/lib/units/month.js +283 -0
  297. data/vendor/assets/javascripts/moment/src/lib/units/offset.js +235 -0
  298. data/vendor/assets/javascripts/moment/src/lib/units/priorities.js +16 -0
  299. data/vendor/assets/javascripts/moment/src/lib/units/quarter.js +32 -0
  300. data/vendor/assets/javascripts/moment/src/lib/units/second.js +29 -0
  301. data/vendor/assets/javascripts/moment/src/lib/units/timestamp.js +20 -0
  302. data/vendor/assets/javascripts/moment/src/lib/units/timezone.js +16 -0
  303. data/vendor/assets/javascripts/moment/src/lib/units/units.js +20 -0
  304. data/vendor/assets/javascripts/moment/src/lib/units/week-calendar-utils.js +65 -0
  305. data/vendor/assets/javascripts/moment/src/lib/units/week-year.js +107 -0
  306. data/vendor/assets/javascripts/moment/src/lib/units/week.js +67 -0
  307. data/vendor/assets/javascripts/moment/src/lib/units/year.js +75 -0
  308. data/vendor/assets/javascripts/moment/src/lib/utils/abs-ceil.js +7 -0
  309. data/vendor/assets/javascripts/moment/src/lib/utils/abs-floor.js +8 -0
  310. data/vendor/assets/javascripts/moment/src/lib/utils/abs-round.js +7 -0
  311. data/vendor/assets/javascripts/moment/src/lib/utils/compare-arrays.js +16 -0
  312. data/vendor/assets/javascripts/moment/src/lib/utils/defaults.js +10 -0
  313. data/vendor/assets/javascripts/moment/src/lib/utils/deprecate.js +55 -0
  314. data/vendor/assets/javascripts/moment/src/lib/utils/extend.js +19 -0
  315. data/vendor/assets/javascripts/moment/src/lib/utils/has-own-prop.js +3 -0
  316. data/vendor/assets/javascripts/moment/src/lib/utils/hooks.js +13 -0
  317. data/vendor/assets/javascripts/moment/src/lib/utils/index-of.js +18 -0
  318. data/vendor/assets/javascripts/moment/src/lib/utils/is-array.js +3 -0
  319. data/vendor/assets/javascripts/moment/src/lib/utils/is-date.js +3 -0
  320. data/vendor/assets/javascripts/moment/src/lib/utils/is-function.js +3 -0
  321. data/vendor/assets/javascripts/moment/src/lib/utils/is-number.js +3 -0
  322. data/vendor/assets/javascripts/moment/src/lib/utils/is-object-empty.js +8 -0
  323. data/vendor/assets/javascripts/moment/src/lib/utils/is-object.js +5 -0
  324. data/vendor/assets/javascripts/moment/src/lib/utils/is-undefined.js +3 -0
  325. data/vendor/assets/javascripts/moment/src/lib/utils/keys.js +19 -0
  326. data/vendor/assets/javascripts/moment/src/lib/utils/map.js +7 -0
  327. data/vendor/assets/javascripts/moment/src/lib/utils/some.js +19 -0
  328. data/vendor/assets/javascripts/moment/src/lib/utils/to-int.js +12 -0
  329. data/vendor/assets/javascripts/moment/src/lib/utils/zero-fill.js +7 -0
  330. data/vendor/assets/javascripts/moment/src/locale/af.js +63 -0
  331. data/vendor/assets/javascripts/moment/src/locale/ar-dz.js +50 -0
  332. data/vendor/assets/javascripts/moment/src/locale/ar-kw.js +49 -0
  333. data/vendor/assets/javascripts/moment/src/locale/ar-ly.js +112 -0
  334. data/vendor/assets/javascripts/moment/src/locale/ar-ma.js +51 -0
  335. data/vendor/assets/javascripts/moment/src/locale/ar-sa.js +95 -0
  336. data/vendor/assets/javascripts/moment/src/locale/ar-tn.js +50 -0
  337. data/vendor/assets/javascripts/moment/src/locale/ar.js +128 -0
  338. data/vendor/assets/javascripts/moment/src/locale/az.js +96 -0
  339. data/vendor/assets/javascripts/moment/src/locale/be.js +125 -0
  340. data/vendor/assets/javascripts/moment/src/locale/bg.js +81 -0
  341. data/vendor/assets/javascripts/moment/src/locale/bn.js +109 -0
  342. data/vendor/assets/javascripts/moment/src/locale/bo.js +110 -0
  343. data/vendor/assets/javascripts/moment/src/locale/br.js +99 -0
  344. data/vendor/assets/javascripts/moment/src/locale/bs.js +133 -0
  345. data/vendor/assets/javascripts/moment/src/locale/ca.js +79 -0
  346. data/vendor/assets/javascripts/moment/src/locale/cs.js +163 -0
  347. data/vendor/assets/javascripts/moment/src/locale/cv.js +53 -0
  348. data/vendor/assets/javascripts/moment/src/locale/cy.js +72 -0
  349. data/vendor/assets/javascripts/moment/src/locale/da.js +50 -0
  350. data/vendor/assets/javascripts/moment/src/locale/de-at.js +69 -0
  351. data/vendor/assets/javascripts/moment/src/locale/de-ch.js +68 -0
  352. data/vendor/assets/javascripts/moment/src/locale/de.js +68 -0
  353. data/vendor/assets/javascripts/moment/src/locale/dv.js +89 -0
  354. data/vendor/assets/javascripts/moment/src/locale/el.js +88 -0
  355. data/vendor/assets/javascripts/moment/src/locale/en-au.js +58 -0
  356. data/vendor/assets/javascripts/moment/src/locale/en-ca.js +53 -0
  357. data/vendor/assets/javascripts/moment/src/locale/en-gb.js +58 -0
  358. data/vendor/assets/javascripts/moment/src/locale/en-ie.js +58 -0
  359. data/vendor/assets/javascripts/moment/src/locale/en-nz.js +57 -0
  360. data/vendor/assets/javascripts/moment/src/locale/eo.js +64 -0
  361. data/vendor/assets/javascripts/moment/src/locale/es-do.js +73 -0
  362. data/vendor/assets/javascripts/moment/src/locale/es.js +74 -0
  363. data/vendor/assets/javascripts/moment/src/locale/et.js +71 -0
  364. data/vendor/assets/javascripts/moment/src/locale/eu.js +57 -0
  365. data/vendor/assets/javascripts/moment/src/locale/fa.js +97 -0
  366. data/vendor/assets/javascripts/moment/src/locale/fi.js +98 -0
  367. data/vendor/assets/javascripts/moment/src/locale/fo.js +51 -0
  368. data/vendor/assets/javascripts/moment/src/locale/fr-ca.js +65 -0
  369. data/vendor/assets/javascripts/moment/src/locale/fr-ch.js +69 -0
  370. data/vendor/assets/javascripts/moment/src/locale/fr.js +74 -0
  371. data/vendor/assets/javascripts/moment/src/locale/fy.js +66 -0
  372. data/vendor/assets/javascripts/moment/src/locale/gd.js +67 -0
  373. data/vendor/assets/javascripts/moment/src/locale/gl.js +68 -0
  374. data/vendor/assets/javascripts/moment/src/locale/gom-latn.js +112 -0
  375. data/vendor/assets/javascripts/moment/src/locale/he.js +90 -0
  376. data/vendor/assets/javascripts/moment/src/locale/hi.js +115 -0
  377. data/vendor/assets/javascripts/moment/src/locale/hr.js +135 -0
  378. data/vendor/assets/javascripts/moment/src/locale/hu.js +100 -0
  379. data/vendor/assets/javascripts/moment/src/locale/hy-am.js +86 -0
  380. data/vendor/assets/javascripts/moment/src/locale/id.js +74 -0
  381. data/vendor/assets/javascripts/moment/src/locale/is.js +118 -0
  382. data/vendor/assets/javascripts/moment/src/locale/it.js +61 -0
  383. data/vendor/assets/javascripts/moment/src/locale/ja.js +71 -0
  384. data/vendor/assets/javascripts/moment/src/locale/jv.js +73 -0
  385. data/vendor/assets/javascripts/moment/src/locale/ka.js +80 -0
  386. data/vendor/assets/javascripts/moment/src/locale/kk.js +77 -0
  387. data/vendor/assets/javascripts/moment/src/locale/km.js +49 -0
  388. data/vendor/assets/javascripts/moment/src/locale/kn.js +116 -0
  389. data/vendor/assets/javascripts/moment/src/locale/ko.js +60 -0
  390. data/vendor/assets/javascripts/moment/src/locale/ky.js +78 -0
  391. data/vendor/assets/javascripts/moment/src/locale/lb.js +128 -0
  392. data/vendor/assets/javascripts/moment/src/locale/lo.js +61 -0
  393. data/vendor/assets/javascripts/moment/src/locale/lt.js +108 -0
  394. data/vendor/assets/javascripts/moment/src/locale/lv.js +88 -0
  395. data/vendor/assets/javascripts/moment/src/locale/me.js +101 -0
  396. data/vendor/assets/javascripts/moment/src/locale/mi.js +54 -0
  397. data/vendor/assets/javascripts/moment/src/locale/mk.js +81 -0
  398. data/vendor/assets/javascripts/moment/src/locale/ml.js +72 -0
  399. data/vendor/assets/javascripts/moment/src/locale/mr.js +150 -0
  400. data/vendor/assets/javascripts/moment/src/locale/ms-my.js +74 -0
  401. data/vendor/assets/javascripts/moment/src/locale/ms.js +73 -0
  402. data/vendor/assets/javascripts/moment/src/locale/my.js +86 -0
  403. data/vendor/assets/javascripts/moment/src/locale/nb.js +54 -0
  404. data/vendor/assets/javascripts/moment/src/locale/ne.js +114 -0
  405. data/vendor/assets/javascripts/moment/src/locale/nl-be.js +79 -0
  406. data/vendor/assets/javascripts/moment/src/locale/nl.js +79 -0
  407. data/vendor/assets/javascripts/moment/src/locale/nn.js +51 -0
  408. data/vendor/assets/javascripts/moment/src/locale/pa-in.js +115 -0
  409. data/vendor/assets/javascripts/moment/src/locale/pl.js +97 -0
  410. data/vendor/assets/javascripts/moment/src/locale/pt-br.js +52 -0
  411. data/vendor/assets/javascripts/moment/src/locale/pt.js +56 -0
  412. data/vendor/assets/javascripts/moment/src/locale/ro.js +66 -0
  413. data/vendor/assets/javascripts/moment/src/locale/ru.js +173 -0
  414. data/vendor/assets/javascripts/moment/src/locale/sd.js +88 -0
  415. data/vendor/assets/javascripts/moment/src/locale/se.js +51 -0
  416. data/vendor/assets/javascripts/moment/src/locale/si.js +61 -0
  417. data/vendor/assets/javascripts/moment/src/locale/sk.js +141 -0
  418. data/vendor/assets/javascripts/moment/src/locale/sl.js +152 -0
  419. data/vendor/assets/javascripts/moment/src/locale/sq.js +61 -0
  420. data/vendor/assets/javascripts/moment/src/locale/sr-cyrl.js +100 -0
  421. data/vendor/assets/javascripts/moment/src/locale/sr.js +100 -0
  422. data/vendor/assets/javascripts/moment/src/locale/ss.js +80 -0
  423. data/vendor/assets/javascripts/moment/src/locale/sv.js +60 -0
  424. data/vendor/assets/javascripts/moment/src/locale/sw.js +50 -0
  425. data/vendor/assets/javascripts/moment/src/locale/ta.js +120 -0
  426. data/vendor/assets/javascripts/moment/src/locale/te.js +79 -0
  427. data/vendor/assets/javascripts/moment/src/locale/tet.js +58 -0
  428. data/vendor/assets/javascripts/moment/src/locale/th.js +57 -0
  429. data/vendor/assets/javascripts/moment/src/locale/tl-ph.js +53 -0
  430. data/vendor/assets/javascripts/moment/src/locale/tlh.js +110 -0
  431. data/vendor/assets/javascripts/moment/src/locale/tr.js +81 -0
  432. data/vendor/assets/javascripts/moment/src/locale/tzl.js +82 -0
  433. data/vendor/assets/javascripts/moment/src/locale/tzm-latn.js +49 -0
  434. data/vendor/assets/javascripts/moment/src/locale/tzm.js +49 -0
  435. data/vendor/assets/javascripts/moment/src/locale/uk.js +142 -0
  436. data/vendor/assets/javascripts/moment/src/locale/ur.js +89 -0
  437. data/vendor/assets/javascripts/moment/src/locale/uz-latn.js +49 -0
  438. data/vendor/assets/javascripts/moment/src/locale/uz.js +49 -0
  439. data/vendor/assets/javascripts/moment/src/locale/vi.js +70 -0
  440. data/vendor/assets/javascripts/moment/src/locale/x-pseudo.js +58 -0
  441. data/vendor/assets/javascripts/moment/src/locale/yo.js +50 -0
  442. data/vendor/assets/javascripts/moment/src/locale/zh-cn.js +102 -0
  443. data/vendor/assets/javascripts/moment/src/locale/zh-hk.js +95 -0
  444. data/vendor/assets/javascripts/moment/src/locale/zh-tw.js +94 -0
  445. data/vendor/assets/javascripts/moment/src/moment.js +82 -0
  446. data/vendor/assets/javascripts/moment/templates/default.js +5 -0
  447. data/vendor/assets/javascripts/moment/templates/locale-header.js +6 -0
  448. data/vendor/assets/javascripts/moment/templates/test-header.js +6 -0
  449. metadata +943 -0
@@ -0,0 +1,120 @@
1
+ require 'json'
2
+ require 'action_pack'
3
+ require 'active_support/core_ext/class/attribute'
4
+ require 'active_support/log_subscriber'
5
+
6
+ module Binnacle
7
+ module Logging
8
+ class RequestLogSubscriber < ActiveSupport::LogSubscriber
9
+ def process_action(event)
10
+ return if Binnacle.configuration.ignore?(event)
11
+ payload = event.payload
12
+ data = extract_request(event, payload)
13
+ Binnacle.client.log_rails_event(data)
14
+ end
15
+
16
+ def redirect_to(event)
17
+ Thread.current[:binnacle_location] = event.payload[:location]
18
+ end
19
+
20
+ # TODO: Implement send_file and send_data
21
+ # def send_file(event)
22
+ # info { "Sent data #{event.payload[:filename]} (#{event.duration.round(1)}ms)" }
23
+ # end
24
+ #
25
+ # def send_data(event)
26
+ # info { "Sent data #{event.payload[:filename]} (#{event.duration.round(1)}ms)" }
27
+ # end
28
+
29
+ def unpermitted_parameters(event)
30
+ Thread.current[:binnacle_unpermitted_params] ||= []
31
+ Thread.current[:binnacle_unpermitted_params].concat(event.payload[:keys])
32
+ end
33
+
34
+ private
35
+
36
+ def extract_request(event, payload)
37
+ payload = event.payload
38
+ data = initial_data(payload)
39
+ data.merge!(extract_status(payload))
40
+ data.merge!(extract_runtimes(event, payload))
41
+ data.merge!(extract_location)
42
+ data.merge!(extract_unpermitted_params)
43
+ data.merge!(extract_event_details(event))
44
+ data.merge!({message: "#{data[:method]} #{data[:path]} AS #{data[:format]} (view: #{data[:view]}ms, db: #{data[:db]}ms)"})
45
+ end
46
+
47
+ def initial_data(payload)
48
+ path = extract_path(payload)
49
+ method = payload[:method]
50
+ format = extract_format(payload)
51
+ {
52
+ direction: :in,
53
+ method: method,
54
+ path: path,
55
+ format: format,
56
+ controller: payload[:params]['controller'],
57
+ action: payload[:params]['action'],
58
+ params: payload[:params],
59
+ }
60
+ end
61
+
62
+ def extract_path(payload)
63
+ path = payload[:path]
64
+ index = path.index('?')
65
+ index ? path[0, index] : path
66
+ end
67
+
68
+ def extract_event_details(event)
69
+ {
70
+ time: event.time,
71
+ transaction_id: event.transaction_id
72
+ }
73
+ end
74
+
75
+ def extract_format(payload)
76
+ (::ActionPack::VERSION::MAJOR == 3 && ::ActionPack::VERSION::MINOR == 0) ? payload[:formats].first : payload[:format]
77
+ end
78
+
79
+ def extract_status(payload)
80
+ if (status = payload[:status])
81
+ { status: status.to_i }
82
+ elsif (error = payload[:exception])
83
+ exception, message = error
84
+ { status: get_error_status_code(exception), error: "#{exception}: #{message}" }
85
+ else
86
+ { status: 0 }
87
+ end
88
+ end
89
+
90
+ def get_error_status_code(exception)
91
+ status = ActionDispatch::ExceptionWrapper.rescue_responses[exception]
92
+ Rack::Utils.status_code(status)
93
+ end
94
+
95
+ def extract_runtimes(event, payload)
96
+ data = { duration: event.duration.to_f.round(2) }
97
+ data[:view] = payload[:view_runtime].to_f.round(2) if payload.key?(:view_runtime)
98
+ data[:db] = payload[:db_runtime].to_f.round(2) if payload.key?(:db_runtime)
99
+ data
100
+ end
101
+
102
+ def extract_location
103
+ location = Thread.current[:binnacle_location]
104
+ return {} unless location
105
+
106
+ Thread.current[:binnacle_location] = nil
107
+ { location: location }
108
+ end
109
+
110
+ def extract_unpermitted_params
111
+ unpermitted_params = Thread.current[:binnacle_unpermitted_params]
112
+ return {} unless unpermitted_params
113
+
114
+ Thread.current[:binnacle_unpermitted_params] = nil
115
+ { unpermitted_params: unpermitted_params }
116
+ end
117
+
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,54 @@
1
+ require 'json'
2
+
3
+ module Binnacle
4
+ class Resource
5
+ attr_reader :route
6
+ attr_writer :connection
7
+
8
+ def post_asynch
9
+ Thread.new do
10
+ response = response_from_post(@connection, self.route, self.to_json)
11
+
12
+ if response.status == 401
13
+ Binnacle.binnacle_logger.error("Error communicating with Binnacle: #{response.body}")
14
+ end
15
+ end
16
+ end
17
+
18
+ def post
19
+ response = response_from_post(@connection, self.route, self.to_json)
20
+
21
+ if response.status == 401
22
+ Binnacle.binnacle_logger.error("Error communicating with Binnacle: #{response.body}")
23
+ else
24
+ JSON.parse(response.body)
25
+ end
26
+ end
27
+
28
+ def self.get(connection, path, query_params)
29
+ response = connection.get do |req|
30
+ req.url path
31
+ req.headers['Content-Type'] = 'application/json'
32
+ query_params.each do |n,v|
33
+ req.params[n] = v if v
34
+ end
35
+ end
36
+
37
+ if response.status == 401
38
+ Binnacle.binnacle_logger.error("Error communicating with Binnacle: #{response.body}")
39
+ else
40
+ JSON.parse(response.body).map { |r| self.from_hash(r) }
41
+ end
42
+ end
43
+
44
+ protected
45
+
46
+ def response_from_post(connection, route, body)
47
+ connection.post do |req|
48
+ req.url route
49
+ req.headers['Content-Type'] = 'application/json'
50
+ req.body = body
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,100 @@
1
+ module Binnacle
2
+ class Event < Resource
3
+
4
+ attr_accessor :channel_id
5
+ attr_accessor :event_name
6
+ attr_accessor :client_id
7
+ attr_accessor :session_id
8
+ attr_accessor :client_event_time
9
+ attr_accessor :ip_address
10
+ attr_accessor :log_level
11
+ attr_accessor :tags
12
+ attr_accessor :json
13
+ attr_accessor :event_time
14
+
15
+ def configure(channel_id, event_name, client_id, session_id, log_level, ts = Time.now, tags = [], json = {})
16
+ self.channel_id = channel_id
17
+ self.event_name = event_name
18
+ self.client_id = client_id
19
+ self.session_id = session_id
20
+ self.timestamp = ts ? ts : Time.now
21
+ self.log_level = log_level
22
+ self.tags = tags
23
+ self.json = json
24
+ end
25
+
26
+ def configure_from_logging_progname(progname, channel_id, client_id, session_id, log_level, ts = Time.now, tags = [], json = {})
27
+ if progname.is_a?(Hash)
28
+ self.client_id = progname[:client_id] || client_id
29
+ self.session_id = progname[:session_id] || session_id
30
+ self.channel_id = progname[:channel_id] || channel_id
31
+ self.event_name = progname[:event_name]
32
+ self.tags = progname[:tags] || tags
33
+ self.json = json
34
+ self.json.merge!(progname[:json]) if progname[:json]
35
+ elsif progname.is_a?(String)
36
+ self.client_id = client_id
37
+ self.session_id = session_id
38
+ self.channel_id = channel_id
39
+ self.event_name = progname
40
+ self.tags = tags
41
+ self.json = json
42
+ end
43
+
44
+ self.timestamp = ts ? ts : Time.now
45
+ self.log_level = log_level
46
+ end
47
+
48
+ def timestamp=(ts)
49
+ self.client_event_time = ts.strftime("%Y-%m-%dT%H:%M:%S%z")
50
+ end
51
+
52
+ def self.from_hash(h)
53
+ event = self.new()
54
+ event.channel_id = h['channelId']
55
+ event.event_name = h['eventName']
56
+ event.client_id = h['clientId']
57
+ event.session_id = h['sessionId']
58
+ event.ip_address = h['ipAddress']
59
+ event.log_level = h['logLevel']
60
+ event.event_time = Time.at(h['eventTime']/1000)
61
+ event.tags = h['tags']
62
+ event.json = h['json']
63
+
64
+ event
65
+ end
66
+
67
+ def to_json
68
+ {
69
+ "channelId" => channel_id,
70
+ "sessionId" => session_id,
71
+ "clientEventTime" => client_event_time,
72
+ "eventName" => event_name,
73
+ "clientId" => client_id,
74
+ "logLevel" => log_level,
75
+ "tags" => tags,
76
+ "json" => json
77
+ }.to_json
78
+ end
79
+
80
+ def route
81
+ "/api/events/#{channel_id}"
82
+ end
83
+
84
+ def self.route(channel)
85
+ "/api/events/#{channel}"
86
+ end
87
+
88
+ def self.recents(connection, lines, since, channel)
89
+ path = [route(channel), 'recents'].compact.join('/')
90
+
91
+ get(connection, path, {'limit' => lines, 'since' => since})
92
+ end
93
+
94
+ def self.events(connection, channel, date, start_hour, end_hour, lines)
95
+ path = [route(channel), date].compact.join('/')
96
+
97
+ get(connection, path, {'start_hour' => start_hour, 'end_hour' => end_hour, 'limit' => lines})
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,130 @@
1
+ module Binnacle
2
+ module Trap
3
+ # Front end to parsing the backtrace for each notice
4
+ class Backtrace
5
+ # --------------------------------------------------------------
6
+ # Attribution:
7
+ # Copied from Airbrake Gem. https://github.com/airbrake/airbrake
8
+ # --------------------------------------------------------------
9
+
10
+ # Handles backtrace parsing line by line
11
+ class Line
12
+
13
+ GEM_PATHS = (Gem.path | [Gem.default_dir]).map { |p| Regexp.escape(p) }
14
+ GEMS_REGEXP = %r{(#{GEM_PATHS.join('|')})/gems/([^/]+)-([\w.]+)/(.*)}
15
+ GEMS_RESULT = '\2 (\3) \4'.freeze
16
+
17
+ # regexp (optionnally allowing leading X: for windows support)
18
+ INPUT_FORMAT = %r{^((?:[a-zA-Z]:)?[^:]+):(\d+)(?::in `([^']+)')?$}.freeze
19
+
20
+ # The file portion of the line (such as app/models/user.rb)
21
+ attr_reader :file
22
+
23
+ # The line number portion of the line
24
+ attr_reader :number
25
+
26
+ # The method_name of the line (such as index)
27
+ attr_reader :method_name
28
+
29
+ # Parses a single line of a given backtrace
30
+ # @param [String] unparsed_line The raw line from +caller+ or some backtrace
31
+ # @return [Line] The parsed backtrace line
32
+ def self.parse(unparsed_line)
33
+ _, file, number, method_name = unparsed_line.match(INPUT_FORMAT).to_a
34
+
35
+ # Remove Rails root from log lines
36
+ file = defined?(Rails) ? file.gsub(Rails.root.to_s, '') : file
37
+
38
+ if file
39
+ # Clean those ERB lines, we don't need the internal autogenerated
40
+ # ERB method, what we do need (line number in ERB file) is already there
41
+ file = file.sub /(\.erb:\d+)\:in `__.*$/, "\\1"
42
+
43
+ # Remove RubyGems root directories
44
+ file = file.sub(GEMS_REGEXP, GEMS_RESULT)
45
+ end
46
+
47
+ new(file, number, method_name)
48
+ end
49
+
50
+ def initialize(file, number, method_name)
51
+ @file = file
52
+ @number = number
53
+ @method_name = method_name
54
+ end
55
+
56
+ # Reconstructs the line in a readable fashion
57
+ def to_s
58
+ "#{file}:#{number}:in `#{method_name}'"
59
+ end
60
+
61
+ def ==(other)
62
+ to_s == other.to_s
63
+ end
64
+
65
+ def inspect
66
+ "<Line:#{to_s}>"
67
+ end
68
+
69
+ def empty?
70
+ file.nil? && number.nil? && method_name.nil?
71
+ end
72
+ end
73
+
74
+ # holder for an Array of Backtrace::Line instances
75
+ attr_reader :lines
76
+
77
+ def self.parse(ruby_backtrace, opts = {})
78
+ ruby_lines = split_multiline_backtrace(ruby_backtrace)
79
+
80
+ filters = opts[:filters] || []
81
+ filtered_lines = ruby_lines.to_a.map do |line|
82
+ filters.inject(line) do |l, proc|
83
+ proc.call(l)
84
+ end
85
+ end.compact
86
+
87
+ lines = filtered_lines.collect do |unparsed_line|
88
+ Line.parse(unparsed_line)
89
+ end
90
+
91
+ new(lines.delete_if(&:empty?))
92
+ end
93
+
94
+ def initialize(lines)
95
+ @lines = lines
96
+ end
97
+
98
+ def inspect
99
+ "<Backtrace: " + lines.collect { |line| line.inspect }.join(", ") + ">"
100
+ end
101
+
102
+ def to_s
103
+ content = []
104
+ lines.each do |line|
105
+ content << line
106
+ end
107
+ content.join("\n")
108
+ end
109
+
110
+ def ==(other)
111
+ if other.respond_to?(:lines)
112
+ lines == other.lines
113
+ else
114
+ false
115
+ end
116
+ end
117
+
118
+ private
119
+
120
+ def self.split_multiline_backtrace(backtrace)
121
+ backtrace = [backtrace] unless backtrace.respond_to?(:to_a)
122
+ if backtrace.to_a.size == 1
123
+ backtrace.to_a.first.split(/\n\s*/)
124
+ else
125
+ backtrace
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,176 @@
1
+ require_relative 'backtrace'
2
+ require 'json'
3
+
4
+ module Binnacle
5
+ module Trap
6
+ HTTP_HEADER_PREFIXES = [
7
+ 'HTTP_'.freeze,
8
+ 'CONTENT_TYPE'.freeze,
9
+ 'CONTENT_LENGTH'.freeze
10
+ ].freeze
11
+
12
+ HTTP_HEADER_SKIPS = [
13
+ 'HTTP_COOKIE'.freeze,
14
+ 'HTTP_X_CSRF_TOKEN'.freeze
15
+ ]
16
+
17
+ class ExceptionEvent < ::Binnacle::Event
18
+ attr_reader :exception
19
+ attr_reader :env
20
+ attr_reader :request
21
+ attr_reader :component
22
+ attr_reader :method
23
+ attr_reader :module
24
+ attr_reader :backtrace
25
+
26
+ def initialize(exception, env)
27
+ @exception = unwrap_exception(exception)
28
+ @env = env
29
+
30
+ if env["action_dispatch.request.parameters"] != nil
31
+ @component = env['action_dispatch.request.parameters'][:controller] || nil
32
+ @method = env['action_dispatch.request.parameters'][:action] || nil
33
+ @module = env['action_dispatch.request.parameters'][:module] || nil
34
+ end
35
+
36
+ @request = ::Rack::Request.new(env)
37
+
38
+ extract_event_name
39
+ extract_session_id
40
+ extract_client_id
41
+ extract_backtrace
42
+
43
+ self.log_level = "EXCEPTION"
44
+ self.tags = []
45
+ build_json_payload
46
+
47
+ configure(
48
+ Binnacle.configuration.error_channel,
49
+ self.event_name,
50
+ self.client_id,
51
+ self.session_id,
52
+ self.log_level,
53
+ nil,
54
+ self.tags,
55
+ self.json
56
+ )
57
+ end
58
+
59
+ private
60
+
61
+ def unwrap_exception(exception)
62
+ if exception.respond_to?(:original_exception)
63
+ exception.original_exception
64
+ elsif exception.respond_to?(:continued_exception)
65
+ exception.continued_exception
66
+ end || exception
67
+ end
68
+
69
+ # The root Exception class name
70
+ def extract_event_name
71
+ self.event_name = @exception.class.to_s
72
+ end
73
+
74
+ # The affected User or some identifier that can be used to determine
75
+ # who was affected by the exception (Warden, Devise, etc. should be used
76
+ # if available to get this information)
77
+ def extract_session_id
78
+ self.session_id = (@env["rack.session"] ? @env["rack.session"]["session_id"] : nil) || @request.ip
79
+ end
80
+
81
+ def extract_backtrace
82
+ backtrace = Backtrace.parse(@exception.backtrace)
83
+ @backtrace = backtrace.lines.map do |line|
84
+ { number: line.number, file: line.file, method: line.method_name }
85
+ end
86
+ end
87
+
88
+ def extract_headers
89
+ http_headers = {}
90
+
91
+ http_headers = @env.map.with_object({}) do |(key, value), headers|
92
+ if Binnacle::Trap::HTTP_HEADER_PREFIXES.any? { |prefix| key.to_s.start_with?(prefix) } && !HTTP_HEADER_SKIPS.include?(key.to_s)
93
+ headers[key] = value
94
+ end
95
+
96
+ headers
97
+ end
98
+
99
+ http_headers
100
+ end
101
+
102
+ def extract_framework
103
+ defined?(Rails) ? "Rails" : "unknown"
104
+ end
105
+
106
+ def extract_framework_version
107
+ defined?(Rails) ? Rails::VERSION::STRING : "unknown"
108
+ end
109
+
110
+ def extract_framework_params
111
+ {}
112
+ end
113
+
114
+ def extract_ruby_version
115
+ "#{RUBY_VERSION rescue '?.?.?'} p#{RUBY_PATCHLEVEL rescue '???'} #{RUBY_RELEASE_DATE rescue '????-??-??'} #{RUBY_PLATFORM rescue '????'}"
116
+ end
117
+
118
+ def extract_hostname
119
+ require 'socket' unless defined?(Socket)
120
+ Socket.gethostname
121
+ rescue
122
+ 'UNKNOWN'
123
+ end
124
+
125
+ def extract_rails_environment_level
126
+ defined?(Rails) ? Rails.env : "UNKNOWN"
127
+ end
128
+
129
+ def extract_libraries_loaded
130
+ libraries = {}
131
+ begin
132
+ libraries = Hash[*Gem.loaded_specs.map{|name, gem_specification| [name, gem_specification.version.to_s]}.flatten]
133
+ rescue
134
+ end
135
+
136
+ libraries
137
+ end
138
+
139
+ def extract_http_params
140
+ @request.params rescue {}
141
+ end
142
+
143
+ def extract_client_id
144
+ session = @env["rack.session"] ? @env["rack.session"].to_hash : {}
145
+ warden_info = session.find { |k,v| k.start_with?('warden.') }
146
+ if warden_info
147
+ self.client_id = warden_info.last.first.first
148
+ else
149
+ self.client_id = ""
150
+ end
151
+ end
152
+
153
+ def build_json_payload
154
+ self.json = {
155
+ path: @request.path,
156
+ exception: event_name,
157
+ message: @exception.message,
158
+ component: @component,
159
+ method: @method,
160
+ environment_level: extract_rails_environment_level,
161
+ hostname: extract_hostname,
162
+ user_agent: @request.user_agent,
163
+ ruby_version: extract_ruby_version,
164
+ framework: extract_framework,
165
+ framework_version: extract_framework_version,
166
+ framework_params: extract_framework_params,
167
+ http_params: extract_http_params,
168
+ headers: extract_headers,
169
+ dependencies: extract_libraries_loaded,
170
+ backtrace: @backtrace
171
+ }
172
+ end
173
+
174
+ end
175
+ end
176
+ end