Commit 9c79849276ec0a292cc6fb5591837abe3d76aa83
Exists in
master
and in
1 other branch
Merge branch 'master' into features/extract_issue_tracker
Conflicts: Gemfile.lock
Showing
28 changed files
with
312 additions
and
137 deletions
Show diff stats
.travis.yml
| @@ -4,13 +4,14 @@ env: | @@ -4,13 +4,14 @@ env: | ||
| 4 | rvm: | 4 | rvm: |
| 5 | - 2.0.0 | 5 | - 2.0.0 |
| 6 | - 1.9.3 | 6 | - 1.9.3 |
| 7 | - - rbx-19mode | 7 | + - 2.1.2 |
| 8 | + - rbx-2 | ||
| 8 | - ruby-head | 9 | - ruby-head |
| 9 | services: mongodb | 10 | services: mongodb |
| 10 | #script: ./script/rspec-queue-mongoid.rb --format progress spec | 11 | #script: ./script/rspec-queue-mongoid.rb --format progress spec |
| 11 | matrix: | 12 | matrix: |
| 12 | allow_failures: | 13 | allow_failures: |
| 13 | - - rvm: rbx-19mode | 14 | + - rvm: rbx-2 |
| 14 | - rvm: ruby-head | 15 | - rvm: ruby-head |
| 15 | 16 | ||
| 16 | 17 |
CONTRIBUTORS.md
| @@ -42,11 +42,14 @@ | @@ -42,11 +42,14 @@ | ||
| 42 | - [@nashby][] | 42 | - [@nashby][] |
| 43 | - [@shingara][] | 43 | - [@shingara][] |
| 44 | - [@tscolari][] | 44 | - [@tscolari][] |
| 45 | +- [@callumd][] | ||
| 46 | + | ||
| 45 | 47 | ||
| 46 | [@anicet]: https://github.com/anicet | 48 | [@anicet]: https://github.com/anicet |
| 47 | [@nashby]: https://github.com/nashby | 49 | [@nashby]: https://github.com/nashby |
| 48 | [@shingara]: https://github.com/shingara | 50 | [@shingara]: https://github.com/shingara |
| 49 | [@tscolari]: https://github.com/tscolari | 51 | [@tscolari]: https://github.com/tscolari |
| 52 | +[@callumd]: https://github.com/callumd | ||
| 50 | 53 | ||
| 51 | ## 0.2.0 - 2013-09-11 | 54 | ## 0.2.0 - 2013-09-11 |
| 52 | 55 |
Gemfile
Gemfile.lock
| 1 | GEM | 1 | GEM |
| 2 | remote: https://rubygems.org/ | 2 | remote: https://rubygems.org/ |
| 3 | specs: | 3 | specs: |
| 4 | - actionmailer (3.2.18) | ||
| 5 | - actionpack (= 3.2.18) | 4 | + actionmailer (3.2.19) |
| 5 | + actionpack (= 3.2.19) | ||
| 6 | mail (~> 2.5.4) | 6 | mail (~> 2.5.4) |
| 7 | actionmailer_inline_css (1.5.3) | 7 | actionmailer_inline_css (1.5.3) |
| 8 | actionmailer (>= 3.0.0) | 8 | actionmailer (>= 3.0.0) |
| 9 | nokogiri (>= 1.4.4) | 9 | nokogiri (>= 1.4.4) |
| 10 | premailer (>= 1.7.1) | 10 | premailer (>= 1.7.1) |
| 11 | - actionpack (3.2.18) | ||
| 12 | - activemodel (= 3.2.18) | ||
| 13 | - activesupport (= 3.2.18) | 11 | + actionpack (3.2.19) |
| 12 | + activemodel (= 3.2.19) | ||
| 13 | + activesupport (= 3.2.19) | ||
| 14 | builder (~> 3.0.0) | 14 | builder (~> 3.0.0) |
| 15 | erubis (~> 2.7.0) | 15 | erubis (~> 2.7.0) |
| 16 | journey (~> 1.0.4) | 16 | journey (~> 1.0.4) |
| @@ -18,18 +18,18 @@ GEM | @@ -18,18 +18,18 @@ GEM | ||
| 18 | rack-cache (~> 1.2) | 18 | rack-cache (~> 1.2) |
| 19 | rack-test (~> 0.6.1) | 19 | rack-test (~> 0.6.1) |
| 20 | sprockets (~> 2.2.1) | 20 | sprockets (~> 2.2.1) |
| 21 | - activemodel (3.2.18) | ||
| 22 | - activesupport (= 3.2.18) | 21 | + activemodel (3.2.19) |
| 22 | + activesupport (= 3.2.19) | ||
| 23 | builder (~> 3.0.0) | 23 | builder (~> 3.0.0) |
| 24 | - activerecord (3.2.18) | ||
| 25 | - activemodel (= 3.2.18) | ||
| 26 | - activesupport (= 3.2.18) | 24 | + activerecord (3.2.19) |
| 25 | + activemodel (= 3.2.19) | ||
| 26 | + activesupport (= 3.2.19) | ||
| 27 | arel (~> 3.0.2) | 27 | arel (~> 3.0.2) |
| 28 | tzinfo (~> 0.3.29) | 28 | tzinfo (~> 0.3.29) |
| 29 | - activeresource (3.2.18) | ||
| 30 | - activemodel (= 3.2.18) | ||
| 31 | - activesupport (= 3.2.18) | ||
| 32 | - activesupport (3.2.18) | 29 | + activeresource (3.2.19) |
| 30 | + activemodel (= 3.2.19) | ||
| 31 | + activesupport (= 3.2.19) | ||
| 32 | + activesupport (3.2.19) | ||
| 33 | i18n (~> 0.6, >= 0.6.4) | 33 | i18n (~> 0.6, >= 0.6.4) |
| 34 | multi_json (~> 1.0) | 34 | multi_json (~> 1.0) |
| 35 | addressable (2.3.6) | 35 | addressable (2.3.6) |
| @@ -177,7 +177,7 @@ GEM | @@ -177,7 +177,7 @@ GEM | ||
| 177 | kgio (2.8.1) | 177 | kgio (2.8.1) |
| 178 | launchy (2.3.0) | 178 | launchy (2.3.0) |
| 179 | addressable (~> 2.3) | 179 | addressable (~> 2.3) |
| 180 | - libv8 (3.16.14.3) | 180 | + libv8 (3.16.14.7) |
| 181 | libxml-ruby (2.7.0) | 181 | libxml-ruby (2.7.0) |
| 182 | lighthouse-api (2.0) | 182 | lighthouse-api (2.0) |
| 183 | activeresource (>= 3.0.0) | 183 | activeresource (>= 3.0.0) |
| @@ -260,7 +260,7 @@ GEM | @@ -260,7 +260,7 @@ GEM | ||
| 260 | cliver (~> 0.3.1) | 260 | cliver (~> 0.3.1) |
| 261 | multi_json (~> 1.0) | 261 | multi_json (~> 1.0) |
| 262 | websocket-driver (>= 0.2.0) | 262 | websocket-driver (>= 0.2.0) |
| 263 | - polyglot (0.3.4) | 263 | + polyglot (0.3.5) |
| 264 | premailer (1.7.3) | 264 | premailer (1.7.3) |
| 265 | css_parser (>= 1.1.9) | 265 | css_parser (>= 1.1.9) |
| 266 | htmlentities (>= 4.0.0) | 266 | htmlentities (>= 4.0.0) |
| @@ -284,25 +284,25 @@ GEM | @@ -284,25 +284,25 @@ GEM | ||
| 284 | rack-ssl-enforcer (0.2.6) | 284 | rack-ssl-enforcer (0.2.6) |
| 285 | rack-test (0.6.2) | 285 | rack-test (0.6.2) |
| 286 | rack (>= 1.0) | 286 | rack (>= 1.0) |
| 287 | - rails (3.2.18) | ||
| 288 | - actionmailer (= 3.2.18) | ||
| 289 | - actionpack (= 3.2.18) | ||
| 290 | - activerecord (= 3.2.18) | ||
| 291 | - activeresource (= 3.2.18) | ||
| 292 | - activesupport (= 3.2.18) | 287 | + rails (3.2.19) |
| 288 | + actionmailer (= 3.2.19) | ||
| 289 | + actionpack (= 3.2.19) | ||
| 290 | + activerecord (= 3.2.19) | ||
| 291 | + activeresource (= 3.2.19) | ||
| 292 | + activesupport (= 3.2.19) | ||
| 293 | bundler (~> 1.0) | 293 | bundler (~> 1.0) |
| 294 | - railties (= 3.2.18) | 294 | + railties (= 3.2.19) |
| 295 | rails_autolink (1.1.4) | 295 | rails_autolink (1.1.4) |
| 296 | rails (> 3.1) | 296 | rails (> 3.1) |
| 297 | - railties (3.2.18) | ||
| 298 | - actionpack (= 3.2.18) | ||
| 299 | - activesupport (= 3.2.18) | 297 | + railties (3.2.19) |
| 298 | + actionpack (= 3.2.19) | ||
| 299 | + activesupport (= 3.2.19) | ||
| 300 | rack-ssl (~> 1.3.2) | 300 | rack-ssl (~> 1.3.2) |
| 301 | rake (>= 0.8.7) | 301 | rake (>= 0.8.7) |
| 302 | rdoc (~> 3.4) | 302 | rdoc (~> 3.4) |
| 303 | thor (>= 0.14.6, < 2.0) | 303 | thor (>= 0.14.6, < 2.0) |
| 304 | raindrops (0.12.0) | 304 | raindrops (0.12.0) |
| 305 | - rake (10.3.1) | 305 | + rake (10.3.2) |
| 306 | rdoc (3.12.2) | 306 | rdoc (3.12.2) |
| 307 | json (~> 1.4) | 307 | json (~> 1.4) |
| 308 | ref (1.0.5) | 308 | ref (1.0.5) |
| @@ -352,7 +352,7 @@ GEM | @@ -352,7 +352,7 @@ GEM | ||
| 352 | railties (~> 3.0) | 352 | railties (~> 3.0) |
| 353 | term-ansicolor (1.2.2) | 353 | term-ansicolor (1.2.2) |
| 354 | tins (~> 0.8) | 354 | tins (~> 0.8) |
| 355 | - therubyracer (0.12.0) | 355 | + therubyracer (0.12.1) |
| 356 | libv8 (~> 3.16.14.0) | 356 | libv8 (~> 3.16.14.0) |
| 357 | ref | 357 | ref |
| 358 | thor (0.19.1) | 358 | thor (0.19.1) |
| @@ -367,7 +367,7 @@ GEM | @@ -367,7 +367,7 @@ GEM | ||
| 367 | turbo-sprockets-rails3 (0.3.10) | 367 | turbo-sprockets-rails3 (0.3.10) |
| 368 | railties (> 3.2.8, < 4.0.0) | 368 | railties (> 3.2.8, < 4.0.0) |
| 369 | sprockets (>= 2.0.0) | 369 | sprockets (>= 2.0.0) |
| 370 | - tzinfo (0.3.39) | 370 | + tzinfo (0.3.41) |
| 371 | uglifier (2.2.1) | 371 | uglifier (2.2.1) |
| 372 | execjs (>= 0.3.0) | 372 | execjs (>= 0.3.0) |
| 373 | json (>= 1.8.0) | 373 | json (>= 1.8.0) |
| @@ -392,9 +392,9 @@ PLATFORMS | @@ -392,9 +392,9 @@ PLATFORMS | ||
| 392 | ruby | 392 | ruby |
| 393 | 393 | ||
| 394 | DEPENDENCIES | 394 | DEPENDENCIES |
| 395 | - actionmailer (~> 3.2.18) | 395 | + actionmailer (~> 3.2.19) |
| 396 | actionmailer_inline_css | 396 | actionmailer_inline_css |
| 397 | - actionpack (~> 3.2.18) | 397 | + actionpack (~> 3.2.19) |
| 398 | airbrake | 398 | airbrake |
| 399 | better_errors | 399 | better_errors |
| 400 | binding_of_caller | 400 | binding_of_caller |
| @@ -443,7 +443,7 @@ DEPENDENCIES | @@ -443,7 +443,7 @@ DEPENDENCIES | ||
| 443 | rack-ssl | 443 | rack-ssl |
| 444 | rack-ssl-enforcer | 444 | rack-ssl-enforcer |
| 445 | rails_autolink | 445 | rails_autolink |
| 446 | - railties (~> 3.2.18) | 446 | + railties (~> 3.2.19) |
| 447 | ri_cal | 447 | ri_cal |
| 448 | rspec-rails | 448 | rspec-rails |
| 449 | rushover | 449 | rushover |
README.md
| @@ -78,25 +78,20 @@ There is a demo available at [http://errbit-demo.herokuapp.com/](http://errbit-d | @@ -78,25 +78,20 @@ There is a demo available at [http://errbit-demo.herokuapp.com/](http://errbit-d | ||
| 78 | Email: demo@errbit-demo.herokuapp.com<br/> | 78 | Email: demo@errbit-demo.herokuapp.com<br/> |
| 79 | Password: password | 79 | Password: password |
| 80 | 80 | ||
| 81 | -# Requirement | 81 | +# Requirements |
| 82 | 82 | ||
| 83 | -The list of requirement to install Errbit is : | 83 | +The list of requirements to install Errbit are : |
| 84 | 84 | ||
| 85 | * Ruby 1.9.3 or higher | 85 | * Ruby 1.9.3 or higher |
| 86 | * MongoDB 2.2.0 or higher | 86 | * MongoDB 2.2.0 or higher |
| 87 | 87 | ||
| 88 | -By default it's the Ruby 2.0.0 to use. But you can define your own ruby | ||
| 89 | -version with RUBY_VERSION variable between : | ||
| 90 | - | ||
| 91 | - * 1.9.3 | ||
| 92 | - * 2.0.0 | ||
| 93 | - * 2.1.0 | 88 | +Errbit uses Ruby 2.0.0 as a default. However, it is compatible with Ruby 1.9.3 and above. |
| 94 | 89 | ||
| 95 | Installation | 90 | Installation |
| 96 | ------------ | 91 | ------------ |
| 97 | 92 | ||
| 98 | *Note*: This app is intended for people with experience deploying and maintaining | 93 | *Note*: This app is intended for people with experience deploying and maintaining |
| 99 | -Rails applications. If you're uncomfortable with any step below then Errbit is not | 94 | +Rails applications. If you're uncomfortable with any steps below then Errbit is not |
| 100 | for you. | 95 | for you. |
| 101 | 96 | ||
| 102 | **Set up your local box or server(Ubuntu):** | 97 | **Set up your local box or server(Ubuntu):** |
| @@ -108,10 +103,10 @@ apt-get update | @@ -108,10 +103,10 @@ apt-get update | ||
| 108 | apt-get install mongodb-10gen | 103 | apt-get install mongodb-10gen |
| 109 | ``` | 104 | ``` |
| 110 | 105 | ||
| 111 | - * Install libxml and libcurl | 106 | + * Install libxml, libzip, libssl and libcurl |
| 112 | 107 | ||
| 113 | ```bash | 108 | ```bash |
| 114 | -apt-get install libxml2 libxml2-dev libxslt-dev libcurl4-openssl-dev | 109 | +apt-get install libxml2 libxml2-dev libxslt-dev libcurl4-openssl-dev libzip-dev libssl-dev |
| 115 | ``` | 110 | ``` |
| 116 | 111 | ||
| 117 | * Install Bundler | 112 | * Install Bundler |
| @@ -179,9 +174,6 @@ heroku config:add HEROKU=true | @@ -179,9 +174,6 @@ heroku config:add HEROKU=true | ||
| 179 | heroku config:add SECRET_TOKEN="$(bundle exec rake secret)" | 174 | heroku config:add SECRET_TOKEN="$(bundle exec rake secret)" |
| 180 | heroku config:add ERRBIT_HOST=some-hostname.example.com | 175 | heroku config:add ERRBIT_HOST=some-hostname.example.com |
| 181 | heroku config:add ERRBIT_EMAIL_FROM=example@example.com | 176 | heroku config:add ERRBIT_EMAIL_FROM=example@example.com |
| 182 | -# This next line is required to access env variables during asset compilation. | ||
| 183 | -# For more info, go to this link: https://devcenter.heroku.com/articles/labs-user-env-compile | ||
| 184 | -heroku labs:enable user-env-compile | ||
| 185 | git push heroku master | 177 | git push heroku master |
| 186 | ``` | 178 | ``` |
| 187 | 179 | ||
| @@ -360,17 +352,16 @@ rake db:migrate | @@ -360,17 +352,16 @@ rake db:migrate | ||
| 360 | rake assets:precompile | 352 | rake assets:precompile |
| 361 | ``` | 353 | ``` |
| 362 | 354 | ||
| 363 | -If we change the way that data is stored, this will run any migrations to bring your database up to date. | 355 | +This will ensure that your application stays up to date with any schema changes. |
| 364 | 356 | ||
| 365 | 357 | ||
| 366 | -### Upgrade from errbit 0.2 to 0.3 | 358 | +### Upgrading errbit from version 0.2 to 0.3 |
| 367 | 359 | ||
| 368 | -The file of MongoDB connection config/mongoid.yml change between 0.2 to | ||
| 369 | -0.3. So Check the new config/mongoid.yml.example file and update it in | ||
| 370 | -good way. | 360 | +The MongoDB connection file `config/mongoid.yml` has changed between version 0.2 and |
| 361 | +0.3. We have provided a new example configuration file to use at `config/mongoid.example.yml`. | ||
| 371 | 362 | ||
| 372 | -This change is not need to be done if you use only ENV variable to | ||
| 373 | -define you access to MongoDB database. | 363 | +This change is not needed if you use ENV variables to |
| 364 | +define access to your MongoDB database. | ||
| 374 | 365 | ||
| 375 | 366 | ||
| 376 | ## User information in error reports | 367 | ## User information in error reports |
| @@ -379,11 +370,12 @@ Errbit can now display information about the user who experienced an error. | @@ -379,11 +370,12 @@ Errbit can now display information about the user who experienced an error. | ||
| 379 | This gives you the ability to ask the user for more information, | 370 | This gives you the ability to ask the user for more information, |
| 380 | and let them know when you've fixed the bug. | 371 | and let them know when you've fixed the bug. |
| 381 | 372 | ||
| 382 | -If you would like to include information about the current user in your error reports, | ||
| 383 | -you can replace the `airbrake` gem in your Gemfile with `airbrake_user_attributes`, | ||
| 384 | -which wraps the `airbrake` gem and injects user information. | ||
| 385 | -It will inject information about the current user into the error report | ||
| 386 | -if your Rails app's controller responds to a `#current_user` method. | 373 | +If you are running a Rails application and would like to include information |
| 374 | +about the current user in your error reports, you can replace the `airbrake` | ||
| 375 | +gem in your Gemfile with `airbrake_user_attributes`. | ||
| 376 | +This gem is a wrapper around the `airbrake` gem and will automatically | ||
| 377 | +inject information about the user into any error reports, | ||
| 378 | +so long as your controllers respond to a `#current_user` method. | ||
| 387 | The user's attributes are filtered to remove authentication fields. | 379 | The user's attributes are filtered to remove authentication fields. |
| 388 | 380 | ||
| 389 | If user information is received with an error report, | 381 | If user information is received with an error report, |
| @@ -394,26 +386,33 @@ it will be displayed under the *User Details* tab: | @@ -394,26 +386,33 @@ it will be displayed under the *User Details* tab: | ||
| 394 | 386 | ||
| 395 | (This tab will be hidden if no user information is available.) | 387 | (This tab will be hidden if no user information is available.) |
| 396 | 388 | ||
| 397 | -Adding javascript errors notifications | 389 | +Javascript error notifications |
| 398 | -------------------------------------- | 390 | -------------------------------------- |
| 399 | 391 | ||
| 400 | -Errbit easily supports javascript errors notifications. You just need to add `config.js_notifier = true` to the errbit initializer in the rails app. | 392 | +You can log javascript errors that occur in your application by following the directions below. |
| 393 | + | ||
| 394 | +# Rails Applications | ||
| 395 | + | ||
| 396 | +Add the following line to the `<head>` section of your application template. | ||
| 397 | + | ||
| 398 | +``` | ||
| 399 | +<%= airbrake_javascript_notifier %> | ||
| 400 | +``` | ||
| 401 | + | ||
| 402 | +# Other Platforms | ||
| 403 | + | ||
| 404 | +include the following before any javascript is loaded in your application. | ||
| 401 | 405 | ||
| 402 | ``` | 406 | ``` |
| 403 | -Errbit.configure do |config| | ||
| 404 | - config.host = 'YOUR-ERRBIT-HOST' | ||
| 405 | - config.api_key = 'YOUR-PROJECT-API-KEY' | ||
| 406 | - config.js_notifier = true | ||
| 407 | -end | 407 | +<script src='http://YOUR-ERRBIT-HOST/javascripts/notifier.js' type='text/javascript'></script> |
| 408 | ``` | 408 | ``` |
| 409 | 409 | ||
| 410 | -Then get the `notifier.js` from `errbit/public/javascript/notifier.js` and add to `application.js` on your rails app or include `http://YOUR-ERRBIT-HOST/javascripts/notifier.js` on your `application.html.erb.` | ||
| 411 | 410 | ||
| 412 | Using custom fingerprinting methods | 411 | Using custom fingerprinting methods |
| 413 | ----------------------------------- | 412 | ----------------------------------- |
| 414 | 413 | ||
| 415 | -Errbit now allows you to easily use your own Fingerprint Strategy if that's what you'd like to do. If you are upgrading from a very old version of errbit, you can use the `LegacyFingerprint` to provide yourself | ||
| 416 | -with compatibility. The fingerprint strategy can be changed by adding an initializer to errbit: | 414 | +Errbit allows you to use your own Fingerprinting Strategy. |
| 415 | +If you are upgrading from a very old version of errbit, you can use the `LegacyFingerprint` for compatibility. The fingerprint strategy can be changed by adding an initializer to errbit: | ||
| 417 | 416 | ||
| 418 | ```ruby | 417 | ```ruby |
| 419 | # config/fingerprint.rb | 418 | # config/fingerprint.rb |
| @@ -533,23 +532,18 @@ Solutions known to work are listed below: | @@ -533,23 +532,18 @@ Solutions known to work are listed below: | ||
| 533 | <table> | 532 | <table> |
| 534 | <tr> | 533 | <tr> |
| 535 | <th>PHP (>= 5.3)</th> | 534 | <th>PHP (>= 5.3)</th> |
| 536 | - <td>https://github.com/flippa/errbit-php</td> | 535 | + <td>[flippa/errbit-php](https://github.com/flippa/errbit-php)</td> |
| 537 | </tr> | 536 | </tr> |
| 538 | <tr> | 537 | <tr> |
| 539 | <th>OOP PHP (>= 5.3)</th> | 538 | <th>OOP PHP (>= 5.3)</th> |
| 540 | - <td>https://github.com/emgiezet/errbitPHP</td> | 539 | + <td>[emgiezet/errbitPHP](https://github.com/emgiezet/errbitPHP)</td> |
| 541 | </tr> | 540 | </tr> |
| 542 | <tr> | 541 | <tr> |
| 543 | <th>Python</th> | 542 | <th>Python</th> |
| 544 | - <td>https://github.com/mkorenkov/errbit.py , https://github.com/pulseenergy/airbrakepy</td> | 543 | + <td>[mkorenkov/errbit.py](https://github.com/mkorenkov/errbit.py) , [pulseenergy/airbrakepy](https://github.com/pulseenergy/airbrakepy)</td> |
| 545 | </tr> | 544 | </tr> |
| 546 | </table> | 545 | </table> |
| 547 | 546 | ||
| 548 | -Develop on Errbit | ||
| 549 | ------------------ | ||
| 550 | - | ||
| 551 | -A guide can help on this way on [**Errbit Advanced Developer Guide**](docs/DEVELOPER-ADVANCED.md) | ||
| 552 | - | ||
| 553 | ## Other documentation | 547 | ## Other documentation |
| 554 | 548 | ||
| 555 | * [All ENV variables availables to configure Errbit](docs/ENV-VARIABLES.md) | 549 | * [All ENV variables availables to configure Errbit](docs/ENV-VARIABLES.md) |
| @@ -582,7 +576,7 @@ Special Thanks | @@ -582,7 +576,7 @@ Special Thanks | ||
| 582 | See the [contributors graph](https://github.com/errbit/errbit/graphs/contributors) for further details. You can see another list of Contributors by release version on [CONTRIBUTORS.md] | 576 | See the [contributors graph](https://github.com/errbit/errbit/graphs/contributors) for further details. You can see another list of Contributors by release version on [CONTRIBUTORS.md] |
| 583 | 577 | ||
| 584 | 578 | ||
| 585 | -Contributing | 579 | +Contributing to Errbit |
| 586 | ------------ | 580 | ------------ |
| 587 | 581 | ||
| 588 | We welcome any contributions. If you need to tweak Errbit for your organization's needs, | 582 | We welcome any contributions. If you need to tweak Errbit for your organization's needs, |
| @@ -604,9 +598,13 @@ and make **optional** features configurable via `config/config.yml`. | @@ -604,9 +598,13 @@ and make **optional** features configurable via `config/config.yml`. | ||
| 604 | * Send us a pull request. Bonus points for topic branches. | 598 | * Send us a pull request. Bonus points for topic branches. |
| 605 | * Add you on the CONTRIBUTORS.md file on the current release | 599 | * Add you on the CONTRIBUTORS.md file on the current release |
| 606 | 600 | ||
| 601 | +# Running tests | ||
| 602 | + | ||
| 603 | +More information can be found in the [**Errbit Advanced Developer Guide**](docs/DEVELOPER-ADVANCED.md) | ||
| 604 | + | ||
| 607 | 605 | ||
| 608 | Copyright | 606 | Copyright |
| 609 | --------- | 607 | --------- |
| 610 | 608 | ||
| 611 | -Copyright (c) 2010-2013 Errbit Team. See LICENSE for details. | 609 | +Copyright (c) 2010-2014 Errbit Team. See LICENSE for details. |
| 612 | 610 |
app/controllers/api/v1/problems_controller.rb
| 1 | class Api::V1::ProblemsController < ApplicationController | 1 | class Api::V1::ProblemsController < ApplicationController |
| 2 | respond_to :json, :xml | 2 | respond_to :json, :xml |
| 3 | + FIELDS = %w{app_id app_name environment message where first_notice_at last_notice_at resolved resolved_at notices_count} | ||
| 4 | + | ||
| 5 | + def show | ||
| 6 | + result = benchmark("[api/v1/problems_controller/show] query time") do | ||
| 7 | + begin | ||
| 8 | + Problem.only(FIELDS).find(params[:id]) | ||
| 9 | + rescue Mongoid::Errors::DocumentNotFound | ||
| 10 | + head :not_found | ||
| 11 | + return false | ||
| 12 | + end | ||
| 13 | + end | ||
| 14 | + | ||
| 15 | + respond_to do |format| | ||
| 16 | + format.any(:html, :json) { render :json => result } # render JSON if no extension specified on path | ||
| 17 | + format.xml { render :xml => result } | ||
| 18 | + end | ||
| 19 | + end | ||
| 3 | 20 | ||
| 4 | def index | 21 | def index |
| 5 | query = {} | 22 | query = {} |
| 6 | - fields = %w{app_id app_name environment message where first_notice_at last_notice_at resolved resolved_at notices_count} | ||
| 7 | 23 | ||
| 8 | if params.key?(:start_date) && params.key?(:end_date) | 24 | if params.key?(:start_date) && params.key?(:end_date) |
| 9 | start_date = Time.parse(params[:start_date]).utc | 25 | start_date = Time.parse(params[:start_date]).utc |
| @@ -11,8 +27,8 @@ class Api::V1::ProblemsController < ApplicationController | @@ -11,8 +27,8 @@ class Api::V1::ProblemsController < ApplicationController | ||
| 11 | query = {:first_notice_at=>{"$lte"=>end_date}, "$or"=>[{:resolved_at=>nil}, {:resolved_at=>{"$gte"=>start_date}}]} | 27 | query = {:first_notice_at=>{"$lte"=>end_date}, "$or"=>[{:resolved_at=>nil}, {:resolved_at=>{"$gte"=>start_date}}]} |
| 12 | end | 28 | end |
| 13 | 29 | ||
| 14 | - results = benchmark("[api/v1/problems_controller] query time") do | ||
| 15 | - Problem.where(query).with(:consistency => :strong).only(fields).to_a | 30 | + results = benchmark("[api/v1/problems_controller/index] query time") do |
| 31 | + Problem.where(query).with(:consistency => :strong).only(FIELDS).to_a | ||
| 16 | end | 32 | end |
| 17 | 33 | ||
| 18 | respond_to do |format| | 34 | respond_to do |format| |
app/mailers/mailer.rb
| @@ -6,7 +6,12 @@ class Mailer < ActionMailer::Base | @@ -6,7 +6,12 @@ class Mailer < ActionMailer::Base | ||
| 6 | helper ApplicationHelper | 6 | helper ApplicationHelper |
| 7 | helper BacktraceLineHelper | 7 | helper BacktraceLineHelper |
| 8 | 8 | ||
| 9 | - default :from => Errbit::Config.email_from | 9 | + default :from => Errbit::Config.email_from, |
| 10 | + 'X-Errbit-Host' => Errbit::Config.host, | ||
| 11 | + 'X-Mailer' => 'Errbit', | ||
| 12 | + 'X-Auto-Response-Suppress' => 'OOF, AutoReply', | ||
| 13 | + 'Precedence' => 'bulk', | ||
| 14 | + 'Auto-Submitted' => 'auto-generated' | ||
| 10 | 15 | ||
| 11 | def err_notification(notice) | 16 | def err_notification(notice) |
| 12 | @notice = notice | 17 | @notice = notice |
| @@ -15,6 +20,10 @@ class Mailer < ActionMailer::Base | @@ -15,6 +20,10 @@ class Mailer < ActionMailer::Base | ||
| 15 | count = @notice.similar_count | 20 | count = @notice.similar_count |
| 16 | count = count > 1 ? "(#{count}) " : "" | 21 | count = count > 1 ? "(#{count}) " : "" |
| 17 | 22 | ||
| 23 | + errbit_headers 'App' => @app.name, | ||
| 24 | + 'Environment' => @notice.environment_name, | ||
| 25 | + 'Error-Id' => @notice.err_id | ||
| 26 | + | ||
| 18 | mail :to => @app.notification_recipients, | 27 | mail :to => @app.notification_recipients, |
| 19 | :subject => "#{count}[#{@app.name}][#{@notice.environment_name}] #{@notice.message.truncate(50)}" | 28 | :subject => "#{count}[#{@app.name}][#{@notice.environment_name}] #{@notice.message.truncate(50)}" |
| 20 | end | 29 | end |
| @@ -23,6 +32,11 @@ class Mailer < ActionMailer::Base | @@ -23,6 +32,11 @@ class Mailer < ActionMailer::Base | ||
| 23 | @deploy = deploy | 32 | @deploy = deploy |
| 24 | @app = deploy.app | 33 | @app = deploy.app |
| 25 | 34 | ||
| 35 | + errbit_headers 'App' => @app.name, | ||
| 36 | + 'Environment' => @deploy.environment, | ||
| 37 | + 'Deploy-Revision' => @deploy.revision, | ||
| 38 | + 'Deploy-User' => @deploy.username | ||
| 39 | + | ||
| 26 | mail :to => @app.notification_recipients, | 40 | mail :to => @app.notification_recipients, |
| 27 | :subject => "[#{@app.name}] Deployed to #{@deploy.environment} by #{@deploy.username}" | 41 | :subject => "[#{@app.name}] Deployed to #{@deploy.environment} by #{@deploy.username}" |
| 28 | end | 42 | end |
| @@ -36,7 +50,18 @@ class Mailer < ActionMailer::Base | @@ -36,7 +50,18 @@ class Mailer < ActionMailer::Base | ||
| 36 | 50 | ||
| 37 | recipients = @comment.notification_recipients | 51 | recipients = @comment.notification_recipients |
| 38 | 52 | ||
| 53 | + errbit_headers 'App' => @app.name, | ||
| 54 | + 'Environment' => @notice.environment_name, | ||
| 55 | + 'Problem-Id' => @problem.id, | ||
| 56 | + 'Comment-Author' => @user.name | ||
| 57 | + | ||
| 39 | mail :to => recipients, | 58 | mail :to => recipients, |
| 40 | :subject => "#{@user.name} commented on [#{@app.name}][#{@notice.environment_name}] #{@notice.message.truncate(50)}" | 59 | :subject => "#{@user.name} commented on [#{@app.name}][#{@notice.environment_name}] #{@notice.message.truncate(50)}" |
| 41 | end | 60 | end |
| 61 | + | ||
| 62 | + private | ||
| 63 | + | ||
| 64 | + def errbit_headers(header) | ||
| 65 | + header.each { |key,value| headers["X-Errbit-#{key}"] = value.to_s } | ||
| 66 | + end | ||
| 42 | end | 67 | end |
app/models/error_report.rb
| @@ -15,15 +15,18 @@ require 'hoptoad_notifier' | @@ -15,15 +15,18 @@ require 'hoptoad_notifier' | ||
| 15 | # * <tt>:notifier</tt> - information to identify the source of the error report | 15 | # * <tt>:notifier</tt> - information to identify the source of the error report |
| 16 | # | 16 | # |
| 17 | class ErrorReport | 17 | class ErrorReport |
| 18 | - attr_reader :error_class, :message, :request, :server_environment, :api_key, :notifier, :user_attributes, :framework | 18 | + attr_reader :error_class, :message, :request, :server_environment, :api_key, |
| 19 | + :notifier, :user_attributes, :framework, :notice | ||
| 19 | 20 | ||
| 20 | cattr_accessor :fingerprint_strategy do | 21 | cattr_accessor :fingerprint_strategy do |
| 21 | Fingerprint | 22 | Fingerprint |
| 22 | end | 23 | end |
| 23 | 24 | ||
| 24 | def initialize(xml_or_attributes) | 25 | def initialize(xml_or_attributes) |
| 25 | - @attributes = (xml_or_attributes.is_a?(String) ? Hoptoad.parse_xml!(xml_or_attributes) : xml_or_attributes).with_indifferent_access | ||
| 26 | - @attributes.each{|k, v| instance_variable_set(:"@#{k}", v) } | 26 | + @attributes = xml_or_attributes |
| 27 | + @attributes = Hoptoad.parse_xml!(@attributes) if @attributes.is_a? String | ||
| 28 | + @attributes = @attributes.with_indifferent_access | ||
| 29 | + @attributes.each { |k, v| instance_variable_set(:"@#{k}", v) } | ||
| 27 | end | 30 | end |
| 28 | 31 | ||
| 29 | def rails_env | 32 | def rails_env |
| @@ -33,30 +36,29 @@ class ErrorReport | @@ -33,30 +36,29 @@ class ErrorReport | ||
| 33 | end | 36 | end |
| 34 | 37 | ||
| 35 | def app | 38 | def app |
| 36 | - @app ||= App.where(:api_key => api_key).first | 39 | + @app ||= App.where(api_key: api_key).first |
| 37 | end | 40 | end |
| 38 | 41 | ||
| 39 | def backtrace | 42 | def backtrace |
| 40 | - @normalized_backtrace ||= Backtrace.find_or_create(:raw => @backtrace) | 43 | + @normalized_backtrace ||= Backtrace.find_or_create(raw: @backtrace) |
| 41 | end | 44 | end |
| 42 | 45 | ||
| 43 | def generate_notice! | 46 | def generate_notice! |
| 44 | return unless valid? | 47 | return unless valid? |
| 45 | return @notice if @notice | 48 | return @notice if @notice |
| 46 | @notice = Notice.new( | 49 | @notice = Notice.new( |
| 47 | - :message => message, | ||
| 48 | - :error_class => error_class, | ||
| 49 | - :backtrace_id => backtrace.id, | ||
| 50 | - :request => request, | ||
| 51 | - :server_environment => server_environment, | ||
| 52 | - :notifier => notifier, | ||
| 53 | - :user_attributes => user_attributes, | ||
| 54 | - :framework => framework | 50 | + message: message, |
| 51 | + error_class: error_class, | ||
| 52 | + backtrace_id: backtrace.id, | ||
| 53 | + request: request, | ||
| 54 | + server_environment: server_environment, | ||
| 55 | + notifier: notifier, | ||
| 56 | + user_attributes: user_attributes, | ||
| 57 | + framework: framework | ||
| 55 | ) | 58 | ) |
| 56 | error.notices << @notice | 59 | error.notices << @notice |
| 57 | @notice | 60 | @notice |
| 58 | end | 61 | end |
| 59 | - attr_reader :notice | ||
| 60 | 62 | ||
| 61 | ## | 63 | ## |
| 62 | # Error associate to this error_report | 64 | # Error associate to this error_report |
| @@ -66,23 +68,22 @@ class ErrorReport | @@ -66,23 +68,22 @@ class ErrorReport | ||
| 66 | # @return [ Error ] | 68 | # @return [ Error ] |
| 67 | def error | 69 | def error |
| 68 | @error ||= app.find_or_create_err!( | 70 | @error ||= app.find_or_create_err!( |
| 69 | - :error_class => error_class, | ||
| 70 | - :environment => rails_env, | ||
| 71 | - :fingerprint => fingerprint | 71 | + error_class: error_class, |
| 72 | + environment: rails_env, | ||
| 73 | + fingerprint: fingerprint | ||
| 72 | ) | 74 | ) |
| 73 | end | 75 | end |
| 74 | 76 | ||
| 75 | def valid? | 77 | def valid? |
| 76 | - !!app | 78 | + app.present? |
| 77 | end | 79 | end |
| 78 | 80 | ||
| 79 | def should_keep? | 81 | def should_keep? |
| 80 | app_version = server_environment['app-version'] || '' | 82 | app_version = server_environment['app-version'] || '' |
| 81 | - if self.app.current_app_version.present? && ( app_version.length <= 0 || Gem::Version.new(app_version) < Gem::Version.new(self.app.current_app_version) ) | ||
| 82 | - false | ||
| 83 | - else | ||
| 84 | - true | ||
| 85 | - end | 83 | + current_version = app.current_app_version |
| 84 | + return true unless current_version.present? | ||
| 85 | + return false if app_version.length <= 0 | ||
| 86 | + Gem::Version.new(app_version) >= Gem::Version.new(current_version) | ||
| 86 | end | 87 | end |
| 87 | 88 | ||
| 88 | private | 89 | private |
| @@ -90,5 +91,4 @@ class ErrorReport | @@ -90,5 +91,4 @@ class ErrorReport | ||
| 90 | def fingerprint | 91 | def fingerprint |
| 91 | @fingerprint ||= fingerprint_strategy.generate(notice, api_key) | 92 | @fingerprint ||= fingerprint_strategy.generate(notice, api_key) |
| 92 | end | 93 | end |
| 93 | - | ||
| 94 | end | 94 | end |
app/models/notification_service.rb
| @@ -54,6 +54,6 @@ class NotificationService | @@ -54,6 +54,6 @@ class NotificationService | ||
| 54 | end | 54 | end |
| 55 | 55 | ||
| 56 | def problem_url(problem) | 56 | def problem_url(problem) |
| 57 | - "http://#{Errbit::Config.host}/apps/#{problem.app.id}/problems/#{problem.id}" | 57 | + "#{Errbit::Config.protocol}://#{Errbit::Config.host}/apps/#{problem.app.id}/problems/#{problem.id}" |
| 58 | end | 58 | end |
| 59 | end | 59 | end |
app/models/notification_services/campfire_service.rb
| @@ -30,7 +30,7 @@ if defined? Campy | @@ -30,7 +30,7 @@ if defined? Campy | ||
| 30 | # build the campfire client | 30 | # build the campfire client |
| 31 | campy = Campy::Room.new(:account => subdomain, :token => api_token, :room_id => room_id) | 31 | campy = Campy::Room.new(:account => subdomain, :token => api_token, :room_id => room_id) |
| 32 | # post the issue to the campfire room | 32 | # post the issue to the campfire room |
| 33 | - campy.speak "[errbit] #{problem.app.name} #{notification_description problem} - http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s}/problems/#{problem.id.to_s}" | 33 | + campy.speak "[errbit] #{problem.app.name} #{notification_description problem} - #{Errbit::Config.protocol}://#{Errbit::Config.host}/apps/#{problem.app.id.to_s}/problems/#{problem.id.to_s}" |
| 34 | end | 34 | end |
| 35 | end | 35 | end |
| 36 | end | 36 | end |
app/models/notification_services/gtalk_service.rb
| @@ -47,7 +47,7 @@ class NotificationServices::GtalkService < NotificationService | @@ -47,7 +47,7 @@ class NotificationServices::GtalkService < NotificationService | ||
| 47 | 47 | ||
| 48 | #has to look like this to be formatted properly in the client | 48 | #has to look like this to be formatted properly in the client |
| 49 | message = """#{problem.app.name.to_s} | 49 | message = """#{problem.app.name.to_s} |
| 50 | -http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} | 50 | +#{Errbit::Config.protocol}://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} |
| 51 | #{notification_description problem}""" | 51 | #{notification_description problem}""" |
| 52 | 52 | ||
| 53 | # post the issue to the xmpp room(s) | 53 | # post the issue to the xmpp room(s) |
app/models/notification_services/hoiio_service.rb
| @@ -35,7 +35,7 @@ class NotificationServices::HoiioService < NotificationService | @@ -35,7 +35,7 @@ class NotificationServices::HoiioService < NotificationService | ||
| 35 | 35 | ||
| 36 | # send sms | 36 | # send sms |
| 37 | room_id.split(',').each do |number| | 37 | room_id.split(',').each do |number| |
| 38 | - sms.send :dest => number, :msg => "http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} #{notification_description problem}" | 38 | + sms.send :dest => number, :msg => "#{Errbit::Config.protocol}://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} #{notification_description problem}" |
| 39 | end | 39 | end |
| 40 | 40 | ||
| 41 | end | 41 | end |
app/models/notification_services/pushover_service.rb
| @@ -26,7 +26,7 @@ class NotificationServices::PushoverService < NotificationService | @@ -26,7 +26,7 @@ class NotificationServices::PushoverService < NotificationService | ||
| 26 | notification = Rushover::Client.new(subdomain) | 26 | notification = Rushover::Client.new(subdomain) |
| 27 | 27 | ||
| 28 | # send push notification to pushover | 28 | # send push notification to pushover |
| 29 | - notification.notify(api_token, "#{notification_description problem}", :priority => 1, :title => "Errbit Notification", :url => "http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s}", :url_title => "Link to error") | 29 | + notification.notify(api_token, "#{notification_description problem}", :priority => 1, :title => "Errbit Notification", :url => "#{Errbit::Config.protocol}://#{Errbit::Config.host}/apps/#{problem.app.id.to_s}", :url_title => "Link to error") |
| 30 | 30 | ||
| 31 | end | 31 | end |
| 32 | end | 32 | end |
app/models/problem.rb
| @@ -50,7 +50,6 @@ class Problem | @@ -50,7 +50,6 @@ class Problem | ||
| 50 | 50 | ||
| 51 | validates_presence_of :last_notice_at, :first_notice_at | 51 | validates_presence_of :last_notice_at, :first_notice_at |
| 52 | 52 | ||
| 53 | - | ||
| 54 | def self.all_else_unresolved(fetch_all) | 53 | def self.all_else_unresolved(fetch_all) |
| 55 | if fetch_all | 54 | if fetch_all |
| 56 | all | 55 | all |
app/views/apps/show.html.haml
| @@ -88,8 +88,7 @@ | @@ -88,8 +88,7 @@ | ||
| 88 | - if app.problems.any? | 88 | - if app.problems.any? |
| 89 | %h3.clear=t('.errors') | 89 | %h3.clear=t('.errors') |
| 90 | %section | 90 | %section |
| 91 | - = form_tag search_problems_path(:all_errs => all_errs, :app_id => app.id), :method => :get, :remote => true do | ||
| 92 | - = text_field_tag :search, params[:search], :placeholder => t('.search_placeholder') | 91 | + = render 'problems/search', :all_errs => @all_errs, :app_id => app.id |
| 93 | %br | 92 | %br |
| 94 | %section | 93 | %section |
| 95 | .problem_table{:id => 'problem_table'} | 94 | .problem_table{:id => 'problem_table'} |
app/views/problems/index.html.haml
| @@ -9,8 +9,7 @@ | @@ -9,8 +9,7 @@ | ||
| 9 | = link_to 'show resolved', problems_path(:all_errs => true), :class => 'button' | 9 | = link_to 'show resolved', problems_path(:all_errs => true), :class => 'button' |
| 10 | 10 | ||
| 11 | %section | 11 | %section |
| 12 | - = form_tag search_problems_path(:all_errs => @all_errs), :method => :get, :remote => true do | ||
| 13 | - = text_field_tag :search, params[:search], :placeholder => 'Search for issues' | 12 | + = render 'problems/search', :all_errs => @all_errs, :app_id => nil |
| 14 | %br | 13 | %br |
| 15 | %section | 14 | %section |
| 16 | #problem_table.problem_table | 15 | #problem_table.problem_table |
config/cloud/cloud66/files/_load_config.rb
| @@ -17,6 +17,7 @@ unless defined?(Errbit::Config) | @@ -17,6 +17,7 @@ unless defined?(Errbit::Config) | ||
| 17 | Errbit::Config.use_gravatar = ENV['ERRBIT_USE_GRAVATAR'] | 17 | Errbit::Config.use_gravatar = ENV['ERRBIT_USE_GRAVATAR'] |
| 18 | Errbit::Config.gravatar_default = ENV['ERRBIT_GRAVATAR_DEFAULT'] | 18 | Errbit::Config.gravatar_default = ENV['ERRBIT_GRAVATAR_DEFAULT'] |
| 19 | 19 | ||
| 20 | + Errbit::Config.github_url = ENV['GITHUB_URL'] | ||
| 20 | Errbit::Config.github_authentication = ENV['GITHUB_AUTHENTICATION'] | 21 | Errbit::Config.github_authentication = ENV['GITHUB_AUTHENTICATION'] |
| 21 | Errbit::Config.github_client_id = ENV['GITHUB_CLIENT_ID'] | 22 | Errbit::Config.github_client_id = ENV['GITHUB_CLIENT_ID'] |
| 22 | Errbit::Config.github_secret = ENV['GITHUB_SECRET'] | 23 | Errbit::Config.github_secret = ENV['GITHUB_SECRET'] |
config/initializers/_load_config.rb
| @@ -6,9 +6,12 @@ unless defined?(Errbit::Config) | @@ -6,9 +6,12 @@ unless defined?(Errbit::Config) | ||
| 6 | Errbit::Config = OpenStruct.new | 6 | Errbit::Config = OpenStruct.new |
| 7 | use_env = ENV['HEROKU'] || ENV['USE_ENV'] | 7 | use_env = ENV['HEROKU'] || ENV['USE_ENV'] |
| 8 | 8 | ||
| 9 | + Errbit::Config.protocol = 'http' | ||
| 10 | + | ||
| 9 | # If Errbit is running on Heroku, config can be set from environment variables. | 11 | # If Errbit is running on Heroku, config can be set from environment variables. |
| 10 | if use_env | 12 | if use_env |
| 11 | Errbit::Config.host = ENV['ERRBIT_HOST'] | 13 | Errbit::Config.host = ENV['ERRBIT_HOST'] |
| 14 | + Errbit::Config.protocol = ENV['ERRBIT_PROTOCOL'] || 'http' | ||
| 12 | Errbit::Config.port = ENV['ERRBIT_PORT'] | 15 | Errbit::Config.port = ENV['ERRBIT_PORT'] |
| 13 | Errbit::Config.email_from = ENV['ERRBIT_EMAIL_FROM'] | 16 | Errbit::Config.email_from = ENV['ERRBIT_EMAIL_FROM'] |
| 14 | # Not really easy to use like an env because need an array and ENV return a string :( | 17 | # Not really easy to use like an env because need an array and ENV return a string :( |
| @@ -34,7 +37,8 @@ unless defined?(Errbit::Config) | @@ -34,7 +37,8 @@ unless defined?(Errbit::Config) | ||
| 34 | :authentication => :plain, | 37 | :authentication => :plain, |
| 35 | :user_name => ENV['SMTP_USERNAME'] || ENV['SENDGRID_USERNAME'], | 38 | :user_name => ENV['SMTP_USERNAME'] || ENV['SENDGRID_USERNAME'], |
| 36 | :password => ENV['SMTP_PASSWORD'] || ENV['SENDGRID_PASSWORD'], | 39 | :password => ENV['SMTP_PASSWORD'] || ENV['SENDGRID_PASSWORD'], |
| 37 | - :domain => ENV['SMTP_DOMAIN'] || ENV['SENDGRID_DOMAIN'] || ENV['ERRBIT_EMAIL_FROM'].split('@').last | 40 | + :domain => ENV['SMTP_DOMAIN'] || ENV['SENDGRID_DOMAIN'] || |
| 41 | + (ENV['ERRBIT_EMAIL_FROM'] ? ENV['ERRBIT_EMAIL_FROM'].split('@').last : nil) | ||
| 38 | } | 42 | } |
| 39 | end | 43 | end |
| 40 | 44 |
config/initializers/mongo.rb
| @@ -6,7 +6,7 @@ if config_file.file? && | @@ -6,7 +6,7 @@ if config_file.file? && | ||
| 6 | elsif ENV['HEROKU'] || ENV['USE_ENV'] | 6 | elsif ENV['HEROKU'] || ENV['USE_ENV'] |
| 7 | # No mongoid.yml file. Use ENV variable to define your MongoDB | 7 | # No mongoid.yml file. Use ENV variable to define your MongoDB |
| 8 | # configuration | 8 | # configuration |
| 9 | - if mongo = ENV['MONGOLAB_URI'] || ENV['MONGOHQ_URL'] || ENV['MONGODB_URL'] | 9 | + if mongo = ENV['MONGOLAB_URI'] || ENV['MONGOHQ_URL'] || ENV['MONGODB_URL'] || ENV['MONGO_URL'] |
| 10 | settings = URI.parse(mongo) | 10 | settings = URI.parse(mongo) |
| 11 | database_name = settings.path.gsub(/^\//, '') | 11 | database_name = settings.path.gsub(/^\//, '') |
| 12 | else | 12 | else |
config/locales/en.yml
| @@ -77,6 +77,8 @@ en: | @@ -77,6 +77,8 @@ en: | ||
| 77 | merge: "Merge select issues? They can be unmerged later." | 77 | merge: "Merge select issues? They can be unmerged later." |
| 78 | unmerge: "Unmerge selected issues? They can be re-merged later." | 78 | unmerge: "Unmerge selected issues? They can be re-merged later." |
| 79 | unresolve: "Unresolve selected issues? They can be resolved again later." | 79 | unresolve: "Unresolve selected issues? They can be resolved again later." |
| 80 | + search: | ||
| 81 | + search_placeholder: 'Search for issues' | ||
| 80 | 82 | ||
| 81 | comments: | 83 | comments: |
| 82 | confirm_delete: "Permanently delete this comment?" | 84 | confirm_delete: "Permanently delete this comment?" |
| @@ -118,7 +120,6 @@ en: | @@ -118,7 +120,6 @@ en: | ||
| 118 | no_watcher: "Sadly, no one is watching this app" | 120 | no_watcher: "Sadly, no one is watching this app" |
| 119 | repository: Repository | 121 | repository: Repository |
| 120 | revision: Revision | 122 | revision: Revision |
| 121 | - search_placeholder: 'Search for issues' | ||
| 122 | show_hide: "(show/hide)" | 123 | show_hide: "(show/hide)" |
| 123 | unresolved_errs: unresolved errs | 124 | unresolved_errs: unresolved errs |
| 124 | unwatch: unwatch | 125 | unwatch: unwatch |
config/routes.rb
| @@ -50,7 +50,7 @@ Errbit::Application.routes.draw do | @@ -50,7 +50,7 @@ Errbit::Application.routes.draw do | ||
| 50 | 50 | ||
| 51 | namespace :api do | 51 | namespace :api do |
| 52 | namespace :v1 do | 52 | namespace :v1 do |
| 53 | - resources :problems, :only => [:index], :defaults => { :format => 'json' } | 53 | + resources :problems, :only => [:index, :show], :defaults => { :format => 'json' } |
| 54 | resources :notices, :only => [:index], :defaults => { :format => 'json' } | 54 | resources :notices, :only => [:index], :defaults => { :format => 'json' } |
| 55 | resources :stats, :only => [], :defaults => { :format => 'json' } do | 55 | resources :stats, :only => [], :defaults => { :format => 'json' } do |
| 56 | collection do | 56 | collection do |
public/robots.txt
| 1 | # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file | 1 | # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file |
| 2 | -# | ||
| 3 | -# To ban all spiders from the entire site uncomment the next two lines: | ||
| 4 | -# User-Agent: * | ||
| 5 | -# Disallow: / | 2 | +User-Agent: * |
| 3 | +Disallow: / |
spec/controllers/api/v1/problems_controller_spec.rb
| @@ -7,6 +7,70 @@ describe Api::V1::ProblemsController do | @@ -7,6 +7,70 @@ describe Api::V1::ProblemsController do | ||
| 7 | @user = Fabricate(:user) | 7 | @user = Fabricate(:user) |
| 8 | end | 8 | end |
| 9 | 9 | ||
| 10 | + describe "GET /api/v1/problems/:id" do | ||
| 11 | + before do | ||
| 12 | + notice = Fabricate(:notice) | ||
| 13 | + err = Fabricate(:err, :notices => [notice]) | ||
| 14 | + @problem = Fabricate(:problem, :errs => [err]) | ||
| 15 | + end | ||
| 16 | + | ||
| 17 | + it "should return JSON if JSON is requested" do | ||
| 18 | + get :show, :auth_token => @user.authentication_token, :format => "json", :id => Problem.first.id | ||
| 19 | + expect { JSON.load(response.body) }.not_to raise_error() #JSON::ParserError | ||
| 20 | + end | ||
| 21 | + | ||
| 22 | + it "should return XML if XML is requested" do | ||
| 23 | + get :index, :auth_token => @user.authentication_token, :format => "xml", :id => @problem.id | ||
| 24 | + expect(Nokogiri::XML(response.body).errors).to be_empty | ||
| 25 | + end | ||
| 26 | + | ||
| 27 | + it "should return JSON by default" do | ||
| 28 | + get :show, :auth_token => @user.authentication_token, :id => @problem.id | ||
| 29 | + expect { JSON.load(response.body) }.not_to raise_error()#JSON::ParserError) | ||
| 30 | + end | ||
| 31 | + | ||
| 32 | + it "should return the correct problem" do | ||
| 33 | + get :show, :auth_token => @user.authentication_token, :format => "json", :id => @problem.id | ||
| 34 | + | ||
| 35 | + returned_problem = JSON.parse(response.body) | ||
| 36 | + expect( returned_problem["_id"] ).to eq(@problem.id.to_s) | ||
| 37 | + end | ||
| 38 | + | ||
| 39 | + it "should return only the correct fields" do | ||
| 40 | + get :show, :auth_token => @user.authentication_token, :format => "json", :id => @problem.id | ||
| 41 | + returned_problem = JSON.parse(response.body) | ||
| 42 | + | ||
| 43 | + expect( returned_problem.keys ).to match_array([ | ||
| 44 | + "app_name", | ||
| 45 | + "first_notice_at", | ||
| 46 | + "error_class", | ||
| 47 | + "messages", | ||
| 48 | + "hosts", | ||
| 49 | + "created_at", | ||
| 50 | + "app_id", | ||
| 51 | + "last_notice_at", | ||
| 52 | + "_id", | ||
| 53 | + "issue_link", | ||
| 54 | + "resolved", | ||
| 55 | + "updated_at", | ||
| 56 | + "resolved_at", | ||
| 57 | + "last_deploy_at", | ||
| 58 | + "where", | ||
| 59 | + "issue_type", | ||
| 60 | + "notices_count", | ||
| 61 | + "user_agents", | ||
| 62 | + "comments_count", | ||
| 63 | + "message", | ||
| 64 | + "environment" | ||
| 65 | + ]) | ||
| 66 | + end | ||
| 67 | + | ||
| 68 | + it "returns a 404 if the problem cannot be found" do | ||
| 69 | + get :show, :auth_token => @user.authentication_token, :format => "json", :id => 'IdontExist' | ||
| 70 | + expect( response.status ).to eq(404) | ||
| 71 | + end | ||
| 72 | + end | ||
| 73 | + | ||
| 10 | describe "GET /api/v1/problems" do | 74 | describe "GET /api/v1/problems" do |
| 11 | before do | 75 | before do |
| 12 | Fabricate(:problem, :first_notice_at => Date.new(2012, 8, 01), :resolved_at => Date.new(2012, 8, 02)) | 76 | Fabricate(:problem, :first_notice_at => Date.new(2012, 8, 01), :resolved_at => Date.new(2012, 8, 02)) |
spec/controllers/problems_controller_spec.rb
| @@ -124,6 +124,31 @@ describe ProblemsController do | @@ -124,6 +124,31 @@ describe ProblemsController do | ||
| 124 | end | 124 | end |
| 125 | end | 125 | end |
| 126 | 126 | ||
| 127 | + describe "GET /problems/search" do | ||
| 128 | + before do | ||
| 129 | + sign_in Fabricate(:admin) | ||
| 130 | + @app = Fabricate(:app) | ||
| 131 | + @problem1 = Fabricate(:problem, :app=>@app, message: "Most important") | ||
| 132 | + @problem2 = Fabricate(:problem, :app=>@app, message: "Very very important") | ||
| 133 | + end | ||
| 134 | + | ||
| 135 | + it "renders successfully" do | ||
| 136 | + get :search | ||
| 137 | + expect(response).to be_success | ||
| 138 | + end | ||
| 139 | + | ||
| 140 | + it "renders index template" do | ||
| 141 | + get :search | ||
| 142 | + expect(response).to render_template('problems/index') | ||
| 143 | + end | ||
| 144 | + | ||
| 145 | + it "searches problems for given string" do | ||
| 146 | + get :search, :search => "Most important" | ||
| 147 | + expect(controller.problems).to include(@problem1) | ||
| 148 | + expect(controller.problems).to_not include(@problem2) | ||
| 149 | + end | ||
| 150 | + end | ||
| 151 | + | ||
| 127 | describe "GET /apps/:app_id/problems/:id" do | 152 | describe "GET /apps/:app_id/problems/:id" do |
| 128 | #render_views | 153 | #render_views |
| 129 | 154 |
spec/mailers/mailer_spec.rb
| 1 | require 'spec_helper' | 1 | require 'spec_helper' |
| 2 | 2 | ||
| 3 | +shared_examples "a notification email" do | ||
| 4 | + it "should have X-Mailer header" do | ||
| 5 | + expect(@email).to have_header('X-Mailer', 'Errbit') | ||
| 6 | + end | ||
| 7 | + | ||
| 8 | + it "should have X-Errbit-Host header" do | ||
| 9 | + expect(@email).to have_header('X-Errbit-Host', Errbit::Config.host) | ||
| 10 | + end | ||
| 11 | + | ||
| 12 | + it "should have Precedence header" do | ||
| 13 | + expect(@email).to have_header('Precedence', 'bulk') | ||
| 14 | + end | ||
| 15 | + | ||
| 16 | + it "should have Auto-Submitted header" do | ||
| 17 | + expect(@email).to have_header('Auto-Submitted', 'auto-generated') | ||
| 18 | + end | ||
| 19 | + | ||
| 20 | + it "should have X-Auto-Response-Suppress header" do | ||
| 21 | + # http://msdn.microsoft.com/en-us/library/ee219609(v=EXCHG.80).aspx | ||
| 22 | + expect(@email).to have_header('X-Auto-Response-Suppress', 'OOF, AutoReply') | ||
| 23 | + end | ||
| 24 | + | ||
| 25 | + it "should send the email" do | ||
| 26 | + expect(ActionMailer::Base.deliveries.size).to eq 1 | ||
| 27 | + end | ||
| 28 | +end | ||
| 29 | + | ||
| 3 | describe Mailer do | 30 | describe Mailer do |
| 4 | context "Err Notification" do | 31 | context "Err Notification" do |
| 5 | include EmailSpec::Helpers | 32 | include EmailSpec::Helpers |
| @@ -19,9 +46,8 @@ describe Mailer do | @@ -19,9 +46,8 @@ describe Mailer do | ||
| 19 | @email = Mailer.err_notification(notice).deliver | 46 | @email = Mailer.err_notification(notice).deliver |
| 20 | end | 47 | end |
| 21 | 48 | ||
| 22 | - it "should send the email" do | ||
| 23 | - expect(ActionMailer::Base.deliveries.size).to eq 1 | ||
| 24 | - end | 49 | + it_should_behave_like "a notification email" |
| 50 | + | ||
| 25 | 51 | ||
| 26 | it "should html-escape the notice's message for the html part" do | 52 | it "should html-escape the notice's message for the html part" do |
| 27 | expect(@email).to have_body_text("class < ActionController::Base") | 53 | expect(@email).to have_body_text("class < ActionController::Base") |
| @@ -62,10 +88,6 @@ describe Mailer do | @@ -62,10 +88,6 @@ describe Mailer do | ||
| 62 | @email = Mailer.comment_notification(comment).deliver | 88 | @email = Mailer.comment_notification(comment).deliver |
| 63 | end | 89 | end |
| 64 | 90 | ||
| 65 | - it "should send the email" do | ||
| 66 | - expect(ActionMailer::Base.deliveries.size).to eq 1 | ||
| 67 | - end | ||
| 68 | - | ||
| 69 | it "should be sent to comment notification recipients" do | 91 | it "should be sent to comment notification recipients" do |
| 70 | expect(@email.to).to eq recipients | 92 | expect(@email.to).to eq recipients |
| 71 | end | 93 | end |
spec/models/notification_service/gtalk_service_spec.rb
| @@ -17,7 +17,7 @@ describe NotificationService::GtalkService do | @@ -17,7 +17,7 @@ describe NotificationService::GtalkService do | ||
| 17 | expect(gtalk).to receive(:connect).with(notification_service.service) | 17 | expect(gtalk).to receive(:connect).with(notification_service.service) |
| 18 | expect(gtalk).to receive(:auth).with(notification_service.api_token) | 18 | expect(gtalk).to receive(:auth).with(notification_service.api_token) |
| 19 | message_value = """#{problem.app.name.to_s} | 19 | message_value = """#{problem.app.name.to_s} |
| 20 | -http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} | 20 | +#{Errbit::Config.protocol}://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} |
| 21 | #{notification_service.notification_description problem}""" | 21 | #{notification_service.notification_description problem}""" |
| 22 | 22 | ||
| 23 | expect(Jabber::Message).to receive(:new).with(notification_service.user_id, message_value).and_return(message) | 23 | expect(Jabber::Message).to receive(:new).with(notification_service.user_id, message_value).and_return(message) |
| @@ -39,7 +39,7 @@ http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} | @@ -39,7 +39,7 @@ http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} | ||
| 39 | @notification_service = Fabricate :gtalk_notification_service, :app => @notice.app | 39 | @notification_service = Fabricate :gtalk_notification_service, :app => @notice.app |
| 40 | @problem = @notice.problem | 40 | @problem = @notice.problem |
| 41 | @error_msg = """#{@problem.app.name.to_s} | 41 | @error_msg = """#{@problem.app.name.to_s} |
| 42 | -http://#{Errbit::Config.host}/apps/#{@problem.app.id.to_s} | 42 | +#{Errbit::Config.protocol}://#{Errbit::Config.host}/apps/#{@problem.app.id.to_s} |
| 43 | #{@notification_service.notification_description @problem}""" | 43 | #{@notification_service.notification_description @problem}""" |
| 44 | 44 | ||
| 45 | # gtalk stubbing | 45 | # gtalk stubbing |
| @@ -105,7 +105,7 @@ http://#{Errbit::Config.host}/apps/#{@problem.app.id.to_s} | @@ -105,7 +105,7 @@ http://#{Errbit::Config.host}/apps/#{@problem.app.id.to_s} | ||
| 105 | expect(gtalk).to receive(:connect) | 105 | expect(gtalk).to receive(:connect) |
| 106 | expect(gtalk).to receive(:auth).with(notification_service.api_token) | 106 | expect(gtalk).to receive(:auth).with(notification_service.api_token) |
| 107 | message_value = """#{problem.app.name.to_s} | 107 | message_value = """#{problem.app.name.to_s} |
| 108 | -http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} | 108 | +#{Errbit::Config.protocol}://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} |
| 109 | #{notification_service.notification_description problem}""" | 109 | #{notification_service.notification_description problem}""" |
| 110 | 110 | ||
| 111 | expect(Jabber::Message).to receive(:new).with(notification_service.room_id, message_value).and_return(message) | 111 | expect(Jabber::Message).to receive(:new).with(notification_service.room_id, message_value).and_return(message) |
spec/models/notification_service/notification_service_spec.rb
0 → 100644
| @@ -0,0 +1,18 @@ | @@ -0,0 +1,18 @@ | ||
| 1 | +require 'spec_helper' | ||
| 2 | + | ||
| 3 | +describe NotificationService do | ||
| 4 | + | ||
| 5 | + let(:notice) { Fabricate :notice } | ||
| 6 | + let(:notification_service) { Fabricate :notification_service, :app => notice.app } | ||
| 7 | + let(:problem) { notice.problem } | ||
| 8 | + | ||
| 9 | + it "it should use http by default in #problem_url" do | ||
| 10 | + notification_service.problem_url(problem).should start_with 'http://' | ||
| 11 | + end | ||
| 12 | + | ||
| 13 | + it "it should use the protocol value specified in the config in #problem_url" do | ||
| 14 | + Errbit::Config.protocol = 'https' | ||
| 15 | + notification_service.problem_url(problem).should start_with 'https://' | ||
| 16 | + end | ||
| 17 | + | ||
| 18 | +end |