health_status 0.0.1
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.
- data/.gitignore +20 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +32 -0
- data/Rakefile +3 -0
- data/bin/health_status_server +17 -0
- data/db/migrate/20121130030246_health_status_migration.rb +22 -0
- data/db/migrate/20121204050629_remove_datetime.rb +9 -0
- data/db/migrate/20121204171946_add_service_metric.rb +64 -0
- data/health_status.gemspec +31 -0
- data/lib/health_status.rb +5 -0
- data/lib/health_status/app.rb +83 -0
- data/lib/health_status/model.rb +284 -0
- data/lib/health_status/version.rb +3 -0
- data/lib/health_status/web.rb +59 -0
- data/public/css/bootstrap.css +5018 -0
- data/public/css/bootstrap.min.css +853 -0
- data/public/css/main.css +45 -0
- data/public/img/glyphicons-halflings-white.png +0 -0
- data/public/img/glyphicons-halflings.png +0 -0
- data/public/js/bootstrap.js +2036 -0
- data/public/js/bootstrap.min.js +7 -0
- data/public/js/jquery.cookie.js +72 -0
- data/public/js/jquery.js +9472 -0
- data/public/js/main.js +245 -0
- data/views/index.erb +123 -0
- metadata +217 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 riywo
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# HealthStatus
|
2
|
+
|
3
|
+
API server to store and visualize applications' health status.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'health_status'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install health_status
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
$ health_status_server -d /path/to/sqlite.db
|
22
|
+
|
23
|
+
$ curl -v -d "status=1" localhost:5678/service1/application1/metric1
|
24
|
+
$ curl -v -d "status=2" localhost:5678/service1/application1/metric2
|
25
|
+
|
26
|
+
## Contributing
|
27
|
+
|
28
|
+
1. Fork it
|
29
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
30
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
31
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
32
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift File.expand_path("../../lib", __FILE__)
|
3
|
+
begin
|
4
|
+
require 'vegas'
|
5
|
+
rescue LoadError
|
6
|
+
require 'rubygems'
|
7
|
+
require 'vegas'
|
8
|
+
end
|
9
|
+
require "health_status/app"
|
10
|
+
require "health_status/model"
|
11
|
+
|
12
|
+
Vegas::Runner.new(HealthStatus::App, 'health_status_server') do |runner, opts, app|
|
13
|
+
opts.on("-d", "--database DATABASE_FILE", "path/to/sqlite.db") do |database|
|
14
|
+
runner.logger.info "Using database #{database}"
|
15
|
+
HealthStatus::App.database_path = database
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class HealthStatusMigration < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
create_table :applications do |t|
|
4
|
+
t.string :name, :null => false
|
5
|
+
t.integer :status, :null => false
|
6
|
+
t.datetime :datetime, :null => false
|
7
|
+
t.datetime :saved_at, :null => false
|
8
|
+
end
|
9
|
+
add_index :applications, [ :name ], :unique => true
|
10
|
+
|
11
|
+
create_table :half_hour_statuses do |t|
|
12
|
+
t.integer :application_id, :null => false
|
13
|
+
t.integer :status, :null => false
|
14
|
+
t.datetime :datetime, :null => false
|
15
|
+
t.datetime :saved_at, :null => false
|
16
|
+
end
|
17
|
+
add_index :half_hour_statuses, [:application_id]
|
18
|
+
end
|
19
|
+
|
20
|
+
def down
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class AddServiceMetric < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
rename_table :applications, :v1_applications
|
4
|
+
rename_table :half_hour_statuses, :v1_half_hour_statuses
|
5
|
+
|
6
|
+
create_table :services do |t|
|
7
|
+
t.string :name, :null => false
|
8
|
+
t.integer :status, :null => false
|
9
|
+
t.datetime :saved_at, :null => false
|
10
|
+
end
|
11
|
+
add_index :services, [ :name ], :unique => true
|
12
|
+
|
13
|
+
create_table :service_half_hour_statuses do |t|
|
14
|
+
t.integer :service_id, :null => false
|
15
|
+
t.integer :status, :null => false
|
16
|
+
t.datetime :datetime, :null => false
|
17
|
+
t.datetime :saved_at, :null => false
|
18
|
+
end
|
19
|
+
add_index :service_half_hour_statuses, [ :service_id ]
|
20
|
+
|
21
|
+
create_table :applications do |t|
|
22
|
+
t.integer :service_id, :null => false
|
23
|
+
t.string :name, :null => false
|
24
|
+
t.integer :status, :null => false
|
25
|
+
t.datetime :saved_at, :null => false
|
26
|
+
end
|
27
|
+
add_index :applications, [ :service_id, :name ], :unique => true
|
28
|
+
|
29
|
+
create_table :application_half_hour_statuses do |t|
|
30
|
+
t.integer :application_id, :null => false
|
31
|
+
t.integer :status, :null => false
|
32
|
+
t.datetime :datetime, :null => false
|
33
|
+
t.datetime :saved_at, :null => false
|
34
|
+
end
|
35
|
+
add_index :application_half_hour_statuses, [ :application_id ]
|
36
|
+
|
37
|
+
create_table :metrics do |t|
|
38
|
+
t.integer :application_id, :null => false
|
39
|
+
t.string :name, :null => false
|
40
|
+
t.integer :status, :null => false
|
41
|
+
t.datetime :saved_at, :null => false
|
42
|
+
end
|
43
|
+
add_index :metrics, [ :application_id, :name ], :unique => true
|
44
|
+
|
45
|
+
create_table :metric_half_hour_statuses do |t|
|
46
|
+
t.integer :metric_id, :null => false
|
47
|
+
t.integer :status, :null => false
|
48
|
+
t.datetime :datetime, :null => false
|
49
|
+
t.datetime :saved_at, :null => false
|
50
|
+
end
|
51
|
+
add_index :metric_half_hour_statuses, [ :metric_id ]
|
52
|
+
end
|
53
|
+
|
54
|
+
def down
|
55
|
+
drop_table :services
|
56
|
+
drop_table :service_half_hour_statuses
|
57
|
+
drop_table :applications
|
58
|
+
drop_table :application_half_hour_statuses
|
59
|
+
drop_table :metrics
|
60
|
+
drop_table :metric_half_hour_statuses
|
61
|
+
rename_table :v1_applications, :applications
|
62
|
+
rename_table :v1_half_hour_statuses, :half_hour_statuses
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'health_status/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "health_status"
|
8
|
+
spec.version = HealthStatus::VERSION
|
9
|
+
spec.authors = ["Ryosuke IWANAGA"]
|
10
|
+
spec.email = ["riywo.jp@gmail.com"]
|
11
|
+
spec.description = %q{Health status API server}
|
12
|
+
spec.summary = %q{API server to store and visualize applications' health status}
|
13
|
+
spec.homepage = "https://github.com/riywo/health_status"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'sinatra'
|
22
|
+
spec.add_dependency 'sinatra-contrib'
|
23
|
+
spec.add_dependency 'activerecord'
|
24
|
+
spec.add_dependency 'sinatra-activerecord'
|
25
|
+
spec.add_dependency 'sqlite3'
|
26
|
+
spec.add_dependency 'vegas'
|
27
|
+
|
28
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
29
|
+
spec.add_development_dependency 'tapp'
|
30
|
+
spec.add_development_dependency 'rake'
|
31
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require "health_status"
|
2
|
+
require "health_status/model"
|
3
|
+
require "health_status/web"
|
4
|
+
require "sinatra/base"
|
5
|
+
require "sinatra/activerecord"
|
6
|
+
require "sinatra/cookies"
|
7
|
+
|
8
|
+
class HealthStatus::App < Sinatra::Base
|
9
|
+
|
10
|
+
class << self
|
11
|
+
attr_accessor :database_path
|
12
|
+
end
|
13
|
+
|
14
|
+
helpers Sinatra::Cookies, ERB::Util
|
15
|
+
register Sinatra::ActiveRecordExtension
|
16
|
+
|
17
|
+
set :public_folder, File.expand_path("../../../public", __FILE__)
|
18
|
+
set :views, File.expand_path("../../../views", __FILE__)
|
19
|
+
|
20
|
+
before do
|
21
|
+
settings.database = "sqlite3:///#{HealthStatus::App.database_path}"
|
22
|
+
ActiveRecord::Base.logger = nil
|
23
|
+
HealthStatus::Model::Migrate.migrate
|
24
|
+
end
|
25
|
+
|
26
|
+
get '/' do
|
27
|
+
@timezone = params["timezone"] || cookies[:timezone] || HealthStatus::Web.system_timezone
|
28
|
+
@zones = HealthStatus::Web.timezones
|
29
|
+
erb :index
|
30
|
+
end
|
31
|
+
|
32
|
+
get '/api/v2/' do
|
33
|
+
HealthStatus::Model::Service.readonly.fetch_all_info().to_json
|
34
|
+
end
|
35
|
+
|
36
|
+
get '/api/v2/:service' do |service_name|
|
37
|
+
args = {}
|
38
|
+
args[:end_time] = Time.now.in_time_zone(params["timezone"])
|
39
|
+
args[:with_status] = true
|
40
|
+
service = HealthStatus::Model::Service.find_by_name(service_name)
|
41
|
+
service.fetch_info(args).to_json
|
42
|
+
end
|
43
|
+
|
44
|
+
get '/api/v2/:service/:application' do |service_name, application_name|
|
45
|
+
Time.zone = params["timezone"]
|
46
|
+
args = {}
|
47
|
+
args[:end_time] = Time.now.in_time_zone(params["timezone"])
|
48
|
+
args[:with_status] = true
|
49
|
+
application = HealthStatus::Model::Service.find_by_name(service_name).applications.find_by_name(application_name)
|
50
|
+
application.fetch_info(args).to_json
|
51
|
+
end
|
52
|
+
|
53
|
+
get '/api/v2/:service/:application/:metric' do |service_name, application_name, metric_name|
|
54
|
+
Time.zone = params["timezone"]
|
55
|
+
args = {}
|
56
|
+
args[:end_time] = Time.now.in_time_zone(params["timezone"])
|
57
|
+
args[:with_status] = true
|
58
|
+
metric = HealthStatus::Model::Service.find_by_name(service_name).applications.find_by_name(application_name).metrics.find_by_name(metric_name)
|
59
|
+
metric.fetch_info(args).to_json
|
60
|
+
end
|
61
|
+
|
62
|
+
post '/api/v2/:service/:application/:metric' do |service_name, application_name, metric_name|
|
63
|
+
raise unless params.has_key? "status"
|
64
|
+
HealthStatus::Model::Service.save_metric(service_name, application_name, metric_name, params["status"])
|
65
|
+
"OK"
|
66
|
+
end
|
67
|
+
|
68
|
+
delete '/api/v2/:service' do |service_name|
|
69
|
+
HealthStatus::Model::Service.find_by_name(service_name).destroy
|
70
|
+
"OK"
|
71
|
+
end
|
72
|
+
|
73
|
+
delete '/api/v2/:service/:application' do |service_name, application_name|
|
74
|
+
HealthStatus::Model::Service.find_by_name(service_name).applications.find_by_name(application_name).destroy
|
75
|
+
"OK"
|
76
|
+
end
|
77
|
+
|
78
|
+
delete '/api/v2/:service/:application/:metric' do |service_name, application_name, metric_name|
|
79
|
+
HealthStatus::Model::Service.find_by_name(service_name).applications.find_by_name(application_name).metrics.find_by_name(metric_name).destroy
|
80
|
+
"OK"
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,284 @@
|
|
1
|
+
require "health_status"
|
2
|
+
require 'sinatra/activerecord'
|
3
|
+
require "sinatra/activerecord/rake"
|
4
|
+
|
5
|
+
class HealthStatus::Model
|
6
|
+
|
7
|
+
module AggregateStatus
|
8
|
+
@@default_timezone = :utc
|
9
|
+
@@half_hour = 30 * 60
|
10
|
+
@@hour = 60 * 60
|
11
|
+
@@day = 24 * @@hour
|
12
|
+
|
13
|
+
def fetch_current_status
|
14
|
+
if saved_at < floor_half_hour(Time.now.utc)
|
15
|
+
nil
|
16
|
+
else
|
17
|
+
status
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def fetch_saved_at(args)
|
22
|
+
end_time = args[:end_time]
|
23
|
+
end_time ||= Time.now
|
24
|
+
Time.at(saved_at.to_i).localtime(end_time.utc_offset)
|
25
|
+
end
|
26
|
+
|
27
|
+
def fetch_status_with_interval(interval, args = {})
|
28
|
+
validate_args = validate_fetch_status(interval, args)
|
29
|
+
interval_status = []
|
30
|
+
time = validate_args[:start_time]
|
31
|
+
while time <= validate_args[:end_time]
|
32
|
+
data = {
|
33
|
+
:datetime => time,
|
34
|
+
:status => self_half_hour_statuses.where(:datetime => time..(time + interval - 1)).maximum(:status),
|
35
|
+
}
|
36
|
+
interval_status << data
|
37
|
+
time += interval
|
38
|
+
end
|
39
|
+
interval_status
|
40
|
+
end
|
41
|
+
|
42
|
+
def fetch_hourly_status(args = {})
|
43
|
+
fetch_status_with_interval(@@hour, args)
|
44
|
+
end
|
45
|
+
|
46
|
+
def fetch_daily_status(args = {})
|
47
|
+
fetch_status_with_interval(@@day, args)
|
48
|
+
end
|
49
|
+
|
50
|
+
def fetch_info(args = {})
|
51
|
+
depth = args[:depth].nil? ? 0 : args[:depth]
|
52
|
+
data = {
|
53
|
+
:id => id,
|
54
|
+
:name => name,
|
55
|
+
:current_status => fetch_current_status,
|
56
|
+
:saved_at => fetch_saved_at(args),
|
57
|
+
}
|
58
|
+
|
59
|
+
if args[:with_status]
|
60
|
+
data[:hourly_status] = fetch_hourly_status(args)
|
61
|
+
data[:daily_status] = fetch_daily_status(args)
|
62
|
+
end
|
63
|
+
|
64
|
+
if args[:with_id]
|
65
|
+
data[:service_id] = service.id if respond_to? :service
|
66
|
+
if respond_to? :application
|
67
|
+
data[:service_id] = application.service.id
|
68
|
+
data[:application_id] = application.id
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
if children.respond_to? :map and depth > 0
|
73
|
+
data[children_name] = children.map do |child|
|
74
|
+
args[:depth] = depth - 1
|
75
|
+
child.fetch_info(args)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
data
|
79
|
+
end
|
80
|
+
|
81
|
+
def save_status(new_status)
|
82
|
+
children_status = children.maximum(:status)
|
83
|
+
if !children_status.nil? and children_status <= new_status.to_i
|
84
|
+
self.status = new_status.to_i
|
85
|
+
end
|
86
|
+
save!
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def validate_fetch_status(interval, args)
|
92
|
+
end_time = args[:end_time]
|
93
|
+
end_time ||= Time.now
|
94
|
+
start_time = args[:start_time]
|
95
|
+
start_time ||= end_time - (interval == @@day ? 7 * @@day : @@day)
|
96
|
+
|
97
|
+
offset = start_time.utc_offset
|
98
|
+
raise if offset != end_time.utc_offset
|
99
|
+
raise if offset % @@half_hour != 0
|
100
|
+
|
101
|
+
start_time = floor(start_time, interval)
|
102
|
+
end_time = floor(end_time, interval)
|
103
|
+
{ :start_time => start_time, :end_time => end_time }
|
104
|
+
end
|
105
|
+
|
106
|
+
def floor_half_hour(datetime)
|
107
|
+
floor(datetime, @@half_hour)
|
108
|
+
end
|
109
|
+
|
110
|
+
def floor_hour(datetime)
|
111
|
+
floor(datetime, @@hour)
|
112
|
+
end
|
113
|
+
|
114
|
+
def floor_day(datetime)
|
115
|
+
floor(datetime, @@day)
|
116
|
+
end
|
117
|
+
|
118
|
+
def floor(datetime, seconds)
|
119
|
+
offset = datetime.utc_offset
|
120
|
+
Time.at(datetime.to_i - ((datetime.to_i + offset) % seconds).floor).localtime(offset)
|
121
|
+
end
|
122
|
+
|
123
|
+
def update_half_hour_status
|
124
|
+
half_hour = floor_half_hour(self.saved_at)
|
125
|
+
current = self.self_half_hour_statuses.find(:all, :conditions => { :datetime => half_hour } ).first
|
126
|
+
if current
|
127
|
+
current.status = status if current.status < status
|
128
|
+
current.saved_at = self.saved_at
|
129
|
+
current.save
|
130
|
+
else
|
131
|
+
self_half_hour_statuses.create(
|
132
|
+
:status => self.status,
|
133
|
+
:datetime => half_hour,
|
134
|
+
:saved_at => self.saved_at,
|
135
|
+
)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class Service < ActiveRecord::Base
|
141
|
+
include AggregateStatus
|
142
|
+
|
143
|
+
has_many :applications, :dependent => :destroy
|
144
|
+
has_many :service_half_hour_statuses, :order => "datetime ASC", :dependent => :destroy
|
145
|
+
|
146
|
+
before_validation do self.saved_at = Time.now.utc end
|
147
|
+
after_save :update_half_hour_status
|
148
|
+
validates_inclusion_of :status, :in => 1..3
|
149
|
+
|
150
|
+
def self.fetch_all_info(args = {})
|
151
|
+
all.map do |service|
|
152
|
+
args[:depth] = 2
|
153
|
+
service.fetch_info(args)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.save_metric(service_name, application_name, metric_name, new_status)
|
158
|
+
ActiveRecord::Base.transaction do
|
159
|
+
service = find_or_initialize_by_name(service_name)
|
160
|
+
application = service.applications.find_or_initialize_by_name(application_name)
|
161
|
+
metric = application.metrics.find_or_initialize_by_name(metric_name)
|
162
|
+
|
163
|
+
if service.new_record?
|
164
|
+
service.status = new_status
|
165
|
+
application.status = new_status
|
166
|
+
elsif application.new_record?
|
167
|
+
application.status = new_status
|
168
|
+
end
|
169
|
+
metric.status = new_status
|
170
|
+
service.save!
|
171
|
+
application.save!
|
172
|
+
metric.save!
|
173
|
+
|
174
|
+
application.save_status(new_status)
|
175
|
+
service.save_status(new_status)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def self_half_hour_statuses
|
180
|
+
service_half_hour_statuses
|
181
|
+
end
|
182
|
+
|
183
|
+
def children_name
|
184
|
+
:applications
|
185
|
+
end
|
186
|
+
|
187
|
+
def children
|
188
|
+
applications
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
class Application < ActiveRecord::Base
|
193
|
+
include AggregateStatus
|
194
|
+
|
195
|
+
belongs_to :service
|
196
|
+
has_many :metrics, :dependent => :destroy
|
197
|
+
has_many :application_half_hour_statuses, :order => "datetime ASC", :dependent => :destroy
|
198
|
+
|
199
|
+
before_validation do self.saved_at = Time.now.utc end
|
200
|
+
after_save :update_half_hour_status
|
201
|
+
validates_inclusion_of :status, :in => 1..3
|
202
|
+
|
203
|
+
def self_half_hour_statuses
|
204
|
+
application_half_hour_statuses
|
205
|
+
end
|
206
|
+
|
207
|
+
def children_name
|
208
|
+
:metrics
|
209
|
+
end
|
210
|
+
|
211
|
+
def children
|
212
|
+
metrics
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
class Metric < ActiveRecord::Base
|
217
|
+
include AggregateStatus
|
218
|
+
|
219
|
+
belongs_to :application
|
220
|
+
has_many :metric_half_hour_statuses, :order => "datetime ASC", :dependent => :destroy
|
221
|
+
|
222
|
+
before_validation do self.saved_at = Time.now.utc end
|
223
|
+
after_save :update_half_hour_status
|
224
|
+
validates_inclusion_of :status, :in => 1..3
|
225
|
+
|
226
|
+
def self_half_hour_statuses
|
227
|
+
metric_half_hour_statuses
|
228
|
+
end
|
229
|
+
|
230
|
+
def children
|
231
|
+
self
|
232
|
+
end
|
233
|
+
|
234
|
+
end
|
235
|
+
|
236
|
+
class ServiceHalfHourStatus < ActiveRecord::Base
|
237
|
+
@@default_timezone = :utc
|
238
|
+
belongs_to :service
|
239
|
+
validates_inclusion_of :status, :in => 1..3
|
240
|
+
end
|
241
|
+
|
242
|
+
class ApplicationHalfHourStatus < ActiveRecord::Base
|
243
|
+
@@default_timezone = :utc
|
244
|
+
belongs_to :application
|
245
|
+
validates_inclusion_of :status, :in => 1..3
|
246
|
+
end
|
247
|
+
|
248
|
+
class MetricHalfHourStatus < ActiveRecord::Base
|
249
|
+
@@default_timezone = :utc
|
250
|
+
belongs_to :metric
|
251
|
+
validates_inclusion_of :status, :in => 1..3
|
252
|
+
end
|
253
|
+
|
254
|
+
module Sort
|
255
|
+
def self.names_sort_by_status
|
256
|
+
all.sort do |a, b|
|
257
|
+
a_status = a.fetch_current_status
|
258
|
+
b_status = b.fetch_current_status
|
259
|
+
if !a_status and !b_status
|
260
|
+
a.name <=> b.name
|
261
|
+
elsif !a_status
|
262
|
+
1
|
263
|
+
elsif !b_status
|
264
|
+
-1
|
265
|
+
else
|
266
|
+
(b.fetch_current_status <=> a.fetch_current_status).nonzero? or
|
267
|
+
a.name <=> b.name
|
268
|
+
end
|
269
|
+
end.map { |app| app.name }
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
module Migrate
|
274
|
+
extend Sinatra::ActiveRecordTasks
|
275
|
+
extend self
|
276
|
+
|
277
|
+
private
|
278
|
+
|
279
|
+
def migrations_dir
|
280
|
+
File.expand_path("../../../db/migrate", __FILE__)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
end
|