rearview 1.1.2-jruby → 1.2.0-jruby

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