#include <time.h> #ifndef NONAMESPACE #include <iostream> using namespace std; #else #include <iostream.h> #endif #include <string> #include "extremes.h" #include "funcnames.h" #include "funcstats.h" #include "linkedts.h" #include "pidfunc.h" #include "timestamp.h" PidFunc::~PidFunc() { LinkedTS *pnextlts; LinkedTS *plts; pnextlts = pfirstcomputets; while( pnextlts ) { plts = pnextlts; pnextlts = plts->GetPNext(); delete plts; } } time_t PidFunc::GetStartTS() { return startts; } int PidFunc::GetPid() { return pid; } string PidFunc::GetUser() { return user; } string PidFunc::GetClient() { return client; } string PidFunc::GetHost() { return host; } PidFunc *PidFunc::GetNextPidFunc() { return nextpidfunc; } void PidFunc::SetNextPidFunc( PidFunc *anextpidfunc ) { nextpidfunc = anextpidfunc; } int PidFunc::Init( time_t ats, int apid, string line, int iscan, int ispan, FuncNames *pfuncnames ) { int iclientspan; int ihostspan; string func; int ifuncname; int rc; startts = ats; seencompute = false; pfirstcomputets = 0; plastcomputets = 0; seenfinish = false; pid = apid; user = line.substr( iscan, ispan - iscan ); iscan = ispan + 1; ispan = line.find(" ", iscan); client = line.substr( iscan, ispan - iscan ); iscan = ispan + 1; ispan = line.find(" ", iscan); host = line.substr( iscan, ispan - iscan ); iscan = ispan + 1; if (line[iscan] == '[') { ispan = line.find("]", iscan + 1) + 1; program = line.substr( iscan, ispan - iscan ); iscan = ispan + 1; } iscan = ispan + 2; if( (ispan = line.find( " ", iscan + 1 ) ) != line.npos ) { func = line.substr( iscan, ispan - iscan ); iscan = ispan + 1; ispan = line.find( "'", iscan + 1 ); args = line.substr( iscan, ispan - iscan ); } else { ispan = line.find( "'", iscan + 1 ); func = line.substr( iscan, ispan - iscan ); } if( !pfuncnames->Find( func, &ifuncname ) ) if( rc = pfuncnames->Insert( func, ifuncname ) ) return rc; funcstats = pfuncnames->GetStats( ifuncname ); refcount = 0; nextpidfunc = 0; return 0; } void PidFunc::IncrementRefCount() { refcount++; } int PidFunc::DecrementRefCount() { refcount--; return refcount; } void PidFunc::Compute( time_t ts, AllExtremes *pmaxgcomputes, AllExtremes *pmingcomputes ) { LinkedTS *pwaslast; pwaslast = plastcomputets; plastcomputets = new LinkedTS( ts ); if( !seencompute ) { seencompute = true; pfirstcomputets = plastcomputets; } else { pwaslast->SetPNext( plastcomputets ); /* * The second through nth compute end records include the first * through n-1th transfer files phases. So the only meaningful * compute end record for maximum and minimum purposes is the * first. Bail so as not to distort the maximums and minimums * with the second through nth compute end records. But we'll * leave the code here hoping for the day that the first through * n-1th transfer files phases can be isolated away from the * second through nth compute end records. */ return; pmaxgcomputes->Remove( this, compute ); pmingcomputes->Remove( this, compute ); funcstats->BackoutCompute( this, compute ); } compute = difftime( ts, startts ); pmaxgcomputes->Insert( this, compute ); pmingcomputes->Insert( this, compute ); funcstats->UpdateCompute( this, compute ); } void PidFunc::Finish( time_t ts, AllExtremes *pmaxgelapseds, AllExtremes *pmingelapseds ) { seenfinish = true; finishts = ts; elapsed = difftime( ts, startts ); pmaxgelapseds->Insert( this, elapsed ); pmingelapseds->Insert( this, elapsed ); funcstats->UpdateElapsed( this, elapsed ); } string PidFunc::StripComma(string s) { string out; out = s; int i = 0; while ((i = out.find(",")) != string::npos) { out[i] = ';'; } return out; } void PidFunc::PrintDetail( FuncNames *pfuncnames ) { time_t ts; string tsstr; time2str( startts, &tsstr ); cout << tsstr << " " << startts << " "; if( seencompute ) { ts = plastcomputets->GetTS(); time2str( ts, &tsstr ); cout << tsstr << " " << ts << " " << compute << " "; } else { cout << "null null null "; } if( seenfinish ) { time2str( finishts, &tsstr ); cout << tsstr << " " << finishts << " " << elapsed << " "; } else { cout << "null null null "; } cout << pid << " " << user << " " << client << " " << host << " "; cout << *pfuncnames->GetName( funcstats->GetIFuncName() ); if( !args.empty() ) cout << " " << args; cout << "\n"; } void PidFunc::PrintCSV( FuncNames *pfuncnames ) { time_t ts; string tsstr; time2ODBCstr( startts, &tsstr ); cout << tsstr << "," << startts << ","; if( seencompute ) { ts = plastcomputets->GetTS(); time2ODBCstr( ts, &tsstr ); cout << tsstr << "," << ts << "," << compute << ","; } else { cout << "0,0,0,"; } if( seenfinish ) { time2ODBCstr( finishts, &tsstr ); cout << tsstr << "," << finishts << "," << elapsed << ","; } else { cout << "0,0,0,"; } cout << pid << "," << StripComma(user) << "," << StripComma(client) << "," << StripComma(host) << ","; if (!program.empty()) { //client.replace(",", ""); cout << StripComma(program) << ","; } cout << StripComma(*pfuncnames->GetName(funcstats->GetIFuncName())) << ","; if( !args.empty() ) { cout << " " << StripComma(args).substr(0,4094); } else { } cout << "\n"; } void PidFunc::PrintPretty( string prefix, FuncNames *pfuncnames ) { string tsstr; LinkedTS *plts; int icomputets; time2str( startts, &tsstr ); cout << prefix << "Start Time: " << tsstr << "\n"; if( seencompute ) { plts = pfirstcomputets; icomputets = 0; while( plts ) { time2str( plts->GetTS(), &tsstr ); cout << prefix << "Compute Phase Times[" << icomputets << "]: "; cout << tsstr; /* * Print the compute phase elapsed time on the first compute * phase timestamp since the only compute end record included * in the compute phase elapsed time is the first. */ if( !icomputets ) cout << " Compute Phase Elapsed Time: " << compute; cout << "\n"; plts = plts->GetPNext(); icomputets++; } } if( seenfinish ) { time2str( finishts, &tsstr ); cout << prefix << "Finish Time: " << tsstr; cout << " Total Elapsed Time: " << elapsed << "\n"; } cout << prefix << "Process/Thread ID: " << pid; cout << " User: " << user << "\n"; cout << prefix << "Client: " << client; cout << " Host: " << host << "\n"; if( pfuncnames ) cout << prefix << "Function: " << *pfuncnames->GetName( funcstats->GetIFuncName() ) << "\n"; if( !args.empty() ) cout << prefix << "Arguments: " << args << "\n"; }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#2 | 5390 | Shawn Hladky |
modified p4loga: added --csv switch to output a coma-separated variable file identifying every command function recorded. No header or summary info is displayed. This file can be loaded in a spreadsheet application or imported into a database for further analysis. added support to identify the ClientProgram name from the log file. At this point, only server logs for a 2005.1 server have been (minimally) tested. |
||
#1 | 5389 | Shawn Hladky | Branching p4loga for modifications | ||
//guest/michael_shields/src/p4loga/pidfunc.cc | |||||
#2 | 1722 | Michael Shields |
p4loga builds for freebsd4 (play), hpux11 (hell), linux24x86 (duey), and solaris26 (shucks). A bit of porting was required for the hpux11 build (aCC as configured on hell isn't quite up to speed with respect to namespaces). |
||
#1 | 1610 | Michael Shields |
Adding p4d log analyzer concocted by myself. Compiles and executes on Red Hat 6.0, 7.0, and probably a few other operating systems with perhaps a little help. Still needs comments. |