Sindbad~EG File Manager
class MysqlWorkload_Lib
require_relative 'oms_common'
def initialize(host, port, username, password, database, encoding, mock_interface=nil)
if mock_interface.nil?
require 'mysql2'
end
@host = host
@port = port
@username = username
@password = password
@database = database
@encoding = encoding
@mock_interface = mock_interface
@query_global_status = "SHOW GLOBAL STATUS"
@query_variables = "SHOW VARIABLES"
# total size of all databases in bytes (ServerDiskUseInBytes)
@query_sizeof_all_databases = 'select "Total" as "Database", SUM(a.data_length) + SUM(a.index_length) as "Size (Bytes)" from information_schema.schemata b left join information_schema.tables a on b.schema_name = a.table_schema'
# Execute a query to get a result set like:
# +--------------------+--------+-------------------------------+
# | Database | Size (Bytes) |
# +--------------------+--------+--------------------------------+
# | Total | 89998192 |
# +--------------------+--------+-------------------------------+
if (@database == nil)
# Number of tables in each database and the table size in bytes
@query_get_database = 'select b.schema_name as "DatabaseName",COUNT(a.table_name) as "NumberOfTables", SUM(a.data_length) + SUM(a.index_length) as "SizeInBytes" from information_schema.schemata b left join information_schema.tables a on b.schema_name = a.table_schema group by b.schema_name'
# Execute a query to get a result set like:
# +--------------------+--------+-------------------------------+
# | DatabaseName | NumberOfTables | SizeInBytes |
# +--------------------+--------+--------------------------------+
# | information_schema | 28 | 8192 |
# +--------------------+--------+-------------------------------+
# Note that Size may be NULL if database has no tables
else
# Number of tables in given database and the table size in bytes
@query_get_database = 'select b.schema_name as "DatabaseName",COUNT(a.table_name) as "NumberOfTables",
SUM(a.data_length) + SUM(a.index_length) as "SizeInBytes"
from information_schema.schemata b
left join information_schema.tables a on b.schema_name = a.table_schema
where b.schema_name =\'' + @database + '\' group by b.schema_name'
end
end
def get_connection
# Opens a connection to mysql server instance
begin
return Mysql2::Client.new({
:host => @host,
:port => @port,
:username => @username,
:password => @password,
:database => @database,
:encoding => @encoding,
:reconnect => true
})
rescue Exception => e
@log.warn("mysql_workload: #{e}")
end
end
def close_connection
# check if close connection was called prior the client connection is created
if @mysql != nil
mysql.close
end
end
def query(input_query)
if @mock_interface.nil?
@mysql ||= get_connection
begin
return @mysql.query(input_query, :cast => false, :cache_rows => false)
rescue Exception => e
@log.warn("mysql_workload: #{e}")
end
else
return @mock_interface.query(input_query)
end
end
def get_mysql_hostname
query("SHOW VARIABLES LIKE 'hostname'").each do |row|
return row.fetch('Value')
end
end
def transform_row(row)
# creates a new hash table where keys from the input row are replaced with the Variable_name key name,
# and the value of the key Variable_name. Case sensitive comparision.
# Example {VariableName => connectedthreads, Value => 20} will be replaced with {connectedthreads = > 20}
result = Hash.new()
result.store(row["Variable_name"], row["Value"] )
return result
end
def get_value (input_array, key_to_find)
# finds given key in the array of hash tables
#and returns it's value, -1 otherwise
value = -1
input_array.each do |row|
if (row.has_key?(key_to_find))
value = row.fetch(key_to_find)
break
end
end
return value
end
def get_server_database_type
# default to InnoDB if default_storage_engine not supported
engine_info_value = "InnoDB"
#retrieve engine info from default_storage_engine
query("show variables like 'default_storage_engine'").each do |row|
engine_info_value = row.fetch('Value')
end
return engine_info_value
end
def get_server_database_version
dbversion_info_value = 0 # default
#retrieve database version info using innodb_version
query("show variables like 'version'").each do |row|
dbversion_info_value = row.fetch('Value')
end
return dbversion_info_value
end
def get_server_stats
global_stats = Array.new
env_var_stats = Array.new
#final list of counters that will be sent to oms. Filtered based on mysql spec.
final_records = Array.new
# populate all mysql performance and analytical data throw SHOW GLOBAL STATUS or SHOW VARIABLES
q_global_status = query(@query_global_status)
q_global_status.each do |row|
new_row = transform_row(row)
global_stats.push(new_row)
end
q_variables = query(@query_variables)
q_variables.each do |row|
new_row = transform_row(row)
env_var_stats.push(new_row)
end
# Add Number of Connections
num_connections = Hash.new
num_connections_value = get_value(global_stats, "Threads_connected")
num_connections.store("Number of Connections", num_connections_value)
final_records.push(num_connections)
# Add Maximum Allowed Connections
max_connections = Hash.new
max_connections_value = get_value(env_var_stats, "max_connections")
max_connections.store("Maximum Allowed Connections", max_connections_value)
final_records.push(max_connections)
# Add Aborted Connections
failed_connections = Hash.new
failedconnections_value = get_value(global_stats, "Aborted_connects")
failed_connections.store("Aborted Connections", failedconnections_value)
final_records.push(failed_connections)
# Add Uptime
uptime = Hash.new
uptime_value = get_value(global_stats, "Uptime")
uptime.store("Uptime", uptime_value)
final_records.push(uptime)
# add KeyCacheHitPct
key_cache_hit_pct = Hash.new
key_reads = get_value(global_stats,'Key_reads')
key_read_requests = get_value(global_stats,'Key_read_requests')
value = 0.0 #initialize
if key_read_requests.to_f != 0
value = (key_reads.to_f / key_read_requests.to_f) * 100
end
key_cache_hit_pct.store("Key Cache Hit Pct", value.round(2))
final_records.push(key_cache_hit_pct)
# add MySQL Worst Case RAM Usage
server_max_ram= Hash.new
value = 0.0 #reset
key_buffer_size = get_value(env_var_stats, 'key_buffer_size')
read_buffer_size = get_value(env_var_stats, 'read_buffer_size')
sort_buffer_size = get_value(env_var_stats, 'sort_buffer_size')
max_connections = get_value(env_var_stats, 'max_connections')
value = key_buffer_size.to_f + (read_buffer_size.to_f + sort_buffer_size.to_f)*max_connections.to_f
server_max_ram.store("MySQL Worst Case RAM Usage", value.round(2))
final_records.push(server_max_ram)
#Add MySQL Server Disk Usage In Bytes
q_size_all_db = query(@query_sizeof_all_databases) # Total size
q_size_all_db.each do |row|
s_database = Hash.new()
s_database.store("MySQL Server Disk Usage In Bytes",row["Size (Bytes)"])
final_records.push(s_database)
end
#add SlowQueryPct
slow_query_pct = Hash.new
queries = get_value(global_stats, "Queries")
if queries == -1
# On MySQL 5.0 queries is not supported. instead use queries = questions + com_stmt_close + com_stmt_reset + com_stmt_prepare
# On MySQL 5.1+, just use variable "queries"
questions = get_value(global_stats, "Questions")
com_stmt_close = get_value(global_stats, "Com_stmt_close")
com_stmt_reset = get_Value(global_stats, "Com_stmt_reset")
com_stmt_prepare = get_value(global_stats, "Com_stmt_prepare")
queries = questions.to_i + com_stmt_close.to_i + com_stmt_reset.to_i + com_stmt_prepare.to_i
end
slow_query_pct.store("Slow Query Pct", queries )
final_records.push(slow_query_pct)
#add Key Cache Write Pct
key_cache_write_pct = Hash.new()
key_writes = get_value(global_stats,"Key_writes")
key_writes_requests = get_value(global_stats,"Key_writes_requests")
value = 0.0
if(key_writes_requests.to_f != 0)
value = (key_writes.to_f)/(key_writes_requests.to_f) * 100
end
key_cache_write_pct.store("Key Cache Write Pct", value.round(2))
final_records.push(key_cache_write_pct)
#add Query CacheHitPct
query_cache_hit_pct = Hash.new()
qcache_hits = get_value(global_stats,"Qcache_hits")
com_select = get_value(global_stats,"Com_select")
value = 0.0
if (qcache_hits.to_f + com_select.to_f) != 0
value = qcache_hits.to_f/(qcache_hits.to_f + com_select.to_f)*100
end
query_cache_hit_pct.store("Query Cache Hit Pct", value.round(2))
final_records.push(query_cache_hit_pct)
#add Query Cache Low memory Prunes
query_cache_prunes_pct = Hash.new()
qcache_prunes = get_value(global_stats,"Qcache_lowmem_prunes")
value = 0.0
if queries.to_f != 0
value = (qcache_prunes.to_f/queries.to_f) * 100
end
query_cache_prunes_pct.store("Query Cache Low memory Prunes", value.round(2))
final_records.push(query_cache_prunes_pct)
#add TableCacheHitPct
table_hit_pct = Hash.new()
open_tables = get_value(global_stats,"Open_tables")
opened_tables = get_value(global_stats,"Opened_tables")
value = 0.0
if opened_tables.to_f != 0
value = open_tables.to_f/opened_tables.to_f * 100
end
table_hit_pct.store("Table Cache Hit Pct", value.round(2))
final_records.push(table_hit_pct)
#add TableLockContentionPct
table_lock_pct = Hash.new()
table_lock_waited = get_value(global_stats,"Table_locks_waited")
table_lock_immediate = get_value(global_stats,"Table_locks_immediate")
value = 0.0
if (table_lock_waited.to_f + table_lock_immediate.to_f) != 0
value = table_lock_waited.to_f/(table_lock_waited.to_f + table_lock_immediate.to_f) * 100
end
table_lock_pct.store("Table Lock Contention Pct", value.round(2))
final_records.push(table_lock_pct)
#add InnoDB Buffer Pool Hit Percent
idb_hit_pct = Hash.new()
innodb_buffer_pool_reads = get_value(global_stats,"Innodb_buffer_pool_reads")
innodb_buffer_pool_read_requests = get_value(global_stats,"Innodb_buffer_pool_read_requests")
value = 0.0
if (innodb_buffer_pool_reads.to_f + innodb_buffer_pool_read_requests.to_f) != 0
value = innodb_buffer_pool_reads.to_f/(innodb_buffer_pool_reads.to_f + innodb_buffer_pool_read_requests.to_f) * 100
end
idb_hit_pct.store("InnoDB Buffer Pool Hit Percent", value.round(2))
final_records.push(idb_hit_pct)
#add InnoDB Buffer Pool Percent Use
idb_use_pct = Hash.new()
innodb_buffer_pool_pages_data = get_value(global_stats,"Innodb_buffer_pool_pages_data")
innodb_buffer_pool_pages_total = get_value(global_stats,"Innodb_buffer_pool_pages_total")
value = 0.0
if( innodb_buffer_pool_pages_total.to_f != 0)
value = innodb_buffer_pool_pages_data.to_f/innodb_buffer_pool_pages_total.to_f * 100
end
idb_use_pct.store("InnoDB Buffer Pool Percent Use", value.round(2) )
final_records.push(idb_use_pct)
#add FullTableScanPct
full_table_pct = Hash.new()
handler_read_rnd = get_value(global_stats,"Handler_read_rnd")
handler_read_first = get_value(global_stats,"Handler_read_first")
handler_read_key = get_value(global_stats,"Handler_read_key")
handler_read_next = get_value(global_stats,"Handler_read_next")
handler_read_prev = get_value(global_stats,"Handler_read_prev")
handler_read_rnd_next = get_value(global_stats,"Handler_read_rnd_next")
full_scan_reads = handler_read_rnd.to_f + handler_read_rnd_next.to_f
all_row_access = handler_read_rnd.to_f + handler_read_first.to_f + handler_read_key.to_f + handler_read_next.to_f + handler_read_prev.to_f + handler_read_rnd_next.to_f
value = 0.0 #reset
if all_row_access != 0
value = full_scan_reads/all_row_access * 100
end
full_table_pct.store("Full Table Scan Pct", value.round(2) )
final_records.push(full_table_pct)
# add SlaveStatus
# add SlaveLag
# add ServerCPU
return final_records
end
# retrieve all databases or given database info of the mysql instance as a hashtable
def get_server_databases (input_query)
database_stats = Array.new
#retrieve engine info from default_storage_engine
#engine_info_value = get_server_database_type
#retrieve database version info frm innodb_version
#dbversion_info_value = get_server_database_version
#get database table information
# Example, execute a query to get a result set like:
# +--------------------+--------+-------------------------------+
# | DatabaseName | NumberOfTables | SizeInBytes |
# +--------------------+--------+--------------------------------+
# | information_schema | 28 | 8192 |
# +--------------------+--------+-------------------------------+
stmt = query(input_query)
stmt.each do |row|
# row.store("Engine", engine_info_value)
# row.store("Version", dbversion_info_value)
# Add SizeAllocated
# Add SizeUnits
# Add LastBackup
database_stats.push(row)
end
return database_stats
end
def get_mysql_instance
# retrieve mysql instance stats later to be used in heartbeat
result = Array.new
row = Hash.new
host_name = get_mysql_hostname
row.store("ProductName", "MySQL Server")
prod_id = host_name + ":" + @port.to_s
row.store("ProductIdentifyingNumber", prod_id)
row.store("ProductVendor", "Oracle")
version_value = get_server_database_version
row.store("ProductVersion", version_value.to_s)
q_variables = query(@query_variables)
server_id = get_value(q_variables,"server_id")
row.store("SystemID", server_id.to_s)
compile_os = get_value(q_variables,"version_compile_os")
row.store("CollectionID", compile_os.to_s)
row.store("Name", nil)
socket_info = get_value(q_variables,"socket")
row.store("SocketFile", socket_info.to_s)
row.store("Port", @port.to_s)
data_dir= get_value(q_variables,"datadir")
row.store("DataDirectory", data_dir.to_s)
log_error = get_value(q_variables,"log_error")
row.store("ErrorLogFile", log_error.to_s)
result.push(row)
return result
end
# Convert data to oms format
def enumerate (time)
#final list of counters to send to oms filtered based on the counters supporeted by mysql plugin (per mysql spec)
final_records = Array.new
timestamp = OMS::Common.format_time(time)
# get mysql global stats and variables
mysqlserver_counters = Array.new
server_stats = get_server_stats
server_stats.each do |row|
row.each {
|key, value|
mysql_server_counter = Hash.new
mysql_server_counter.store("CounterName", key)
mysql_server_counter.store("Value", value)
mysqlserver_counters.push(mysql_server_counter)
}
end
host_name = get_mysql_hostname
# Only one mysql instance is supported
mysql_instance = Hash.new
mysql_instance["Timestamp"] = timestamp
mysql_instance["Host"] = host_name
mysql_instance["ObjectName"]="MySQL Server"
mysql_instance_name = host_name + ":" + @port.to_s
mysql_instance["InstanceName"] = mysql_instance_name
mysql_instance["Collections"] = mysqlserver_counters
#add the instance to the list
final_records.push(mysql_instance)
#get mysql database tables info
result_dbs = get_server_databases(@query_get_database)
result_dbs.each do |row|
mysql_db_counters = Array.new
db_instance = Hash.new
db_instance["Timestamp"] = timestamp
db_instance["Host"] = host_name
db_instance["ObjectName"]="MySQL Database"
db_instance["InstanceName"] = row["DatabaseName"]
row.delete("DatabaseName") # leave only table name and size columns and remove database name
row.each {
|key, value|
db_counter = Hash.new
db_counter.store("CounterName", key)
if value.nil?
db_counter.store("Value", 0) # if the given database has no tables, set the size to 0 instead of nil
else
db_counter.store("Value", value)
end
mysql_db_counters.push(db_counter)
}
db_instance["Collections"] = mysql_db_counters
#add the db instance to the list
final_records.push(db_instance)
end
if final_records.length > 0
wrapper = {
"DataType"=>"LINUX_PERF_BLOB",
"IPName"=>"LogManagement",
"DataItems"=>final_records
}
return wrapper
end
end
end
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists