#!/usr/local/bin/perl # # $Header: emdb/sysman/admin/scripts/rac/collectSrvPerf.pl /st_emdbsa_11.2/5 2009/03/20 22:21:46 rsamaved Exp $ # # collectSrvPerf.pl # # Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved. # # NAME # collectSrvPerf.pl - # # DESCRIPTION # # # NOTES # # # MODIFIED (MM/DD/YY) # rsamaved 03/18/09 - fix typo # ngade 02/02/09 - Code slap 10.2.0.5.0 -> 11.2 round 2 # gallison 12/04/08 - Fix up services on standby # sadattaw 06/19/07 - put inst cpu & core into hashtable # sadattaw 05/28/07 - fix numcores . # sadattaw 03/15/07 - fix available CPU computation # rsamaved 02/16/07 - fix min resp calculation # rsamaved 01/30/07 - adding method to get instance level elapsed time # and cpu time values # rsamaved 01/26/07 - # sadattaw 01/25/07 - service performance collection methods # sadattaw 01/25/07 - Creation # use strict; use DBI qw(:sql_types); use Cwd; require "$ENV{EMDROOT}/sysman/admin/scripts/db/dbstate.pl"; require "$ENV{EMDROOT}/sysman/admin/scripts/db/dg/dgutil.pl"; sub collect_service_metric { my ($usr_name, $pwd, $dbName, $addr, $role ) = @_; my $mode = 0; if($role =~ /SYSDBA/i) { $mode = 2; } elsif($role =~ /SYSOPER/i) { $mode = 4; } # -------------------------------------------------------------------- # +++ Establish Target DB Connection # -------------------------------------------------------------------- my $lda = DBI->connect('dbi:Oracle:', "$usr_name@".$addr, "$pwd", {ora_session_mode => $mode, PrintError => 0, RaiseError => 0, AutoCommit => 0}) or die "em_error=Could not connect to $usr_name/$addr: $DBI::errstr\n"; #print "DB connection successful : $address \n"; EMD_PERL_DEBUG( "DB connection successful: $addr \n"); my $database_role = getDBRole($lda); # do not collect any service info if mounted since views are not accessible... my $database_status = getDBStatus($lda); if ($database_status !~ /OPEN/i) { EMD_PERL_DEBUG( "Skipping services.. RAC DB is $database_status\n"); print "em_result=1||\n"; $lda->disconnect(); exit 0; } #gv$services table does not exclude deleted services so use all_servies to get service list from db my $tbl = 'all_services'; #Query services defined for this database my $sql = qq{ SELECT DISTINCT service_id, name, creation_date FROM $tbl }; my $sth = $lda->prepare( $sql ); $sth->execute(); my( $srv_id, $srv_name, $cr_date); $sth->bind_columns( undef, \$srv_id, \$srv_name, \$cr_date); #print "Service names from query \n"; EMD_PERL_DEBUG( "Service names from query \n"); my $instcpus = {}; my $instcores = {}; my $instnames = {}; while( $sth->fetch() ) { # print "Service : $srv_id, $srv_name, $cr_date\n"; EMD_PERL_DEBUG( "Service : $srv_id, $srv_name, $cr_date\n"); #For each service calculate the metric get_service_metric($srv_name, $lda, $dbName, $instcpus, $instcores, $instnames, $database_role); } $sth->finish(); $lda->disconnect(); } sub getDBStatus { my ( $connection ) = @_; my $sql = "select status from v\$instance"; my $dbcur = $connection->prepare($sql); $dbcur->execute; my @row = $dbcur->fetchrow_array(); my $status = $row[0]; return ("${status}"); } sub get_service_metric { my ( $srv_name, $connection, $dbname, $instcpu, $instcore, $instnm, $dbrole) = @_; my $met_tbl = 'gv$servicemetric_history'; my $actserv_tbl = 'gv$active_services'; my $inst_tbl = 'gv$instance'; my $param_tbl = 'gv$osstat'; # print "get_service_metric : $srv_name\n"; EMD_PERL_DEBUG( "get_service_metric : $srv_name , role $dbrole\n"); #calculate average response time and throughput values across all instances for a given service # hence query gv$ tables my $met_sql = qq{ SELECT mt.inst_id, service_name, TO_CHAR(CAST(begin_time AS TIMESTAMP) AT TIME ZONE 'GMT', 'YYYY-MM-DD HH24:MI:SS TZD') time, TO_CHAR(CAST(end_time AS TIMESTAMP) AT TIME ZONE 'GMT', 'YYYY-MM-DD HH24:MI:SS TZD') time, intsize_csec, group_id, cpupercall, dbtimepercall, callspersec, dbtimepersec FROM $met_tbl mt , $actserv_tbl ast WHERE service_name = ? AND end_time >= SYSDATE - 5/(60*24) AND group_id = 6 and mt.service_name = ast.name and mt.inst_id = ast.inst_id ORDER BY mt.inst_id asc, end_time DESC }; my $met_sth = $connection->prepare( $met_sql ); if (!$met_sth) { EMD_PERL_DEBUG( "em_error=prepare query failed for metric query, returning \n"); print "em_error=prepare query failed for metric query, returning \n"; return; } $met_sth->bind_param( 1, $srv_name, SQL_VARCHAR ); $met_sth->execute(); my( $instid, $sv_name, $beginTime, $endTime, $interval, $grpid, $cpupercall, $dbpercall, $callspersec, $dbtimepersec); $met_sth->bind_columns( undef, \$instid, \$sv_name, \$beginTime, \$endTime, \$interval, \$grpid, \$cpupercall, \$dbpercall, \$callspersec, \$dbtimepersec ); # print "\n -- getServiceMetric:: Service metrics records for service $srv_name \n"; # print "instid | service name | begin time | end time | interval | groupid | cpupercall | dbpercall | calls/sec | dbtime/sec \n"; EMD_PERL_DEBUG( "\n -- getServiceMetric:: Service metrics records for service $srv_name \n"); ## EMD_PERL_DEBUG( "instid | service name | begin time | end time | interval | groupid | cpupercall | dbpercall | calls/sec | dbtime/sec \n"); my $cpu_sql = qq{ SELECT value FROM $param_tbl WHERE inst_id = ? and stat_name='NUM_CPUS' }; my $cpu_core_sql = qq{ SELECT value FROM $param_tbl WHERE inst_id = ? and stat_name='NUM_CPU_CORES' }; my $inst_sql = qq{ SELECT instance_name FROM $inst_tbl WHERE inst_id = ? }; my $inst_sth = $connection->prepare( $inst_sql ); # my $minresp = 1000000.0; my $minresp; my $maxresp; my $mininst = 1; my $maxinst = 1; ## need some value if all the resp times are 0 my $timedif = 0.0; my $cpuload = 0.0; my $totalcpu = 0.0; my $availcpu = 0.0; my $avgResponse = 0.0; my $totalcalls = 0.0; my $service_status = ''; my $running_instlist = ''; my $lastinst = 0; my $totalcpuInst = 0.0; my $availinstcpuInst = 0.0; my $avgResponseInst = 0.0; my $totalcallsInst = 0.0; my $beginTimeInst; my $endTimeInst; my $instentries = 0; my $inst_cpu =0; my $cpu_sth = $connection->prepare( $cpu_sql ); my $inst_cpu_cores =0; my $cpu_core_sth = $connection->prepare( $cpu_core_sql ); my $inst_name = ""; while( $met_sth->fetch() ) { ## print "$instid, $sv_name, $beginTime, $endTime, $interval, $grpid, $cpupercall, $dbpercall, $callspersec, $dbtimepersec \n"; ## EMD_PERL_DEBUG( "$instid, $sv_name, $beginTime, $endTime, $interval, $grpid, $cpupercall, $dbpercall, $callspersec, $dbtimepersec \n"); $timedif = $interval /100; #interval is in 100th of sec #print "timedif $timedif \n"; if ($callspersec == 0) { $callspersec = 1; } if ($instid != $lastinst) { if ($lastinst != 0) { if ($totalcallsInst != 0.0) { #print "$instid :: total dbtimeInst: $avgResponseInst, total cpu inst : $totalcpuInst, total callsInst: $totalcallsInst \n"; $totalcpuInst = $totalcpuInst / $totalcallsInst; $avgResponseInst = $avgResponseInst / $totalcallsInst; } print "inst_result=$dbname|$srv_name|$lastinst|$inst_name|$beginTimeInst|$endTimeInst|$totalcpuInst|$avgResponseInst\n"; EMD_PERL_DEBUG("inst_result=$dbname|$srv_name|$lastinst|$inst_name|$beginTimeInst|$endTimeInst|$totalcpuInst|$avgResponseInst\n"); } $inst_cpu = $instcpu->{$instid}; if (!defined $inst_cpu) { $cpu_sth->execute($instid); $cpu_sth->bind_columns( undef, \$inst_cpu ); $cpu_sth->fetch(); $instcpu->{$instid} = $inst_cpu; # print "instance $instid, cpu count : $inst_cpu\n"; EMD_PERL_DEBUG( "instance $instid, cpu count : $inst_cpu \n"); } if ($inst_cpu == 0) { $inst_cpu = 1; } $inst_cpu_cores = $instcore->{$instid}; if (!defined $inst_cpu_cores) { $cpu_core_sth->execute($instid); $cpu_core_sth->bind_columns( undef, \$inst_cpu_cores ); $cpu_core_sth->fetch(); $instcore->{$instid} = $inst_cpu_cores; # print "instance $instid, cpu core count: $inst_cpu_cores \n"; EMD_PERL_DEBUG( "instance $instid, cpu core count: $inst_cpu_cores \n"); } if ($inst_cpu_cores == 0) { $inst_cpu_cores = 1; } $inst_name = $instnm->{$instid}; if (!defined $inst_name) { $inst_sth->execute($instid); $inst_sth->bind_columns( undef, \$inst_name ); $inst_sth->fetch(); $instnm->{$instid} = $inst_name; # print "instance $instid, nm : $inst_name \n"; EMD_PERL_DEBUG( "instance $instid, nm : $inst_name \n"); } $lastinst = $instid; $totalcpuInst = 0.0; $availinstcpuInst = 0.0; $avgResponseInst = 0.0; $totalcallsInst = 0.0; $beginTimeInst = $beginTime; $instentries = 0; } $totalcpuInst += ($cpupercall / 1000) * $callspersec * $timedif; $availinstcpuInst += $timedif* 1000 * $inst_cpu * $inst_cpu_cores; # get in to milliseconds $avgResponseInst += ($dbpercall/1000) * $callspersec * $timedif; $totalcallsInst += $callspersec * $timedif; $endTimeInst = $endTime; $totalcpu += ($cpupercall / 1000) * $callspersec * $timedif; $availcpu += $timedif* 1000 * $inst_cpu * $inst_cpu_cores; # get in to milliseconds ## $avgResponse += $dbpercall; ### $availcpu += $dbpercall * $callspersec * $timedif * $inst_cpu; $avgResponse += ($dbpercall/1000) * $callspersec * $timedif; $totalcalls += $callspersec * $timedif; if (! defined $minresp or ($dbpercall < $minresp)) { $minresp = $dbpercall; $mininst = $instid; } if ( ! defined $maxresp or ($dbpercall > $maxresp)) { $maxresp = $dbpercall; $maxinst = $instid; } } if ($availcpu != 0) { $cpuload = ($totalcpu/$availcpu) *100; } # print the last instance data if ($totalcallsInst != 0.0) { #print "$instid :: total dbtimeInst: $avgResponseInst, total cpu inst : $totalcpuInst, total callsInst: $totalcallsInst \n"; $totalcpuInst = $totalcpuInst / $totalcallsInst; $avgResponseInst = $avgResponseInst / $totalcallsInst; } print "inst_result=$dbname|$srv_name|$lastinst|$inst_name|$beginTimeInst|$endTimeInst|$totalcpuInst|$avgResponseInst\n"; EMD_PERL_DEBUG("inst_result=$dbname|$srv_name|$lastinst|$inst_name|$beginTimeInst|$endTimeInst|$totalcpuInst|$avgResponseInst\n"); # if ($met_sth->rows != 0) # { # $avgResponse = $avgResponse / ($met_sth->rows); # } # print "total cputime: $totalcpu, avail cputime: $availcpu , cpuload % $cpuload\n"; EMD_PERL_DEBUG("total cputime: $totalcpu, avail cputime: $availcpu, cpuload % $cpuload\n"); if ($totalcalls != 0.0) { $avgResponse = $avgResponse / $totalcalls; } # print "total dbtime: $avgResponse, total calls: $totalcalls \n"; EMD_PERL_DEBUG("total dbtime: $avgResponse, total calls: $totalcalls\n"); my $mininst_name = ''; my $maxinst_name = ''; if (! defined $minresp) { $minresp = 0.0; } else { $mininst_name = $instnm->{$mininst}; if (!defined $mininst_name) { $inst_sth->execute($mininst); $inst_sth->bind_columns( undef, \$mininst_name ); $inst_sth->fetch(); } } if (! defined $maxresp) { $maxresp = 0.0; } else { $maxinst_name = $instnm->{$maxinst}; if (!defined $maxinst_name) { $inst_sth->execute($maxinst); $inst_sth->bind_columns( undef, \$maxinst_name ); $inst_sth->fetch(); } } $minresp = $minresp/1000; $maxresp = $maxresp/1000; # print "min resp: $minresp, min instid : $mininst, min instname: $mininst_name \n"; # EMD_PERL_DEBUG( "min resp: $minresp, min instid : $mininst, min instname: $mininst_name \n"); # print "max resp: $maxresp, max instid : $maxinst, max instname: $maxinst_name \n"; # EMD_PERL_DEBUG( "max resp: $maxresp, max instid : $maxinst, max instname: $maxinst_name \n"); my $stat_sql = qq{ SELECT s.inst_id, s.name, i.instance_name FROM $actserv_tbl s, $inst_tbl i WHERE s.name = ? AND s.inst_id = i.inst_id }; my $stat_sth = $connection->prepare( $stat_sql ); $stat_sth->execute($srv_name); my( $stat_instid, $stat_sv_name, $stat_instnm); $stat_sth->bind_columns( undef, \$stat_instid, \$stat_sv_name, \$stat_instnm ); my $idx = 0; while( $stat_sth->fetch() ) { # print "$stat_instid, $stat_sv_name, $stat_instnm \n"; # EMD_PERL_DEBUG( "$stat_instid, $stat_sv_name, $stat_instnm , $idx \n"); if ($idx != 0) { $running_instlist = $running_instlist.","; } $running_instlist = $running_instlist.$stat_instnm; $idx++; } if ($stat_sth->rows != 0) { $service_status = "Up"; } else { $service_status = "Down"; } if ($srv_name eq 'seeddata' or $srv_name eq 'seeddataXDB') { $service_status = ""; } # ignore service if down and standby role. if ($service_status eq "Down" && $dbrole !~ /PRIMARY/i) { EMD_PERL_DEBUG( "Ignoring $service_status service $srv_name for $dbrole.\n"); } else { print "em_result=$dbname|$srv_name|$minresp|$mininst_name|$maxresp|$maxinst_name|$avgResponse|$cpuload|$service_status|$running_instlist\n"; EMD_PERL_DEBUG( "em_result=$dbname|$srv_name|$minresp|$mininst_name|$maxresp|$maxinst_name|$avgResponse|$cpuload|$service_status|$running_instlist\n"); } }