rearview 1.1.2-jruby → 1.2.0-jruby

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 (106) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -3
  3. data/app/controllers/rearview/application_controller.rb +11 -0
  4. data/app/controllers/rearview/dashboard_children_controller.rb +1 -1
  5. data/app/controllers/rearview/dashboards_controller.rb +1 -1
  6. data/app/controllers/rearview/home_controller.rb +1 -1
  7. data/app/controllers/rearview/jobs_controller.rb +33 -29
  8. data/app/controllers/rearview/monitor_controller.rb +16 -2
  9. data/app/controllers/rearview/user_controller.rb +2 -2
  10. data/app/helpers/rearview/application_helper.rb +3 -3
  11. data/app/mailers/rearview/alert_mailer.rb +0 -2
  12. data/app/mailers/rearview/metrics_validation_mailer.rb +12 -0
  13. data/app/models/rearview/job.rb +17 -13
  14. data/app/views/rearview/home/show.html.erb +2 -0
  15. data/app/views/rearview/jobs/_job.json.jbuilder +1 -0
  16. data/app/views/rearview/metrics_validation_mailer/validation_failed_email.text.erb +13 -0
  17. data/app/views/rearview/monitor/create.json.jbuilder +1 -0
  18. data/db/migrate/20131106162900_base_schema.rb +2 -2
  19. data/lib/generators/templates/rearview.rb +24 -7
  20. data/lib/graphite.rb +13 -0
  21. data/lib/graphite/cacerts.pem +2184 -0
  22. data/lib/graphite/client.rb +44 -0
  23. data/lib/graphite/graph.rb +35 -0
  24. data/lib/{rearview/graphite_parser.rb → graphite/raw_parser.rb} +2 -3
  25. data/lib/graphite/target.rb +9 -0
  26. data/lib/graphite/target_grammer.rb +114 -0
  27. data/lib/graphite/target_grammer.treetop +53 -0
  28. data/lib/graphite/target_parser.rb +50 -0
  29. data/lib/graphite/treetop_ext.rb +14 -0
  30. data/lib/rearview.rb +11 -3
  31. data/lib/rearview/alerts_handler.rb +2 -6
  32. data/lib/rearview/configuration.rb +44 -19
  33. data/lib/rearview/cron_expression_validator.rb +11 -0
  34. data/lib/rearview/metrics_validator.rb +52 -0
  35. data/lib/rearview/metrics_validator_service.rb +24 -0
  36. data/lib/rearview/metrics_validator_task.rb +56 -0
  37. data/lib/rearview/monitor_runner.rb +9 -7
  38. data/lib/rearview/monitor_service.rb +2 -0
  39. data/lib/rearview/stats_service.rb +4 -2
  40. data/lib/rearview/version.rb +1 -1
  41. data/lib/tasks/rearview_tasks.rake +7 -1
  42. data/public/{help → rearview-src/help}/alert.html +0 -0
  43. data/public/{help → rearview-src/help}/quick.html +0 -0
  44. data/public/rearview-src/js/app.js +9 -0
  45. data/public/rearview-src/js/model/user.js +6 -2
  46. data/public/rearview-src/js/view/addmonitor.js +13 -8
  47. data/public/rearview-src/js/view/alert.js +11 -4
  48. data/public/rearview-src/js/view/dashboard.js +4 -2
  49. data/public/rearview-src/js/view/expandedmonitor.js +22 -9
  50. data/public/rearview-src/js/view/settings.js +84 -0
  51. data/public/rearview-src/less/login.less +4 -4
  52. data/public/rearview-src/less/rearview.less +17 -10
  53. data/public/{monitors → rearview-src/monitors}/index.json +1 -1
  54. data/public/{monitors → rearview-src/monitors}/outage.rb +0 -0
  55. data/public/rearview-src/templates/alert.hbs +10 -2
  56. data/public/rearview-src/templates/primarynav.hbs +6 -6
  57. data/public/rearview-src/templates/schedulemonitor.hbs +2 -1
  58. data/public/rearview-src/templates/settings.hbs +23 -0
  59. data/public/rearview/build.txt +1 -0
  60. data/public/rearview/help/alert.html +20 -0
  61. data/public/rearview/help/quick.html +34 -0
  62. data/public/rearview/js/app.js +1 -1
  63. data/public/rearview/js/main.js +21 -21
  64. data/public/rearview/js/model/user.js +1 -1
  65. data/public/rearview/js/view/addmonitor.js +1 -1
  66. data/public/rearview/js/view/alert.js +1 -1
  67. data/public/rearview/js/view/dashboard.js +1 -1
  68. data/public/rearview/js/view/expandedmonitor.js +1 -1
  69. data/public/rearview/js/view/settings.js +1 -0
  70. data/public/rearview/less/login.less +4 -4
  71. data/public/rearview/less/rearview.less +17 -10
  72. data/public/rearview/monitors/index.json +3 -0
  73. data/public/rearview/monitors/outage.rb +2 -0
  74. data/public/rearview/templates/alert.hbs +10 -2
  75. data/public/rearview/templates/primarynav.hbs +6 -6
  76. data/public/rearview/templates/schedulemonitor.hbs +2 -1
  77. data/public/rearview/templates/settings.hbs +23 -0
  78. data/spec/controllers/jobs_controller_spec.rb +1 -0
  79. data/spec/controllers/monitor_controller_spec.rb +3 -0
  80. data/spec/controllers/user_controller_spec.rb +5 -2
  81. data/spec/data/metrics.yml +598 -0
  82. data/spec/dummy/log/development.log +1044 -0
  83. data/spec/dummy/log/test.log +171716 -0
  84. data/spec/helpers/application_helper_spec.rb +33 -0
  85. data/spec/lib/graphite/client_spec.rb +126 -0
  86. data/spec/lib/graphite/graph_spec.rb +17 -0
  87. data/spec/lib/graphite/graphite_spec.rb +4 -0
  88. data/spec/lib/{rearview/graphite_parser_spec.rb → graphite/raw_parser.rb} +6 -5
  89. data/spec/lib/graphite/target_grammer_spec.rb +106 -0
  90. data/spec/lib/graphite/target_parser_spec.rb +124 -0
  91. data/spec/lib/graphite/target_spec.rb +5 -0
  92. data/spec/lib/rearview/configuration_spec.rb +69 -48
  93. data/spec/lib/rearview/metrics_validator_service_spec.rb +43 -0
  94. data/spec/lib/rearview/metrics_validator_spec.rb +84 -0
  95. data/spec/lib/rearview/metrics_validator_task_spec.rb +62 -0
  96. data/spec/lib/rearview/monitor_runner_spec.rb +3 -3
  97. data/spec/lib/rearview/stats_task_spec.rb +21 -0
  98. data/spec/mailers/metrics_validation_mailer_spec.rb +46 -0
  99. data/spec/models/job_spec.rb +82 -9
  100. data/spec/spec_helper.rb +15 -4
  101. data/spec/support/json_factory.rb +1 -1
  102. data/spec/views/dashboards/show.json.jbuilder_spec.rb +3 -1
  103. data/spec/views/jobs/show.json.jbuilder_spec.rb +2 -1
  104. metadata +98 -11
  105. data/public/rearview-src/templates/test.txt +0 -1
  106. data/public/rearview/templates/test.txt +0 -1
@@ -0,0 +1,11 @@
1
+ module Rearview
2
+ class CronExpressionValidator < ActiveModel::EachValidator
3
+ def validate_each(record, attribute, value)
4
+ if value.present?
5
+ unless Rearview::CronHelper.valid_expression?(value)
6
+ record.errors.add(attribute,(options[:message] || "is not a valid cron expression"))
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,52 @@
1
+ module Rearview
2
+ class MetricsValidator < ActiveModel::EachValidator
3
+ attr_accessor :message
4
+ def validate_each(record, attribute, value)
5
+ if value.present? && value.respond_to?(:each)
6
+ value.each do |metric|
7
+ unless metric_valid?(metric)
8
+ record.errors.add(attribute,(message || "contains an invalid metric: #{metric}"))
9
+ message = nil
10
+ end
11
+ end
12
+ end
13
+ end
14
+ def metric_valid?(metric)
15
+ valid = false
16
+ metric_key = nil
17
+ target_parser.parse(metric)
18
+ if target_parser.error?
19
+ message = "contains an unparseable metric: #{metric} (#{target_parser.error})"
20
+ else
21
+ if target_parser.tree.comment?
22
+ valid = true
23
+ else
24
+ metric_key = target_parser.tree.metric
25
+ if metric_key.present?
26
+ if cache?
27
+ unless cache.has_key?(metric_key)
28
+ cache[metric_key] = client.metric_exists?(metric_key)
29
+ end
30
+ valid = cache[metric_key]
31
+ else
32
+ valid = client.metric_exists?(metric_key)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ valid
38
+ end
39
+ def cache?
40
+ options[:cache]
41
+ end
42
+ def cache
43
+ @cache ||= {}
44
+ end
45
+ def client
46
+ @client ||= Graphite::Client.new(Rearview.config.graphite_connection)
47
+ end
48
+ def target_parser
49
+ @target_parser ||= Graphite::TargetParser.new
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,24 @@
1
+
2
+ module Rearview
3
+ class MetricsValidatorService
4
+ class MetricsValidatorServiceError < StandardError; end;
5
+ include Celluloid
6
+ include Rearview::Logger
7
+ def started?
8
+ @started
9
+ end
10
+ def startup
11
+ logger.info "#{self} starting up service..."
12
+ raise MetricsValidatorServiceError.new("service already started") if started?
13
+ @task = Rearview::MetricsValidatorTask.supervise(Rearview.config.metrics_validator_schedule)
14
+ @started = true
15
+ end
16
+ def shutdown
17
+ logger.info "#{self} shutting down service..."
18
+ raise MetricsValidatorServiceError.new("service not started") unless started?
19
+ @task.actors.first.terminate
20
+ @started = false
21
+ end
22
+ end
23
+ end
24
+
@@ -0,0 +1,56 @@
1
+ require 'json'
2
+
3
+ module Rearview
4
+ class MetricsValidatorTask
5
+ class StatsTaskError < StandardError; end;
6
+ include Celluloid
7
+ include Rearview::Logger
8
+ attr_reader :cron_expression
9
+
10
+ def initialize(cron_expression,start=true)
11
+ @cron_expression = cron_expression
12
+ schedule if start
13
+ end
14
+
15
+ def schedule
16
+ logger.debug "#{self} schedule"
17
+ if ActiveRecord::Base.connection_pool.active_connection?
18
+ ActiveRecord::Base.connection_pool.release_connection
19
+ end
20
+ delay = if cron_expression == '0 * * * * ?'
21
+ 60.0
22
+ else
23
+ Rearview::CronHelper.next_valid_time_after(cron_expression)
24
+ end
25
+ logger.info "#{self} scheduled to run next in #{delay}s"
26
+ if(@timer)
27
+ @timer.cancel
28
+ end
29
+ @timer = after(delay) { self.run }
30
+ end
31
+
32
+ def run
33
+ logger.debug "#{self} run"
34
+ validator = Rearview::MetricsValidator.new({ attributes: [:metrics], cache: true })
35
+ ActiveRecord::Base.connection_pool.with_connection do
36
+ Rearview::Job.schedulable.load.each do |job|
37
+ validator.validate_each(job,:metrics,job.metrics)
38
+ unless job.errors[:metrics].empty?
39
+ alert_validation_failed(job)
40
+ end
41
+ end
42
+ end
43
+ rescue
44
+ logger.error "#{self} run failed: #{$!}\n#{$@.join("\n")}"
45
+ ensure
46
+ schedule
47
+ end
48
+
49
+ def alert_validation_failed(job)
50
+ logger.debug "#{self} alerting on invalid metrics for #{job.id}"
51
+ Rearview::MetricsValidationMailer.validation_failed_email(job.user.email,job).deliver
52
+ end
53
+
54
+ end
55
+ end
56
+
@@ -62,16 +62,18 @@ module Rearview
62
62
  logger.debug "#{self} fetch_data"
63
63
  encMetrics = metrics.delete_if { |m| m.empty? }.map { |m| URI.escape(m) }
64
64
  from, to = create_from_to_dates(minutes, to_date)
65
- uri = "#{Rearview.config.graphite_url}/render?from=#{from}&until=#{to}&format=raw&target=" + encMetrics.join("&target=")
66
-
67
- logger.debug("#{self} fetch_data #{uri}")
65
+ params = {}.tap do |h|
66
+ h["from"] = from
67
+ h["until"] = to
68
+ h["format"] = "raw"
69
+ h["target"] = metrics.delete_if { |m| m.empty? }
70
+ end
68
71
 
69
72
  begin
70
- response = HTTParty.get(uri)
71
-
72
- case response.code
73
+ response = Graphite::Client.new(Rearview.config.graphite_connection).render(params)
74
+ case response.status
73
75
  when 200
74
- Rearview::GraphiteParser.parse(response.body)
76
+ Graphite::RawParser.parse(response.body)
75
77
  else
76
78
  message = response.body
77
79
  logger.error("Graphite request failure: #{message}")
@@ -18,6 +18,7 @@ module Rearview
18
18
  @started
19
19
  end
20
20
  def startup
21
+ logger.info "#{self} starting up service..."
21
22
  raise MonitorServiceError.new("service already started") if started?
22
23
  # TODO actor could die, need to reference by name in registry and/or create link
23
24
  @supervisor = Rearview::MonitorSupervisor.run!
@@ -25,6 +26,7 @@ module Rearview
25
26
  @started = true
26
27
  end
27
28
  def shutdown
29
+ logger.info "#{self} shutting down service..."
28
30
  raise MonitorServiceError.new("service not started") unless started?
29
31
  @supervisor.remove_all_tasks
30
32
  @supervisor.terminate
@@ -14,13 +14,15 @@ module Rearview
14
14
  @started
15
15
  end
16
16
  def startup
17
+ logger.info "#{self} starting up service..."
17
18
  raise StatsServiceError.new("service already started") if started?
18
19
  @started = true
19
- @stats_task = Rearview::StatsTask.supervise
20
+ @task = Rearview::StatsTask.supervise
20
21
  end
21
22
  def shutdown
23
+ logger.info "#{self} shutting down service..."
22
24
  raise StatsServiceError.new("service not started") unless started?
23
- @stats_task.actors.first.terminate
25
+ @task.actors.first.terminate
24
26
  end
25
27
  end
26
28
  end
@@ -1,3 +1,3 @@
1
1
  module Rearview
2
- VERSION = "1.1.2"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -1,8 +1,8 @@
1
1
  # Tasks made available to engine host..
2
2
 
3
3
  namespace :rearview do
4
- namespace :config do
5
4
 
5
+ namespace :config do
6
6
  desc "Verify configuration"
7
7
  task :verify => [:environment] do
8
8
  puts "using \"#{Rails.env}\" configuration:\n#{Rearview.config.dump}"
@@ -14,6 +14,12 @@ namespace :rearview do
14
14
  puts Rearview.config.errors.full_messages.join("\n")
15
15
  end
16
16
  end
17
+ end
17
18
 
19
+ desc "Setup Rearview"
20
+ task :setup => [:environment,"db:create","db:migrate","db:seed"] do
21
+ Kernel.system("bin/rails generate rearview:install")
22
+ puts "setup done"
18
23
  end
24
+
19
25
  end
@@ -13,6 +13,7 @@ define([
13
13
  'view/addcategory',
14
14
  'view/ecosystem',
15
15
  'view/secondarynav',
16
+ 'view/settings',
16
17
  'model/user',
17
18
  'model/dashboard',
18
19
  'collection/monitor',
@@ -35,6 +36,7 @@ define([
35
36
  AddCategoryView,
36
37
  EcosystemView,
37
38
  SecondaryNavView,
39
+ SettingsView,
38
40
  UserModel,
39
41
  DashboardModel,
40
42
  MonitorCollection,
@@ -105,6 +107,11 @@ define([
105
107
  'user' : this.user,
106
108
  'templar' : this.templar
107
109
  }).render();
110
+ new SettingsView({
111
+ 'el' : $('.settings-wrap'),
112
+ 'user' : this.user,
113
+ 'templar' : this.templar
114
+ }).render();
108
115
  },
109
116
 
110
117
  secondaryNav : function() {
@@ -282,8 +289,10 @@ define([
282
289
  'schedulemonitor',
283
290
  'secondarynav',
284
291
  'setmetrics',
292
+ 'settings',
285
293
  'smallmonitor'
286
294
  ], {
295
+ url : rearview.path + '/templates/',
287
296
  version : ( _.isUndefined(rearview.version) ? '0.0.1' : rearview.version ),
288
297
  cache : ( _.isUndefined(rearview.cache) ? true : false )
289
298
  })
@@ -57,9 +57,13 @@ function(
57
57
  }
58
58
  },
59
59
 
60
- updatePrefs : function(preferences) {
60
+ applyPrefs : function(preferences) {
61
61
  var existingPreferences = this.get('preferences');
62
62
  this.set('preferences', _.extend(existingPreferences, preferences));
63
+ },
64
+
65
+ updatePrefs : function(preferences) {
66
+ this.applyPrefs(preferences);
63
67
  this.save();
64
68
  },
65
69
 
@@ -78,4 +82,4 @@ function(
78
82
  });
79
83
 
80
84
  return UserModel;
81
- });
85
+ });
@@ -19,7 +19,8 @@ define([
19
19
  el : '.add-monitor-wrap',
20
20
 
21
21
  subscriptions : {
22
- 'view:dashboard:category' : 'updateDashboardId'
22
+ 'view:dashboard:category' : 'updateDashboardId',
23
+ 'view:settings:save' : 'render'
23
24
  },
24
25
 
25
26
  events : {
@@ -42,9 +43,9 @@ define([
42
43
  // use debounce to throttle resize events and set the height when
43
44
  // the viewport changes.
44
45
  var resize = _.debounce(this.adjustModalLayout, 500);
46
+
45
47
  // Add the event listener
46
48
  $(window).resize(resize);
47
- //
48
49
  this.render();
49
50
  },
50
51
 
@@ -60,7 +61,9 @@ define([
60
61
  this.templar.render({
61
62
  path : 'schedulemonitor',
62
63
  el : this.$el.find('.content-wrap'),
63
- data : {}
64
+ data : {
65
+ 'user' : this.user.toJSON()
66
+ }
64
67
  });
65
68
 
66
69
  this.scheduleViewInitialized = true;
@@ -297,7 +300,8 @@ define([
297
300
  if(result.status === 'error') {
298
301
  Backbone.Mediator.pub('view:addmonitor:test', {
299
302
  'model' : this.model,
300
- 'message' : "The monitor '" + this.model.get('name') + "' produced an error after testing.",
303
+ 'errors' : result.errors,
304
+ 'raw' : result.output,
301
305
  'attention' : 'Monitor Test Error!',
302
306
  'status' : 'error'
303
307
  });
@@ -306,7 +310,8 @@ define([
306
310
  .error(function(result) {
307
311
  Backbone.Mediator.pub('view:addmonitor:test', {
308
312
  'model' : this.model,
309
- 'message' : "The monitor '" + this.model.get('name') + "' produced an error after testing.",
313
+ 'errors' : result.errors,
314
+ 'raw' : result.output,
310
315
  'attention' : 'Monitor Test Error!',
311
316
  'status' : 'error'
312
317
  });
@@ -373,7 +378,7 @@ define([
373
378
  var $content = '';
374
379
 
375
380
  $.ajax({
376
- url : '/help/quick.html',
381
+ url : rearview.path + '/help/quick.html',
377
382
  async : false,
378
383
  success : function( response ) {
379
384
  $content = response;
@@ -445,7 +450,7 @@ define([
445
450
  **/
446
451
  _getTemplateMetaData : function(cb) {
447
452
  $.ajax({
448
- url : '/monitors/index.json',
453
+ url : rearview.path + '/monitors/index.json',
449
454
  success : function( response ) {
450
455
  if ( typeof cb === 'function' ) {
451
456
  cb(response);
@@ -666,7 +671,7 @@ define([
666
671
  error : function(model, xhr, options) {
667
672
  Backbone.Mediator.pub('view:addmonitor:save', {
668
673
  'model' : model,
669
- 'message' : xhr.responseText,
674
+ 'tryJSON' : xhr.responseText,
670
675
  'attention' : 'Monitor Save Error!',
671
676
  'status' : 'error'
672
677
  });
@@ -2,7 +2,7 @@ define([
2
2
  'view/base'
3
3
  ], function(
4
4
  BaseView
5
- ){
5
+ ){
6
6
 
7
7
  var AlertView = BaseView.extend({
8
8
 
@@ -13,6 +13,7 @@ define([
13
13
  'view:addmonitor:test' : 'render',
14
14
  'view:expandedmonitor:delete' : 'render',
15
15
  'view:expandedmonitor:save' : 'render',
16
+ 'view:expandedmonitor:test' : 'render',
16
17
  'view:smallmonitor:save' : 'render',
17
18
  'view:dashboard:save' : 'render',
18
19
  'view:resetmonitor:reset' : 'render'
@@ -24,18 +25,24 @@ define([
24
25
  },
25
26
 
26
27
  render : function(data) {
28
+ if( data.tryJSON ) {
29
+ try {
30
+ data.errors = JSON.parse(data.tryJSON).errors;
31
+ } catch(e) {
32
+ data.raw = data.tryJSON;
33
+ }
34
+ }
27
35
  this.templar.render({
28
36
  path : 'alert',
29
37
  el : this.$el,
30
38
  data : data
31
39
  });
32
-
33
40
  this.activate();
34
41
  },
35
42
 
36
43
  activate : function() {
37
44
  this.$el.addClass('active');
38
- _.delay(this.deactivate, 8000);
45
+ _.delay(this.deactivate, 20000);
39
46
  },
40
47
 
41
48
  deactivate : function() {
@@ -44,4 +51,4 @@ define([
44
51
  });
45
52
 
46
53
  return AlertView;
47
- });
54
+ });
@@ -102,7 +102,9 @@ define([
102
102
  **/
103
103
  initMonitors : function() {
104
104
  this.getCategories();
105
-
105
+ if(this.categories.length && this.categoryId==null) {
106
+ Backbone.Mediator.pub('view:dashboard:category', this.setCategoryId(this.categories[this.carouselIndex].id));
107
+ }
106
108
  // publish dashboard information for the header view
107
109
  this.getDashboardInfo(this.dashboardId, function(title) {
108
110
  Backbone.Mediator.pub('view:dashboard:render', {
@@ -490,4 +492,4 @@ define([
490
492
  });
491
493
 
492
494
  return DashboardView;
493
- });
495
+ });
@@ -22,7 +22,7 @@ define([
22
22
 
23
23
  initialize : function(options) {
24
24
  _.bindAll(this);
25
-
25
+
26
26
  var self = this;
27
27
  this.user = options.user;
28
28
  this.router = options.router;
@@ -47,7 +47,7 @@ define([
47
47
  this.categories = categories;
48
48
  this.categoryId = categoryId;
49
49
  this.dashboardId = dashboardId;
50
-
50
+
51
51
  this.initMonitor();
52
52
  },
53
53
  /**
@@ -194,17 +194,18 @@ define([
194
194
  var self = this,
195
195
  $content = '';
196
196
  $alertContent = '';
197
-
197
+ //TODO fix this path
198
198
  $.ajax({
199
- url : '/help/quick.html',
199
+ url : rearview.path + '/help/quick.html',
200
200
  async : false,
201
201
  success : function( response ) {
202
202
  $content = response;
203
203
  }
204
204
  });
205
205
 
206
+ //TODO fix this path
206
207
  $.ajax({
207
- url : '/help/alert.html',
208
+ url : rearview.path + '/help/alert.html',
208
209
  async : false,
209
210
  success : function( response ) {
210
211
  $alertContent = response;
@@ -291,9 +292,21 @@ define([
291
292
  self.$el.find('textarea.output-view').val(result.output);
292
293
  }
293
294
 
295
+ if(result.status === 'error') {
296
+ Backbone.Mediator.pub('view:expandedmonitor:test', {
297
+ 'model' : this.model,
298
+ 'errors' : result.errors,
299
+ 'raw' : result.output,
300
+ 'attention' : 'Monitor Test Error!',
301
+ 'status' : 'error'
302
+ });
303
+ }
304
+
294
305
  if(typeof cb === 'function') {
295
306
  cb(result.output);
296
307
  }
308
+ },
309
+ failure : function(result) {
297
310
  }
298
311
  });
299
312
  }
@@ -377,9 +390,9 @@ define([
377
390
  self.updateGraph(monitor);
378
391
  },
379
392
  error : function(model, xhr, options) {
380
- Backbone.Mediator.pub('view:expandedmonitor:save', {
393
+ Backbone.Mediator.pub('view:expandedmonitor:save', {
381
394
  'model' : self.model,
382
- 'message' : "The monitor '" + model.get('name') + "' caused an error on saving, please try again.",
395
+ 'tryJSON' : xhr.responseText,
383
396
  'attention' : 'Monitor Saved Error!',
384
397
  'status' : 'error'
385
398
  });
@@ -464,8 +477,8 @@ define([
464
477
  var windowOffSet = 580,
465
478
  alertsOffset = 6,
466
479
  outputOffset = 4,
467
- tabHeight = ( this.$el.find('#viewMetrics') )
468
- ? this.$el.find('#viewMetrics').height()
480
+ tabHeight = ( this.$el.find('#viewMetrics') )
481
+ ? this.$el.find('#viewMetrics').height()
469
482
  : null;
470
483
 
471
484
  // tab height fixing