cloudscale 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.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +33 -0
  4. data/bin/autospec +16 -0
  5. data/bin/bundler +16 -0
  6. data/bin/htmldiff +16 -0
  7. data/bin/ldiff +16 -0
  8. data/bin/monitor +16 -0
  9. data/bin/rake +16 -0
  10. data/bin/rspec +16 -0
  11. data/lib/cloudscale.rb +127 -0
  12. data/lib/cloudscale/monitor/agent/init.rb +63 -0
  13. data/lib/cloudscale/monitor/agent/init_charts.rb +60 -0
  14. data/lib/cloudscale/monitor/agent/init_menus.rb +44 -0
  15. data/lib/cloudscale/monitor/agent/preops/general_preop.rb +34 -0
  16. data/lib/cloudscale/monitor/agent/preops/preop.rb +72 -0
  17. data/lib/cloudscale/monitor/model/agent/agent_instance.rb +33 -0
  18. data/lib/cloudscale/monitor/model/agent/agent_instance_settings.rb +26 -0
  19. data/lib/cloudscale/monitor/model/constants/agent_instance_store.rb +42 -0
  20. data/lib/cloudscale/monitor/model/constants/agent_store.rb +23 -0
  21. data/lib/cloudscale/monitor/model/constants/influxdb_store.rb +23 -0
  22. data/lib/cloudscale/monitor/model/influxdb/influxdata.rb +28 -0
  23. data/lib/cloudscale/monitor/reporter/influxdb_reporter.rb +188 -0
  24. data/lib/cloudscale/plugins/mongo/data/os_chart.json +362 -0
  25. data/lib/cloudscale/plugins/mongo/data/os_menu.json +17 -0
  26. data/lib/cloudscale/plugins/mongo/mongo_db_status.rb +57 -0
  27. data/lib/cloudscale/plugins/mongo/mongo_replica_status.rb +103 -0
  28. data/lib/cloudscale/plugins/mongo/mongo_server_status.rb +172 -0
  29. data/lib/cloudscale/plugins/os/data/os_chart.json +362 -0
  30. data/lib/cloudscale/plugins/os/data/os_menu.json +17 -0
  31. data/lib/cloudscale/plugins/os/preops/plugin_preop.rb +56 -0
  32. data/lib/cloudscale/plugins/os/sigar_cpu_perc.rb +54 -0
  33. data/lib/cloudscale/plugins/os/sigar_disk_iops.rb +55 -0
  34. data/lib/cloudscale/plugins/os/sigar_disk_space.rb +54 -0
  35. data/lib/cloudscale/plugins/os/sigar_net_byte_information.rb +53 -0
  36. data/lib/cloudscale/plugins/os/sigar_packet_information.rb +63 -0
  37. data/lib/cloudscale/plugins/os/sigar_ram_usage.rb +46 -0
  38. data/lib/cloudscale/plugins/os/sigar_swap_usage.rb +46 -0
  39. data/lib/cloudscale/plugins/plugin.rb +98 -0
  40. data/lib/cloudscale/plugins/postgres/postgres_server_status.rb +143 -0
  41. data/lib/cloudscale/plugins/preops/plugin_mongodb_preop.rb +105 -0
  42. data/lib/cloudscale/plugins/preops/plugin_postgres_preop.rb +70 -0
  43. data/lib/cloudscale/registry.rb +48 -0
  44. data/lib/cloudscale/rest/rest_client.rb +198 -0
  45. data/lib/cloudscale/rest/rest_client_helper.rb +70 -0
  46. data/lib/cloudscale/schedule.rb +32 -0
  47. data/lib/cloudscale/store/agent/agent.store +7 -0
  48. data/lib/cloudscale/store/agent/agent_instance.store +11 -0
  49. data/lib/cloudscale/store/agent/influxdb.store +6 -0
  50. data/lib/cloudscale/store/plugin/token +1 -0
  51. data/lib/cloudscale/version.rb +8 -0
  52. data/lib/test/rest/rest_client_test.rb +50 -0
  53. data/lib/test/sigar/sigar_test.rb +36 -0
  54. metadata +264 -0
@@ -0,0 +1,98 @@
1
+ require "fsdb"
2
+ require "yaml/store"
3
+ require "logger"
4
+ require "ruby-metrics"
5
+ require "#{File.dirname(__FILE__)}/../monitor/agent/init_charts"
6
+ require "#{File.dirname(__FILE__)}/../monitor/agent/init_menus"
7
+ require "#{File.dirname(__FILE__)}/../monitor/model/constants/agent_instance_store"
8
+ require "#{File.dirname(__FILE__)}/../rest/rest_client"
9
+
10
+ ##
11
+ #
12
+ # @author Johannes Hiemer.
13
+ #
14
+ ##
15
+ module Cloudscale
16
+ module Plugins
17
+ class Plugin
18
+ attr_accessor :log, :plugins, :rest_client
19
+
20
+ @plugins = Set.new
21
+
22
+ def log
23
+ @log = Logger.new(STDOUT)
24
+ end
25
+
26
+ def initialize()
27
+ @rest_client = RestClientWrapper.instance
28
+ end
29
+
30
+ def self.reset(agentInstanceId)
31
+ resetRestEndpoint('coredatas', agentInstanceId, 'Coredata')
32
+ resetRestEndpoint('tables', agentInstanceId, 'Table')
33
+ resetRestEndpoint('charts', agentInstanceId, 'Chart')
34
+
35
+ Monitor::InitCharts.remove_charts()
36
+ Monitor::InitMenus.remove_menus()
37
+
38
+ remove_measurements(agentInstanceId)
39
+ remove_agenInstance(agentInstanceId)
40
+ end
41
+
42
+ def self.remove(agentInstanceId)
43
+ reset(agentInstanceId)
44
+
45
+ resetRestEndpoint('components', agentInstanceId, 'Components')
46
+ resetRestEndpoint('agentInstanceMenus', agentInstanceId, 'Agent Insntance Menus')
47
+
48
+ Constants::AgentInstance.remove()
49
+ end
50
+
51
+ def self.resetRestEndpoint(entityRel, agentInstanceId, entityName)
52
+ rest_client = RestClientWrapper.instance
53
+ entities = rest_client.searchAny(entityRel,"findByAgentInstanceId",
54
+ { :agentInstanceId => agentInstanceId })
55
+
56
+ puts "Found #{entityName} elements for Agent (#{agentInstanceId}): #{entities["content"].length.to_s}"
57
+ puts " Starting to delete all elements..."
58
+
59
+ entities["content"].each do | entity |
60
+ rest_client.delete(entityRel, RestClientWrapper.load_entity_id(entity))
61
+ end
62
+
63
+ puts " Deleting all elements was successful \n\n"
64
+ end
65
+
66
+ def self.remove_agenInstance(agentInstanceId)
67
+ rest_client = RestClientWrapper.instance
68
+ puts "Removing AgentInstance completely:\n\n"
69
+
70
+ agent_instance = rest_client.searchOne('agentInstances',
71
+ 'findByAgentInstanceId', { :id => agentInstanceId })
72
+
73
+ rest_client.delete('agentInstances', RestClientWrapper.load_entity_id(agent_instance))
74
+
75
+ puts " Deleting AgentInstance was successful \n\n"
76
+ end
77
+
78
+ def self.remove_measurements(agentInstanceId)
79
+ rest_client = RestClientWrapper.instance
80
+ puts "Removing Measurement elements for Agent (#{agentInstanceId}):\n\n"
81
+ puts " Starting to delete all elements..."
82
+
83
+ rest_client.customDelete("measurements", "removeByAgentInstanceId", { :agentInstanceId => agentInstanceId })
84
+
85
+ puts " Deleting all elements was successful \n\n"
86
+ end
87
+
88
+ def self.plugins
89
+ @plugins
90
+ end
91
+
92
+ def self.inherited(klass)
93
+ @plugins << klass
94
+ end
95
+
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,143 @@
1
+ #require "#{File.dirname(__FILE__)}/../preops/plugin_postgres_preop"
2
+ require "#{File.dirname(__FILE__)}/../plugin"
3
+
4
+ ##
5
+ #
6
+ # @author Johannes Hiemer.
7
+ #
8
+ ##
9
+ module Cloudscale
10
+ module Plugins
11
+ class PostgresServerStatus < Plugins::Plugin
12
+ attr_reader :menu_generalInformationm, :menu_numBackends, :menu_transactionInformation, :menu_bulkOps, :menu_rowStats,
13
+ :numBackends, :xactCommit, :xactRollback, :xactTotal, :blksRead, :blksHit,
14
+ :generalInformation, :rowsSelectIdx, :rowsSelectScan, :rowInserts, :rowUpdated, :rowDeleted, :rowTotal
15
+ def log
16
+ @log = Logger.new(STDOUT)
17
+ end
18
+
19
+ def is_enabled
20
+ false
21
+ end
22
+
23
+ def initialize
24
+ super
25
+ if is_enabled
26
+ menus = Plugins::PluginMenus.load_hash()
27
+ @menu_generalInformation = load_menu(menus["pgDatabaseStats"], "generalInformation")
28
+ @menu_numBackends = load_menu(menus["pgDatabaseStats"], "numBackends")
29
+ @menu_transactionInformation = load_menu(menus["pgDatabaseStats"], "transactionInformation")
30
+ @menu_bulkOps = load_menu(menus["pgDatabaseStats"], "bulkOps")
31
+ @menu_rowStats = load_menu(menus["pgTableStats"], "rowStats")
32
+
33
+ @connection = Plugins::PostgresDbWrapper.instance.connection
34
+ components = Plugins::PluginComponents.load_hash()
35
+ @numBackends = load_metric(components["pgDatabaseStats"], "numBackends")
36
+ @xactCommit = load_metric(components["pgDatabaseStats"], "xactCommit")
37
+ @xactRollback = load_metric(components["pgDatabaseStats"], "xactRollback")
38
+ @xactTotal = load_metric(components["pgDatabaseStats"], "xactTotal")
39
+ @blksRead = load_metric(components["pgDatabaseStats"], "blksRead")
40
+ @blksHit = load_metric(components["pgDatabaseStats"], "blksHit")
41
+
42
+ @generalInformation = load_metric(components["pgDatabaseStats"], "generalInformation")
43
+
44
+ @rowsSelectIdx = load_metric(components["pgTableStats"], "rowsSelectIdx")
45
+ @rowsSelectScan = load_metric(components["pgTableStats"], "rowsSelectScan")
46
+ @rowInserts = load_metric(components["pgTableStats"], "rowInserts")
47
+ @rowUpdated = load_metric(components["pgTableStats"], "rowUpdated")
48
+ @rowDeleted = load_metric(components["rowDeleted"], "rowDeleted")
49
+ @rowTotal = load_metric(components["rowTotal"], "rowTotal")
50
+
51
+ end
52
+ end
53
+
54
+ def collect(agentInstanceId)
55
+ log.info("Calling Collect on MongoServerStatus")
56
+ report_general_information(agentInstanceId)
57
+ report_database_stats(agentInstanceId)
58
+ report_table_stats(agentInstanceId)
59
+ end
60
+
61
+ def report_database_stats(agentInstanceId)
62
+ result = @connection.exec('SELECT sum(idx_tup_fetch) AS "rows_select_idx",
63
+ sum(seq_tup_read) AS "rows_select_scan",
64
+ sum(n_tup_ins) AS "rows_insert",
65
+ sum(n_tup_upd) AS "rows_update",
66
+ sum(n_tup_del) AS "rows_delete",
67
+ (sum(idx_tup_fetch) + sum(seq_tup_read) + sum(n_tup_ins) + sum(n_tup_upd) + sum(n_tup_del)) AS "rows_total"
68
+ FROM pg_stat_all_tables;')
69
+ row = result[0]
70
+
71
+ report(rowsSelectIdx, menu_rowStats, row['rows_select_idx'], false, agentInstanceId, "rowsSelectIdxChart",
72
+ "Select indexes", "Select indexes across all tables in the database", "area", "Time", "Count", "c", nil)
73
+
74
+ report(rowsSelectScan, menu_rowStats, row['rows_select_scan'], false, agentInstanceId, "rowsSelectScanChart",
75
+ "Row select scan", "Row select scans across all tables in the database", "area", "Time", "Count", "c", nil)
76
+
77
+ report(rowInserts, menu_rowStats, row['rows_insert'], false, agentInstanceId, "rowInsertsChart",
78
+ "Row inserts", "Row inserts across all tables in the database", "area", "Time", "Count", "c", nil)
79
+
80
+ report(rowUpdated, menu_rowStats, row['rows_update'], false, agentInstanceId, "rowUpdatedChart",
81
+ "Row updates", "Row updates across all tables in the database", "area", "Time", "Count", "c", nil)
82
+
83
+ report(rowDeleted, menu_rowStats, row['rows_delete'], false, agentInstanceId, "rowDeletedChart",
84
+ "Row deletes", "Row deletes across all tables in the database", "area", "Time", "Count", "c", nil)
85
+
86
+ report(rowTotal, menu_rowStats, row['rows_total'], false, agentInstanceId, "rowTotalChart",
87
+ "Rows affected", "Rows affected across all tables in the database", "area", "Time", "Count", "c", nil)
88
+ end
89
+
90
+ def report_table_stats(agentInstanceId)
91
+ result = @connection.exec('SELECT sum(numbackends) AS "numbackends",
92
+ sum(xact_commit) AS "xact_commit",
93
+ sum(xact_rollback) AS "xact_rollback",
94
+ sum(xact_commit+xact_rollback) AS "xact_total",
95
+ sum(blks_read) AS "blks_read",
96
+ sum(blks_hit) AS "blks_hit"
97
+ FROM pg_stat_database;')
98
+ row = result[0]
99
+
100
+ report(xactCommit, menu_transactionInformation, row['xact_commit'], false, agentInstanceId, "xactCommitChart",
101
+ "Transaction commits", "Transaction commits across all tables in the database", "area", "Time", "Count", "c", nil)
102
+
103
+ report(xactRollback, menu_transactionInformation, row['xact_rollback'], false, agentInstanceId, "xactRollbackChart",
104
+ "Transaction rollback", "Transaction rollback across all tables in the database", "area", "Time", "Count", "c", nil)
105
+
106
+ report(xactTotal, menu_transactionInformation, row['xact_total'], false, agentInstanceId, "xactTotalChart",
107
+ "Transactions total", "Transactions total across all tables in the database", "area", "Time", "Count", "c", nil)
108
+
109
+ report(blksRead, menu_bulkOps, row['blks_read'], false, agentInstanceId, "blksReadChart",
110
+ "Bulk reads", "Bulk reads across all tables in the database", "area", "Time", "Count", "c", nil)
111
+
112
+ report(blksHit, menu_bulkOps, row['blks_hit'], false, agentInstanceId, "blksHitChart",
113
+ "Bulk hits", "Bulk hits across all tables in the database", "area", "Time", "Count", "c", nil)
114
+ end
115
+
116
+ def report_general_information(agentInstanceId)
117
+ result = @connection.exec('SELECT datid,
118
+ datname, pid, usesysid, usename,
119
+ client_addr, client_hostname,
120
+ client_port, backend_start, state, waiting
121
+ FROM pg_stat_activity;')
122
+ row = result[0]
123
+
124
+ body = Array.new
125
+ body.push(["DatId", row['datid']])
126
+ body.push(["Datname", row['datname']])
127
+ body.push(["Pid", row['pid']])
128
+ body.push(["Use Sysid", row['usesysid']])
129
+ body.push(["usename", row['usename']])
130
+ body.push(["client_addr", row['client_addr']])
131
+ body.push(["client_hostname", row['client_hostname']])
132
+ body.push(["client_port", row['client_port']])
133
+ body.push(["backend_start", row['backend_start']])
134
+ body.push(["state", row['state']])
135
+ body.push(["waiting", row['waiting']])
136
+ mongo_general_inf_table = Monitor::Table.new("generalInformationPostgres", "Postgres General Information", nil, body, "compact")
137
+ mongo_general_inf_table.caption = "General Information regarding your Postgres Instance"
138
+
139
+ persist_table(mongo_general_inf_table, agentInstanceId, menu_generalInformation)
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,105 @@
1
+ require "logger"
2
+ #require "mongo"
3
+ require "singleton"
4
+ require "#{File.dirname(__FILE__)}/../../monitor/agent/preops/preop"
5
+
6
+ ##
7
+ #
8
+ # @author Johannes Hiemer.
9
+ #
10
+ ##
11
+ module Cloudscale
12
+ module Plugins
13
+ class PluginMongodbPreop < Preops::Preop
14
+ include Singleton
15
+
16
+ attr_accessor :db, :connection
17
+ @@options = {
18
+ :host => {
19
+ :argument => "--host",
20
+ :description => "Host for your MongoDB Instance (e.g. host.mongodb.com)",
21
+ :required => true,
22
+ :value => nil
23
+ },
24
+ :port => {
25
+ :argument => "--port",
26
+ :description => "Port for your MongoDB Instance (Standard 27017)",
27
+ :required => false,
28
+ :value => 27017
29
+ },
30
+ :db => {
31
+ :argument => "--db",
32
+ :description => "Database of your MongoDB instance",
33
+ :required => true,
34
+ :value => nil
35
+ },
36
+ :ssl => {
37
+ :argument => "--ssl",
38
+ :description => "Usage SSL of your MongoDB instance",
39
+ :required => false,
40
+ :value => false
41
+ },
42
+ :username => {
43
+ :argument => "--username",
44
+ :description => "Username for your MongoDB instance",
45
+ :required => false,
46
+ :value => nil
47
+ },
48
+ :password => {
49
+ :argument => "--password",
50
+ :description => "Password for your MongoDB instance",
51
+ :required => false,
52
+ :value => nil
53
+ },
54
+ :connect_timeout => {
55
+ :argument => "--connect_timeout",
56
+ :description => "Connection Timeout for your MongoDB instance",
57
+ :required => false,
58
+ :value => 30
59
+ },
60
+ :op_timeout => {
61
+ :argument => "--op_timeout",
62
+ :description => "Operation TImeout for your MongoDB instance",
63
+ :required => false,
64
+ :value => 30
65
+ }
66
+ }
67
+
68
+ def options
69
+ @@options
70
+ end
71
+
72
+ def initialize
73
+ self.init
74
+ begin
75
+ @connection = Mongo::Connection.new(options[:host][:value], options[:port][:value])
76
+ rescue Mongo::ConnectionFailure
77
+ puts "Unable to connect to the MongoDB Daemon.",
78
+ "Please ensure it is running on #{@host}:#{@port}\n\nException Message: #{$!.message}. Also confirm if SSL should be enabled or disabled."
79
+ end
80
+
81
+ # Try to connect to the database
82
+ if (@connection != nil)
83
+ @db = @connection.db(options[:db][:value])
84
+ end
85
+
86
+ begin
87
+ if (@username != nil)
88
+ @db.authenticate(options[:username][:value], options[:password][:value])
89
+ end
90
+ rescue Mongo::AuthenticationError
91
+ puts "Unable to authenticate to MongoDB Database." << $!.message
92
+ end
93
+ end
94
+
95
+ def connection
96
+ @connection
97
+ end
98
+
99
+ def db
100
+ @db
101
+ end
102
+
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,70 @@
1
+ require "logger"
2
+ #require "pg"
3
+ require "singleton"
4
+ require "#{File.dirname(__FILE__)}/../../monitor/agent/preops/preop"
5
+
6
+ ##
7
+ #
8
+ # @author Johannes Hiemer.
9
+ #
10
+ ##
11
+ module Cloudscale
12
+ module Plugins
13
+ class PluginPostgresPreop < Preops::Preop
14
+ include Singleton
15
+
16
+ @@options = {
17
+ :host => {
18
+ :argument => "--host",
19
+ :description => "Host for your Postgres Instance (e.g. host.instance.com)",
20
+ :required => true,
21
+ :value => nil
22
+ },
23
+ :port => {
24
+ :argument => "--port",
25
+ :description => "Port for your Postgres Instance (Standard 5432)",
26
+ :required => false,
27
+ :value => 5432
28
+ },
29
+ :db => {
30
+ :argument => "--db",
31
+ :description => "Database of your Postgres instance",
32
+ :required => true,
33
+ :value => nil
34
+ },
35
+ :username => {
36
+ :argument => "--username",
37
+ :description => "Username for your Postgres instance",
38
+ :required => false,
39
+ :value => nil
40
+ },
41
+ :password => {
42
+ :argument => "--password",
43
+ :description => "Password for your Postgres instance",
44
+ :required => false,
45
+ :value => nil
46
+ }
47
+ }
48
+
49
+ def options
50
+ @@options
51
+ end
52
+
53
+ def initialize
54
+ self.init
55
+ begin
56
+ @connection = PG.connect(:host => options[:host][:value], :user => options[:username][:value],
57
+ :password => options[:password][:value],
58
+ :port => options[:port][:value].to_i, :dbname => options[:db][:value])
59
+ rescue PGError => e
60
+ puts e.message
61
+ end
62
+ end
63
+
64
+ def connection
65
+ @connection
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,48 @@
1
+ require "singleton"
2
+ require "securerandom"
3
+ require "#{File.dirname(__FILE__)}/monitor/model/constants/agent_instance_store"
4
+
5
+ ##
6
+ #
7
+ # @author Johannes Hiemer.
8
+ #
9
+ ##
10
+ module Cloudscale
11
+ module Monitor
12
+ class Registry
13
+ include Singleton
14
+
15
+ attr_accessor :agent_instance_id, :metrics, :generated_instance_id,
16
+ :stored_agent_instance, :stored_agent
17
+
18
+ def initialize()
19
+ @metrics = Hash.new
20
+ @generated_instance_id = SecureRandom.hex
21
+ @stored_agent_instance = Constants::AgentInstance.load
22
+ @stored_agent = Constants::Agent.load
23
+ end
24
+
25
+ def metrics
26
+ @metrics
27
+ end
28
+
29
+ def agent_instance_id
30
+ instance_id = Constants::AgentInstance.load["agentInstanceId"]
31
+ if (instance_id == nil)
32
+ return @generated_instance_id
33
+ else
34
+ return instance_id
35
+ end
36
+ end
37
+
38
+ def stored_agent
39
+ @stored_agent
40
+ end
41
+
42
+ def stored_agent_instance
43
+ @stored_agent_instance
44
+ end
45
+
46
+ end
47
+ end
48
+ end