Windows2003-3790/sdktools/trace/tracectr/report.c
2020-09-30 16:53:55 +02:00

4061 lines
152 KiB
C

/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
report.c
Abstract:
Manipulation routines for cpdata structures.
Author:
Melur Raghuraman (mraghu) 03-Oct-1997
Environment:
Revision History:
Corey Morgan (coreym) 04-June-2002
Reformatted report output to XML.
--*/
#include <stdlib.h>
#include <stdio.h>
#include "cpdata.h"
#include "tracectr.h"
#include <ntverp.h>
#include "item.h"
#define MODULE_STRING_SIZE 256
#define FILE_NAME_COLUMN_SIZE 80
#define URL_NAME_COLUMN_SIZE 79
#define MAX_GUID_STRING_SIZE 64
#define DISPLAY_SIZE 10
extern PTRACE_CONTEXT_BLOCK TraceContext;
extern ULONG TotalEventsLost;
extern ULONG TotalEventCount;
extern ULONG TimerResolution;
extern __int64 ElapseTime;
extern ULONG TotalBuffersRead;
extern BOOLEAN XPorHigher;
extern FARPROC EtwpIpv4ToStringA;
extern FARPROC EtwpIpv4ToStringW;
extern FARPROC EtwpIpv6ToStringA;
extern FARPROC EtwpIpv6ToStringW;
static FILE* procFile;
static void PrintDiskTotals();
static void PrintProcessCpuTime();
static void PrintProcessData();
static void PrintPerThreadPerDiskTable();
static void WriteTransactionStatistics();
static void WriteTransactionCPUTime();
static void PrintProcessSubDataInclusive();
static void PrintProcessSubDataExclusive();
void TransInclusive(
PLIST_ENTRY TrHead,
ULONG level
);
static void ReportHotFileInfo();
static void ReportPrintJobInfo();
PIIS_REPORT_RECORD IIS = NULL;
ULONG RequestsDiscarded = 0;
ULONG SendErrorRequests = 0;
void ProcessIisRequest(HTTP_REQUEST_RECORD *pReq);
static void ReportIisEvents();
extern GUID PrintJobGuid;
extern GUID UlGuid;
#ifdef DBG
BOOLEAN TracectrDbgEnabled = FALSE;
#endif
PWCHAR CpdiGuidToString(
PWCHAR s,
ULONG len,
LPGUID piid
);
PCHAR RemoveCtrlCharA(
PCHAR String,
ULONG NumChars
);
PCHAR ReduceStringA(
PCHAR OutString,
ULONG NumChars,
PCHAR LongString
);
PWCHAR ReduceStringW(
PWCHAR OutString,
ULONG NumChars,
PWCHAR LongString
);
ULONG ReportFlags = 0;
void DecodeIpAddressA(
USHORT AddrType,
PULONG IpAddrV4,
PUSHORT IpAddrV6,
PCHAR pszA
)
{
if (AddrType == TDI_ADDRESS_TYPE_IP) {
if (XPorHigher && EtwpIpv4ToStringA != NULL) {
struct in_addr IPv4Addr
= * (struct in_addr UNALIGNED*) IpAddrV4;
pszA = (PCHAR)(*EtwpIpv4ToStringA)(&IPv4Addr, pszA);
*pszA = '\0';
}
else {
StringCchCopyA(pszA, MAX_ADDRESS_LENGTH, "Undecodable IP Address");
}
}
else if (AddrType == TDI_ADDRESS_TYPE_IP6) {
if (XPorHigher && EtwpIpv6ToStringA != NULL) {
struct in6_addr IPv6Addr
= * (struct in6_addr UNALIGNED*) IpAddrV6;
pszA = (PCHAR)(*EtwpIpv6ToStringA)(&IPv6Addr, pszA);
*pszA = '\0';
}
else {
StringCchCopyA(pszA, MAX_ADDRESS_LENGTH, "Undecodable IP Address");
}
}
else {
StringCchCopyA(pszA, MAX_ADDRESS_LENGTH, "Unknown IP Address Type");
}
}
void DecodeIpAddressW(
USHORT AddrType,
PULONG IpAddrV4,
PUSHORT IpAddrV6,
PWCHAR pszW
)
{
if (AddrType == TDI_ADDRESS_TYPE_IP) {
if (XPorHigher && EtwpIpv4ToStringW != NULL) {
struct in_addr IPv4Addr
= * (struct in_addr UNALIGNED*) IpAddrV4;
pszW = (PWCHAR)(*EtwpIpv4ToStringW)(&IPv4Addr, pszW);
*pszW = L'\0';
}
else {
StringCchCopyW(pszW, MAX_ADDRESS_LENGTH, L"Undecodable IP Address");
}
}
else if (AddrType == TDI_ADDRESS_TYPE_IP6) {
if (XPorHigher && EtwpIpv6ToStringW != NULL) {
struct in6_addr IPv6Addr
= * (struct in6_addr UNALIGNED*) IpAddrV6;
pszW = (PWCHAR)(*EtwpIpv6ToStringW)(&IPv6Addr, pszW);
*pszW = L'\0';
}
else {
StringCchCopyW(pszW, MAX_ADDRESS_LENGTH, L"Undecodable IP Address");
}
}
else {
StringCchCopyW(pszW, MAX_ADDRESS_LENGTH, L"Unknown IP Address Type");
}
}
// URLs may contain non-printable characters. This routine removes them.
PCHAR RemoveCtrlCharA(
PCHAR String,
ULONG NumChars
)
{
ULONG i;
for (i = 0 ; i <= NumChars && String[i] != '\0'; i++) {
if ( isprint(String[i]) == 0 ||
String[i] == '\t' ||
String[i] == '\b' ||
String[i] == '\n' ||
String[i] == '\'' ||
String[i] == '\"') {
String[i] = '?';
}
}
return String;
}
PCHAR ReduceStringA(
PCHAR OutString,
ULONG NumChars,
PCHAR LongString
)
{
ULONG Size;
ULONG i;
if (LongString == NULL) {
return NULL;
}
// We assume here that LongString is not junk.
Size = strlen(LongString);
if (OutString == NULL) {
return NULL;
}
RtlZeroMemory(OutString, NumChars);
// This function is only useful when the length of LongString exceeds NumChars.
// However, it still works when the length of LongString is smaller than NumChars.
if (Size <= (NumChars - 1)) {
StringCchCopyA(OutString, NumChars, LongString);
return OutString;
}
i = Size - 1;
while (LongString[i] != '\\' && LongString[i] != '/' && i > 0) {
i--;
}
if (i == 0) { // there's no /s or \s. Just truncate.
StringCchCopyA(OutString, NumChars, LongString);
return OutString;
}
else {
if ((Size - i) >= NumChars - 3) { // only name exceeds given chars.
StringCchPrintfA(OutString, NumChars, "..%s", &LongString[1]);
return OutString;
}
else {
ULONG SpareChars = (NumChars - 3) - (Size - i);
StringCchCopyA(OutString, SpareChars + 1, LongString);
StringCchCatA(OutString, NumChars + 1, "..");
StringCchCatA(OutString, NumChars + 1, &LongString[i]);
return OutString;
}
}
}
PWCHAR ReduceStringW(
PWCHAR OutString,
ULONG NumChars,
PWCHAR LongString
)
{
ULONG Size;
ULONG i;
if (LongString == NULL) {
return NULL;
}
// We assume here that LongString is not junk.
Size = wcslen(LongString);
if (OutString == NULL) {
return NULL;
}
RtlZeroMemory(OutString, NumChars * sizeof(WCHAR));
// This function is only useful when the length of LongString exceeds NumChars.
// However, it still works when the length of LongString is smaller than NumChars.
if (Size <= (NumChars - 1)) {
StringCchCopyW(OutString, NumChars, LongString);
return OutString;
}
i = Size - 1;
while (LongString[i] != L'\\' && LongString[i] != L'/' && i > 0) {
i--;
}
if (i == 0) { // there's no /s or \s. Just truncate.
StringCchCopyW(OutString, NumChars, LongString);
return OutString;
}
else {
if ((Size - i) >= NumChars - 3) { // only name exceeds given chars.
StringCchPrintfW(OutString, NumChars, L"..%ws", &LongString[1]);
return OutString;
}
else {
ULONG SpareChars = (NumChars - 3) - (Size - i);
StringCchCopyW(OutString, SpareChars + 1, LongString);
StringCchCatW(OutString, NumChars + 1, L"..");
StringCchCatW(OutString, NumChars + 1, &LongString[i]);
return OutString;
}
}
}
void CollapseTree(
PLIST_ENTRY OldTree,
PLIST_ENTRY NewTree,
BOOL flat
)
{
PLIST_ENTRY OldNext;
PTRANS_RECORD pTrans;
PTRANS_RECORD pNewTrans;
OldNext = OldTree->Flink;
while (OldNext != OldTree)
{
pTrans = CONTAINING_RECORD(OldNext, TRANS_RECORD, Entry);
OldNext = OldNext->Flink;
pNewTrans = FindTransByList(NewTree, pTrans->pGuid, 0);
if( NULL != pNewTrans ){
pNewTrans->KCpu += pTrans->KCpu;
pNewTrans->UCpu += pTrans->UCpu;
pNewTrans->RefCount += pTrans->RefCount;
pNewTrans->RefCount1 += pTrans->RefCount1;
if (flat)
{
CollapseTree(&pTrans->SubTransListHead, NewTree, TRUE );
}
else
{
CollapseTree(& pTrans->SubTransListHead,
& pNewTrans->SubTransListHead,
FALSE);
}
}
}
}
#define BARLEN 70
char*
TimeWindowBar(
char* buffer,
ULONGLONG min,
ULONGLONG max
)
{
double unit;
ULONGLONG duration;
int pre, bar, count, index;
if(buffer == NULL){
return NULL;
}
duration = ((CurrentSystem.EndTime - CurrentSystem.StartTime) / 10000000);
unit = (double)BARLEN/(ULONG)duration;
pre = (int)((ULONG)((min - CurrentSystem.StartTime)/10000000) * unit);
bar = (int)((ULONG)((max - min)/10000000) * unit);
buffer[0] = '\0';
count = 0;
index = 0;
while(count < pre) {
buffer[index] = ' ';
index++;
count++;
}
buffer[index] = '|';
index++;
count = 0;
while(count < bar) {
buffer[index] = '_';
index++;
count++;
}
buffer[index] = '|';
buffer[index + 1] = '\0';
return buffer;
}
char*
GetDateString( char* buffer, size_t cchBuffer, ULONGLONG llTime )
{
FILETIME ft, lft;
SYSTEMTIME st;
LARGE_INTEGER LargeTmp;
BOOL bResult;
HRESULT hr;
WCHAR wDate[128];
CHAR aDate[128];
LargeTmp.QuadPart = llTime;
ft.dwHighDateTime = LargeTmp.HighPart;
ft.dwLowDateTime = LargeTmp.LowPart;
FileTimeToLocalFileTime(&ft, &lft);
bResult = FileTimeToSystemTime (
&lft,
&st
);
if( ! bResult || st.wMonth > 12 ){
buffer[0] = '\0';
}else{
GetDateFormatW(
LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, wDate, 128 );
WideCharToMultiByte(
CP_UTF8, 0, wDate, wcslen(wDate)+1, aDate, 128, NULL, NULL );
hr = StringCchCopyA( buffer, cchBuffer, aDate );
hr = StringCchCatA( buffer, cchBuffer, " " );
GetTimeFormatW(
LOCALE_USER_DEFAULT, 0, &st, NULL, wDate, 128 );
WideCharToMultiByte(
CP_UTF8, 0, wDate, wcslen(wDate)+1, aDate, 128, NULL, NULL );
hr = StringCchCatA( buffer, cchBuffer, aDate );
}
return buffer;
}
void
WriteProc(
LPWSTR ProcFileName,
ULONG flags,
PVOID pUserContext
)
{
ULONGLONG duration;
PLIST_ENTRY Next, Head;
PPROCESS_FILE_RECORD pFileRec;
char buffer[MAXSTR];
BOOL bResult;
ReportFlags = flags;
procFile = _wfopen(ProcFileName, L"w");
if (procFile == NULL)
return;
fprintf( procFile, "<?xml version=\"1.0\" encoding='UTF-8'?>\n" );
if( !(TraceContext->Flags & TRACE_TRANSFORM_XML ) && TraceContext->XSLDocName != NULL ){
fprintf( procFile, "<?xml-stylesheet type=\"text/xsl\" href=\"%ws\"?>\n", TraceContext->XSLDocName );
}
fprintf( procFile, "<report>\n<header>\n" );
fprintf( procFile, "<version>%d</version>\n", VER_PRODUCTBUILD );
fprintf( procFile, "<type>%s</type>\n", ( ReportFlags & TRACE_TOTALS_REPORT ) ? "Total" : "Default" );
fprintf( procFile, "<build>%d</build>\n",CurrentSystem.BuildNumber );
fprintf( procFile, "<processors>%d</processors>\n", CurrentSystem.NumberOfProcessors );
if (CurrentSystem.CpuSpeed > 0) {
fprintf(procFile,
"<cpu_speed units='MHz'>%d</cpu_speed>\n",
CurrentSystem.CpuSpeed
);
} else {
fprintf(procFile, "<cpu_speed/>\n" );
}
if (CurrentSystem.MemorySize > 0) {
fprintf(procFile,
"<memory units='Mb'>%d</memory>\n",
CurrentSystem.MemorySize
);
} else {
fprintf(procFile, "<memory/>\n" );
}
if (CurrentSystem.ComputerName != NULL) {
fprintf(procFile,
"<computer_name>%ws</computer_name>\n",
CurrentSystem.ComputerName
);
} else {
fprintf(procFile, "<computer_name/>\n" );
}
fprintf( procFile, "<start>%s</start>\n",
GetDateString( buffer, MAXSTR, CurrentSystem.StartTime ) );
fprintf( procFile, "<end>%s</end>\n",
GetDateString( buffer, MAXSTR, CurrentSystem.EndTime) );
duration = (CurrentSystem.EndTime - CurrentSystem.StartTime) / 10000000;
fprintf( procFile, "<duration>%I64u</duration>\n",duration );
Head = &CurrentSystem.ProcessFileListHead;
Next = Head->Flink;
while (Next != Head) {
pFileRec = CONTAINING_RECORD( Next, PROCESS_FILE_RECORD, Entry );
Next = Next->Flink;
fprintf( procFile, "<trace name=\"%ws\">\n", pFileRec->TraceName ? pFileRec->TraceName : L"-" );
fprintf( procFile, "<file>%ws</file>\n", pFileRec->FileName ? pFileRec->FileName : L"-" );
if (pFileRec->StartTime == 0){
pFileRec->StartTime = CurrentSystem.StartTime;
}
if (pFileRec->EndTime == 0){
pFileRec->EndTime = CurrentSystem.EndTime;
}
fprintf( procFile, "<start>%s</start>\n",
GetDateString( buffer, MAXSTR, pFileRec->StartTime ) );
duration = (pFileRec->EndTime - pFileRec->StartTime) / 10000000;
fprintf( procFile,
"<end>%s</end>\n"
"<duration>%I64u</duration>\n",
GetDateString( buffer, MAXSTR, pFileRec->EndTime ),
duration );
fprintf( procFile,
"<duration_window xml:space='preserve'>%s</duration_window>\n",
TimeWindowBar(buffer, pFileRec->StartTime, pFileRec->EndTime) );
fprintf( procFile, "</trace>\n" );
}
fprintf( procFile, "</header>\n" );
if (flags & (TRACE_BASIC_REPORT|TRACE_TOTALS_REPORT)){
PMOF_INFO pMofInfo;
WriteTransactionStatistics();
WriteTransactionCPUTime();
pMofInfo = GetMofInfoHead ((LPCGUID)&PrintJobGuid);
if ( pMofInfo != NULL ){
if (pMofInfo->EventCount > 0) {
ReportPrintJobInfo();
}
}
pMofInfo = GetMofInfoHead ((LPCGUID)&UlGuid);
if ( pMofInfo != NULL ){
if (pMofInfo->EventCount > 0) {
ReportIisEvents();
}
}
// PrintProcessData() must be run before others to set the process
// time from the added thread times
PrintProcessData();
PrintProcessSubDataExclusive();
PrintProcessSubDataInclusive();
/*
PrintProcessCpuTime();
*/
PrintDiskTotals();
PrintPerThreadPerDiskTable();
pMofInfo = GetMofInfoHead ((LPCGUID)&FileIoGuid);
if ( pMofInfo != NULL ) {
pMofInfo = GetMofInfoHead ((LPCGUID)&DiskIoGuid);
if ( pMofInfo != NULL ) {
ReportHotFileInfo();
}
}
}
fprintf( procFile, "</report>\n" );
fclose(procFile);
}
static void
PrintDiskTotals()
{
// Print the Disk Table.
PTDISK_RECORD pDisk;
PLIST_ENTRY Next, Head;
ULONG rio, wio;
ULONGLONG Duration = (ULONGLONG)((CurrentSystem.EndTime - CurrentSystem.StartTime) / 10000000);
if (Duration == 0) {
return;
}
Head = &CurrentSystem.GlobalDiskListHead;
Next = Head->Flink;
if( Next == Head ){
return;
}
fprintf(procFile, "<table title='Disk Totals'>\n" );
Head = &CurrentSystem.GlobalDiskListHead;
Next = Head->Flink;
while (Next != Head) {
pDisk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
rio = pDisk->ReadCount + pDisk->HPF;
wio = pDisk->WriteCount;
fprintf( procFile, "<disk number=\"%d\">\n", pDisk->DiskNumber );
fprintf( procFile, "<read_rate>%1.3f</read_rate>\n", (double)rio / ((double)Duration) );
fprintf( procFile, "<read_size>%d</read_size>\n", (rio == 0) ? 0 : (pDisk->ReadSize + pDisk->HPFSize) / rio );
fprintf( procFile, "<write_rate>%1.3f</write_rate>\n", (double)wio / ((double)Duration));
fprintf( procFile, "<write_size>%d</write_size>\n", (wio == 0) ? 0 : pDisk->WriteSize / wio );
fprintf( procFile, "</disk>\n" );
Next = Next->Flink;
}
fprintf(procFile, "</table>\n" );
}
void TotalTransChildren(
PLIST_ENTRY Head,
ULONG *Kernel,
ULONG *User,
LONG level )
{
PTRANS_RECORD pTrans;
PLIST_ENTRY Next;
Next = Head->Flink;
while( Next != Head ){
pTrans = CONTAINING_RECORD( Next, TRANS_RECORD, Entry );
Next = Next->Flink;
TotalTransChildren( &pTrans->SubTransListHead, Kernel, User, level+1 );
*Kernel += pTrans->KCpu;
*User += pTrans->UCpu;
}
}
void PrintTransList( PLIST_ENTRY TrHead, LONG level )
{
PTRANS_RECORD pTrans;
PMOF_INFO pMofInfo;
ULONG Kernel;
ULONG User;
WCHAR str[MAXSTR];
WCHAR buffer[MAXSTR];
PLIST_ENTRY TrNext = TrHead->Flink;
while( TrNext != TrHead ){
int count = 0;
pTrans = CONTAINING_RECORD( TrNext, TRANS_RECORD, Entry );
TrNext = TrNext->Flink;
Kernel = pTrans->KCpu;
User = pTrans->UCpu;
pMofInfo = GetMofInfoHead( pTrans->pGuid);
if (pMofInfo == NULL) {
return;
}
StringCchCopyW ( buffer,
MAXSTR,
( pMofInfo->strDescription ?
pMofInfo->strDescription :
CpdiGuidToString( str, MAXSTR, &pMofInfo->Guid ) ));
TotalTransChildren( &pTrans->SubTransListHead, &Kernel, &User, 0 );
fprintf( procFile, "<transaction name=\"%ws\">\n", buffer );
fprintf( procFile, "<count>%d</count>\n", pTrans->RefCount );
fprintf( procFile, "<kernel>%d</kernel>\n", Kernel );
fprintf( procFile, "<user>%d</user>\n", User );
fprintf( procFile, "\n<transaction>\n" );
if( level <= MAX_TRANS_LEVEL ){
PrintTransList( &pTrans->SubTransListHead, level+1 );
}
}
}
static void PrintProcessCpuTime()
{
PTHREAD_RECORD pThread;
PPROCESS_RECORD pProcess;
ULONGLONG lLifeTime;
ULONG TotalUserTime = 0;
ULONG TotalKernelTime = 0;
ULONG TotalCPUTime = 0;
PLIST_ENTRY Next, Head;
PLIST_ENTRY ThNext, ThHead;
BOOL titled;
ULONG usedThreadCount;
ULONG ThreadCount;
ULONG ProcessUTime;
ULONG ProcessKTime;
ULONG ThreadKCPU;
ULONG ThreadUCPU;
Head = &CurrentSystem.ProcessListHead;
Next = Head->Flink;
if( Head == Next ){
return;
}
fprintf( procFile, "<table title='Process/Thread CPU Time Statistics'>\n" );
Head = &CurrentSystem.ProcessListHead;
Next = Head->Flink;
while (Next != Head) {
pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
lLifeTime = CalculateProcessLifeTime(pProcess);
fprintf(procFile,
"<process name=\"%ws\">"
"<pid>0x%04X</pid>"
"<kernel>%d</kernel>"
"<user>%d</user>"
"<read>%d</read>"
"<read_size>%1.2f</read_size>"
"<write>%d</write>"
"<write_size>%1.2f</write_size>"
"<send>%d</send>"
"<send_size>%1.2f</send_size>"
"<recv>%5d</recv>"
"<recv_size>%.2f</recv_size>"
"<duation>%I64u</duation>\n",
(pProcess->ImageName) ? pProcess->ImageName : L"Idle",
pProcess->PID,
CalculateProcessKCPU(pProcess),
CalculateProcessUCPU(pProcess),
pProcess->ReadIO + pProcess->HPF,
(pProcess->ReadIO + pProcess->HPF) ?
(double)(pProcess->ReadIOSize + pProcess->HPFSize)/
(double)(pProcess->ReadIO + pProcess->HPF) : 0,
pProcess->WriteIO,
pProcess->WriteIO ? (double)pProcess->WriteIOSize/(double)pProcess->WriteIO : 0,
pProcess->SendCount,
pProcess->SendCount ?
(double)(pProcess->SendSize / 1024)/(double)pProcess->SendCount : 0,
pProcess->RecvCount,
pProcess->RecvCount ?
(double)(pProcess->RecvSize / 1024) / (double)pProcess->RecvCount : 0,
(lLifeTime / 10000000 )
);
ThHead = &pProcess->ThreadListHead;
ThNext = ThHead->Flink;
titled = FALSE;
usedThreadCount = 0;
ThreadCount = 0;
ProcessUTime = 0;
ProcessKTime = 0;
while (ThNext != ThHead) {
pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
ThreadKCPU = (pThread->KCPUEnd - pThread->KCPUStart)
* CurrentSystem.TimerResolution;
ThreadUCPU = (pThread->UCPUEnd - pThread->UCPUStart)
* CurrentSystem.TimerResolution;
if( pThread->ReadIO
|| pThread->WriteIO
|| ThreadKCPU
|| ThreadUCPU
|| pThread->SendCount
|| pThread->RecvCount
|| pThread->HPF ){
fprintf(procFile,
"<thread>"
"<tid>0x%04I64X</tid>"
"<kernel>%d</kernel>"
"<user>%d</user>"
"<read>%d</read>"
"<read_size>%1.2f</read_size>"
"<write>%d</write>"
"<write_size>%1.2f</write_size>"
"<send>%d</send>"
"<send_size>%1.2f</send_size>"
"<recv>%d</recv>"
"<recv_size>%1.2f</recv_size>"
"<duration>%I64u</duration>"
"</thread>\n",
pThread->TID,
ThreadKCPU,
ThreadUCPU,
pThread->ReadIO + pThread->HPF,
pThread->ReadIO + pThread->HPF ?
(double)(pThread->ReadIOSize + pThread->HPFSize)/
(double)(pThread->ReadIO + pThread->HPF) : 0,
pThread->WriteIO,
pThread->WriteIO ? (double)pThread->WriteIOSize/
(double)pThread->WriteIO : 0,
pThread->SendCount,
pThread->SendCount ?
(double)(pThread->SendSize / 1024)/(double)pThread->SendCount : 0,
pThread->RecvCount,
pThread->RecvCount ?
(double)(pThread->RecvSize / 1024)/(double)pThread->RecvCount : 0,
((pThread->TimeEnd - pThread->TimeStart) / 10000000)
);
}
PrintTransList( &pThread->TransListHead, 0 );
TotalUserTime += ThreadUCPU;
TotalKernelTime += ThreadKCPU;
TotalCPUTime += ThreadKCPU + ThreadUCPU;
ThNext = ThNext->Flink;
}
fprintf( procFile, "</process>\n" );
Next = Next->Flink;
}
fprintf( procFile, "</table>\n" );
}
static void PrintProcessData()
{
PTHREAD_RECORD pThread;
PPROCESS_RECORD pProcess;
PTRANS_RECORD pTrans;
PLIST_ENTRY Next, Head;
PLIST_ENTRY ThNext, ThHead;
PLIST_ENTRY TrNext, TrHead;
ULONG usedThreadCount;
ULONG ThreadCount;
ULONG TotalusedThreadCount = 0;
ULONG TotalThreadCount = 0;
ULONG ThreadUTime;
ULONG ThreadKTime;
ULONG ThreadUTimeTrans;
ULONG ThreadKTimeTrans;
ULONG ThreadUTimeNoTrans;
ULONG ThreadKTimeNoTrans;
ULONG CountThreadNoTrans;
ULONG TotalKCPUThreadNoTrans;
ULONG TotalUCPUThreadNoTrans;
double PercentThreadNoTrans;
ULONG CountThreadTrans;
ULONG TotalKCPUThreadTrans;
ULONG TotalUCPUThreadTrans;
double PercentThreadTrans;
ULONG TransUTime;
ULONG TransKTime;
ULONG Processors;
ULONG TotalKThread = 0;
ULONG TotalUThread = 0;
ULONG TotalKTrans = 0;
ULONG TotalUTrans = 0;
double PerTotal = 0.0;
double IdlePercent = 0.0;
double percent;
double percentTrans;
double lDuration;
Head = &CurrentSystem.ProcessListHead;
Next = Head->Flink;
if( Head == Next ){
return;
}
Processors = CurrentSystem.NumberOfProcessors ? CurrentSystem.NumberOfProcessors : 1;
lDuration = ((double)((LONGLONG)(CurrentSystem.EndTime - CurrentSystem.StartTime)))
/ 10000000.00;
fprintf( procFile, "<table title='Image Statistics'>\n" );
Head = &CurrentSystem.ProcessListHead;
Next = Head->Flink;
while (Next != Head) {
pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
ThHead = &pProcess->ThreadListHead;
ThNext = ThHead->Flink;
usedThreadCount = 0;
ThreadCount = 0;
ThreadUTime = 0;
ThreadKTime = 0;
ThreadUTimeTrans = 0;
ThreadKTimeTrans = 0;
ThreadUTimeNoTrans = 0;
ThreadKTimeNoTrans = 0;
TransKTime = 0;
TransUTime = 0;
percent = 0;
CountThreadNoTrans = 0;
TotalKCPUThreadNoTrans = 0;
TotalUCPUThreadNoTrans = 0;
CountThreadTrans = 0;
TotalKCPUThreadTrans = 0;
TotalUCPUThreadTrans = 0;
while (ThNext != ThHead) {
LIST_ENTRY NewTransList;
pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
if( pThread->ReadIO
|| pThread->WriteIO
|| pThread->KCPUEnd > pThread->KCPUStart
|| pThread->UCPUEnd > pThread->UCPUStart
|| pThread->SendCount
|| pThread->RecvCount
|| pThread->HPF )
{
usedThreadCount++;
TotalusedThreadCount++;
}
ThreadCount++;
TotalThreadCount++;
ThreadUTime += (pThread->UCPUEnd - pThread->UCPUStart)
* CurrentSystem.TimerResolution;
ThreadKTime += (pThread->KCPUEnd - pThread->KCPUStart)
* CurrentSystem.TimerResolution;
ThreadKTimeTrans += pThread->KCPU_Trans
* CurrentSystem.TimerResolution;
ThreadUTimeTrans += pThread->UCPU_Trans
* CurrentSystem.TimerResolution;
ThreadKTimeNoTrans += pThread->KCPU_NoTrans
* CurrentSystem.TimerResolution;
ThreadUTimeNoTrans += pThread->UCPU_NoTrans
* CurrentSystem.TimerResolution;
if (pThread->KCPU_Trans + pThread->UCPU_Trans == 0)
{
CountThreadNoTrans ++;
TotalKCPUThreadNoTrans += pThread->KCPU_NoTrans
* CurrentSystem.TimerResolution;
TotalUCPUThreadNoTrans += pThread->UCPU_NoTrans
* CurrentSystem.TimerResolution;
}
else
{
CountThreadTrans ++;
TotalKCPUThreadTrans += ( pThread->KCPU_Trans
+ pThread->KCPU_NoTrans)
* CurrentSystem.TimerResolution;
TotalUCPUThreadTrans += ( pThread->UCPU_Trans
+ pThread->UCPU_NoTrans)
* CurrentSystem.TimerResolution;
}
InitializeListHead(& NewTransList);
CollapseTree(& pThread->TransListHead, & NewTransList, TRUE);
TrHead = & NewTransList;
TrNext = TrHead->Flink;
while( TrNext != TrHead ){
pTrans = CONTAINING_RECORD( TrNext, TRANS_RECORD, Entry );
TransUTime += pTrans->UCpu;
TransKTime += pTrans->KCpu;
TrNext = TrNext->Flink;
}
DeleteTransList(& NewTransList, 0);
ThNext = ThNext->Flink;
}
TotalKThread += ThreadKTime;
TotalUThread += ThreadUTime;
TotalKTrans += TransKTime;
TotalUTrans += TransUTime;
percent = (((ThreadKTime + ThreadUTime + 0.0)/lDuration)/1000.0) * 100.0;
if (ThreadKTime + ThreadUTime == 0)
{
percentTrans = 0.0;
PercentThreadTrans = 0.0;
PercentThreadNoTrans = 0.0;
}
else
{
percentTrans = ( (ThreadKTimeTrans + ThreadUTimeTrans + 0.0)
/ (ThreadKTime + ThreadUTime + 0.0))
* 100.00;
PercentThreadTrans = ((TotalKCPUThreadTrans + TotalUCPUThreadTrans + 0.0)
/ (ThreadKTime + ThreadUTime + 0.0)) * 100.00;
PercentThreadNoTrans = ((TotalKCPUThreadNoTrans + TotalUCPUThreadNoTrans + 0.0)
/ (ThreadKTime + ThreadUTime + 0.0)) * 100.00;
}
PerTotal += percent;
fprintf(procFile,
"<image name=\"%ws\">"
"<pid>0x%08X</pid>"
"<threads>%d</threads>"
"<used_threads>%d</used_threads>"
"<process_kernel>%d</process_kernel>"
"<process_user>%d</process_user>"
"<transaction_kernel>%d</transaction_kernel>"
"<transaction_user>%d</transaction_user>"
"<cpu>%1.2f</cpu>"
"</image>\n",
(pProcess->ImageName) ? pProcess->ImageName : L"Idle",
pProcess->PID,
ThreadCount,
usedThreadCount,
ThreadKTime,
ThreadUTime,
ThreadKTimeTrans,
ThreadUTimeTrans,
(percent / Processors)
);
if(pProcess->PID == 0){
IdlePercent += (percent / Processors );
}
Next = Next->Flink;
}
fprintf( procFile, "</table>\n" );
}
void TransInclusive(
PLIST_ENTRY TrHead,
ULONG level
)
{
ULONG Kernel, User;
PLIST_ENTRY TrNext = TrHead->Flink;
PMOF_INFO pMofInfo;
PTRANS_RECORD pTrans;
WCHAR buffer[MAXSTR];
WCHAR str[MAXSTR];
while( TrNext != TrHead ){
ULONG count = 0;
pTrans = CONTAINING_RECORD( TrNext, TRANS_RECORD, Entry );
TrNext = TrNext->Flink;
pMofInfo = GetMofInfoHead( pTrans->pGuid);
if (pMofInfo == NULL) {
return;
}
Kernel = pTrans->KCpu;
User = pTrans->UCpu;
TotalTransChildren( &pTrans->SubTransListHead, &Kernel, &User, 0 );
StringCchCopyW ( buffer,
MAXSTR,
( pMofInfo->strDescription ?
pMofInfo->strDescription :
CpdiGuidToString( str, MAXSTR, &pMofInfo->Guid ) ));
fprintf(procFile,
"<transaction level='%d' name=\"%ws\">"
"<count>%d</count>"
"<kernel>%d</kernel>"
"<user>%d</user>",
level,
buffer,
pTrans->RefCount,
Kernel,
User
);
TransInclusive( &pTrans->SubTransListHead, level+1 );
fprintf(procFile, "</transaction>\n" );
}
}
static void PrintProcessSubDataInclusive()
{
PPROCESS_RECORD pProcess;
PTHREAD_RECORD pThread;
PLIST_ENTRY Next, Head;
PLIST_ENTRY TrNext;
PLIST_ENTRY ThNext, ThHead;
LIST_ENTRY NewHead;
BOOL bTable = FALSE;
Head = &CurrentSystem.ProcessListHead;
Next = Head->Flink;
while (Next != Head && !bTable ) {
pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
Next = Next->Flink;
if( pProcess->PID == 0 ){
continue;
}
// Total up all the threads into one list
InitializeListHead( &NewHead );
ThHead = &pProcess->ThreadListHead;
ThNext = ThHead->Flink;
while( ThNext != ThHead ){
pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
ThNext = ThNext->Flink;
CollapseTree(&pThread->TransListHead, &NewHead, FALSE );
}
TrNext = NewHead.Flink;
if( TrNext != &NewHead ){
bTable = TRUE;
}
DeleteTransList( &NewHead, 0 );
}
if( !bTable ){
return;
}
// Walk through the Process List and Print the report.
fprintf(procFile, "<table title='Inclusive Transactions Per Process'>\n" );
Head = &CurrentSystem.ProcessListHead;
Next = Head->Flink;
while (Next != Head) {
pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
Next = Next->Flink;
if( pProcess->PID == 0 ){
continue;
}
// Total up all the threads into one list
InitializeListHead( &NewHead );
ThHead = &pProcess->ThreadListHead;
ThNext = ThHead->Flink;
while( ThNext != ThHead ){
pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
ThNext = ThNext->Flink;
CollapseTree(&pThread->TransListHead, &NewHead, FALSE );
}
TrNext = NewHead.Flink;
if( TrNext != &NewHead ){
fprintf(procFile,
"<process name=\"%ws\">"
"<pid>0x%04X</pid>\n",
(pProcess->ImageName) ? pProcess->ImageName : L"Idle",
pProcess->PID
);
TransInclusive( &NewHead, 0 );
fprintf( procFile, "</process>\n" );
}
DeleteTransList( &NewHead, 0 );
}
fprintf(procFile, "</table>\n" );
}
static void PrintProcessSubDataExclusive()
{
PPROCESS_RECORD pProcess;
PTRANS_RECORD pTrans;
PTHREAD_RECORD pThread;
PLIST_ENTRY ThNext, ThHead;
PMOF_INFO pMofInfo;
PLIST_ENTRY Next, Head;
PLIST_ENTRY TrNext;
LIST_ENTRY NewHead;
double percent, percentCPU, totalPerCPU;
double processPart;
double transPart;
double totalPercent;
double trans, KCPU, UCPU;
WCHAR str[MAXSTR];
double duration = ((double)((LONGLONG)(CurrentSystem.EndTime - CurrentSystem.StartTime))) / 10000000.00;
BOOL bTable = FALSE;
Head = &CurrentSystem.ProcessListHead;
Next = Head->Flink;
while (Next != Head && !bTable ) {
pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
Next = Next->Flink;
if( pProcess->PID == 0 ){
continue;
}
InitializeListHead( &NewHead );
ThHead = &pProcess->ThreadListHead;
ThNext = ThHead->Flink;
while( ThNext != ThHead ){
pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
ThNext = ThNext->Flink;
CollapseTree(&pThread->TransListHead, &NewHead, TRUE );
}
TrNext = NewHead.Flink;
if( TrNext != &NewHead ){
bTable = TRUE;
}
DeleteTransList( &NewHead, 0 );
}
if( !bTable ){
return;
}
// Walk through the Process List and Print the report.
fprintf(procFile, "<table title='Exclusive Transactions Per Process'>\n" );
Head = &CurrentSystem.ProcessListHead;
Next = Head->Flink;
while (Next != Head) {
BOOL titled = FALSE;
pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
Next = Next->Flink;
if( pProcess->PID == 0 ){
continue;
}
InitializeListHead( &NewHead );
ThHead = &pProcess->ThreadListHead;
ThNext = ThHead->Flink;
while( ThNext != ThHead ){
pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
ThNext = ThNext->Flink;
CollapseTree(&pThread->TransListHead, &NewHead, TRUE );
}
TrNext = NewHead.Flink;
totalPercent = 0.0;
totalPerCPU = 0.0;
while( TrNext != &NewHead ){
if(!titled){
fprintf(procFile,
"<process name=\"%ws\">"
"<pid>0x%04X</pid>\n",
(pProcess->ImageName) ? pProcess->ImageName : L"Idle",
pProcess->PID
);
titled = TRUE;
}
pTrans = CONTAINING_RECORD( TrNext, TRANS_RECORD, Entry );
TrNext = TrNext->Flink;
pMofInfo = GetMofInfoHead( pTrans->pGuid);
if (pMofInfo == NULL) {
return;
}
transPart = pTrans->UCpu + pTrans->KCpu;
processPart = CalculateProcessKCPU(pProcess)
+ CalculateProcessUCPU(pProcess);
percentCPU = ((((double)pTrans->KCpu + (double)pTrans->UCpu ) / 10.0 ) / duration) / ((double) CurrentSystem.NumberOfProcessors);
totalPerCPU += percentCPU;
if(processPart)
percent = (transPart/processPart) * 100.0;
else
percent = 0;
totalPercent += percent;
if (!(ReportFlags & TRACE_TOTALS_REPORT) ){
if (pTrans->RefCount == 0 && pTrans->RefCount1 == 0)
KCPU = UCPU = 0.0;
else if (pTrans->RefCount == 0) {
KCPU = (double) pTrans->KCpu;
UCPU = (double) pTrans->UCpu;
}
else {
KCPU = (double) pTrans->KCpu / (double) pTrans->RefCount;
UCPU = (double) pTrans->UCpu / (double) pTrans->RefCount;
}
}
else{
KCPU = (double)pTrans->KCpu;
UCPU = (double)pTrans->UCpu;
}
trans = (double)pTrans->RefCount / duration;
fprintf(procFile,
"<transaction name=\"%ws\">"
"<count>%d</count>"
"<rate>%1.2f</rate>"
"<kernel>%1.0f</kernel>"
"<user>%1.0f</user>"
"<process_cpu>%1.2f</process_cpu>"
"<cpu>%1.2f</cpu>"
"</transaction>\n",
(pMofInfo->strDescription != NULL) ? pMofInfo->strDescription : CpdiGuidToString( str, MAXSTR, &pMofInfo->Guid ),
pTrans->RefCount,
trans,
KCPU,
UCPU,
percent,
percentCPU
);
}
if( titled ){
fprintf( procFile, "</process>\n" );
}
DeleteTransList( &NewHead, 0 );
}
fprintf(procFile, "</table>\n" );
}
static void PrintPerThreadPerDiskTable( )
{
PPROCESS_RECORD pProcess;
PTDISK_RECORD pDisk;
PLIST_ENTRY Next, Head;
PLIST_ENTRY GNext, GHead;
PLIST_ENTRY DiNext, DiHead;
ULONG rio, wio, DiskNumber;
BOOL bTable = FALSE;
ULONGLONG Duration = (ULONGLONG)((CurrentSystem.EndTime - CurrentSystem.StartTime) / 10000000);
if (Duration == 0) {
return;
}
// Walk through the Process List and Print the report.
GHead = &CurrentSystem.GlobalDiskListHead;
GNext = GHead->Flink;
while (GNext != GHead && !bTable) {
pDisk = CONTAINING_RECORD( GNext, TDISK_RECORD, Entry);
DiskNumber = pDisk->DiskNumber;
Head = &CurrentSystem.ProcessListHead;
Next = Head->Flink;
while (Next != Head) {
pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
DiHead = &pProcess->DiskListHead;
DiNext = DiHead->Flink;
while (DiNext != DiHead && !bTable) {
pDisk = CONTAINING_RECORD( DiNext, TDISK_RECORD, Entry );
if (DiskNumber != pDisk->DiskNumber) {
DiNext = DiNext->Flink;
continue;
}else{
bTable = TRUE;
break;
}
}
Next = Next->Flink;
}
GNext = GNext->Flink;
}
if( !bTable ){
return;
}
GHead = &CurrentSystem.GlobalDiskListHead;
GNext = GHead->Flink;
while (GNext != GHead) {
pDisk = CONTAINING_RECORD( GNext, TDISK_RECORD, Entry);
DiskNumber = pDisk->DiskNumber;
fprintf( procFile, "<table title='Disk' number='%d'>\n", DiskNumber );
Head = &CurrentSystem.ProcessListHead;
Next = Head->Flink;
while (Next != Head) {
pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
DiHead = &pProcess->DiskListHead;
DiNext = DiHead->Flink;
while (DiNext != DiHead) {
pDisk = CONTAINING_RECORD( DiNext, TDISK_RECORD, Entry );
if (DiskNumber != pDisk->DiskNumber) {
DiNext = DiNext->Flink;
continue;
}
rio = pDisk->ReadCount + pDisk->HPF;
wio = pDisk->WriteCount;
fprintf(procFile,
"<image name='%ws'>"
"<pid>0x%08X</pid>"
"<authority>%ws</authority>"
"<read_rate>%1.3f</read_rate>"
"<read_size>%d</read_size>"
"<write_rate>%1.3f</write_rate>"
"<write_size>%d</write_size>"
"</image>\n",
(pProcess->ImageName) ? pProcess->ImageName : L"-",
pProcess->PID,
(pProcess->UserName) ? pProcess->UserName : L"-",
(double)rio / ((double)Duration),
(rio == 0) ? 0 : (pDisk->ReadSize + pDisk->HPFSize) / rio,
(double)wio / ((double)Duration),
(wio == 0) ? 0 : pDisk->WriteSize / wio
);
DiNext = DiNext->Flink;
}
Next = Next->Flink;
}
fprintf( procFile, "</table>\n" );
GNext = GNext->Flink;
}
}
static void WriteTransactionStatistics()
{
PLIST_ENTRY Head, Next;
PLIST_ENTRY Dhead, DNext;
ULONG trans;
double KCPU, UCPU, PerCpu;
double RIO, WIO, Send, Recv;
PMOF_INFO pMofInfo;
PMOF_DATA pMofData;
double AvgRT;
double TransRate;
WCHAR str[MAXSTR];
double duration = ((double)((LONGLONG)(CurrentSystem.EndTime - CurrentSystem.StartTime)))
/ 10000000.00;
BOOL bTable = FALSE;
Head = &CurrentSystem.EventListHead;
Next = Head->Flink;
while (Head != Next && !bTable ) {
pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
Dhead = &pMofInfo->DataListHead;
DNext = Dhead->Flink;
while(DNext!=Dhead){
pMofData = CONTAINING_RECORD(DNext, MOF_DATA, Entry);
trans = pMofData->CompleteCount;
if (trans > 0) {
bTable = TRUE;
break;
}
DNext = DNext->Flink;
}
Next = Next->Flink;
}
if( !bTable ){
return;
}
fprintf( procFile, "<table title='Transaction Statistics'>\n" );
Head = &CurrentSystem.EventListHead;
Next = Head->Flink;
while (Head != Next) {
pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
Dhead = &pMofInfo->DataListHead;
DNext = Dhead->Flink;
while(DNext!=Dhead){
pMofData = CONTAINING_RECORD(DNext, MOF_DATA, Entry);
trans = pMofData->CompleteCount;
if (trans > 0) {
UCPU = pMofData->UserCPU;
KCPU = pMofData->KernelCPU;
PerCpu = (((UCPU + KCPU)/1000.0)/duration) * 100.0;
UCPU /= trans;
KCPU /= trans;
if(CurrentSystem.NumberOfProcessors)
PerCpu/=CurrentSystem.NumberOfProcessors;
if( ReportFlags & TRACE_TOTALS_REPORT ){
RIO = pMofData->ReadCount;
WIO = pMofData->WriteCount;
Send = pMofData->SendCount;
Recv = pMofData->RecvCount;
}else{
RIO = pMofData->ReadCount / trans;
WIO = pMofData->WriteCount / trans;
Send = pMofData->SendCount / trans;
Recv = pMofData->RecvCount / trans;
}
AvgRT = (double)pMofData->TotalResponseTime;
AvgRT /= trans;
TransRate = ( (float)trans / duration );
// TODO: NOT /trans if TRACE_TOTALS_REPORT
fprintf(procFile,
"<transaction name='%ws'>"
"<count>%d</count>"
"<response_time>%1.0f</response_time>"
"<rate>%1.2f</rate>"
"<cpu>%1.2f</cpu>"
"<disk_read_per_trans>%1.2f</disk_read_per_trans>"
"<disk_write_per_trans>%1.2f</disk_write_per_trans>"
"<tcp_send_per_trans>%1.2f</tcp_send_per_trans>"
"<tcp_recv_per_trans>%1.2f</tcp_recv_per_trans>"
"</transaction>\n",
(pMofInfo->strDescription) ? pMofInfo->strDescription : CpdiGuidToString( str, MAXSTR, &pMofInfo->Guid ),
pMofData->CompleteCount,
AvgRT,
TransRate,
PerCpu,
RIO,
WIO,
Send,
Recv
);
}
DNext = DNext->Flink;
}
Next = Next->Flink;
}
fprintf(procFile, "</table>" );
}
static void WriteTransactionCPUTime()
{
PLIST_ENTRY Head, Next;
PLIST_ENTRY Dhead, DNext;
double KCPU, UCPU;
PMOF_INFO pMofInfo;
PMOF_DATA pMofData;
double trans;
double PerCpu;
WCHAR str[MAXSTR];
double duration = ((double)((LONGLONG)(CurrentSystem.EndTime - CurrentSystem.StartTime))) / 10000000.00;
BOOL bTable = FALSE;
Head = &CurrentSystem.EventListHead;
Next = Head->Flink;
while (Head != Next && !bTable ) {
pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
Dhead = &pMofInfo->DataListHead;
DNext = Dhead->Flink;
while(DNext!=Dhead){
pMofData = CONTAINING_RECORD(DNext, MOF_DATA, Entry);
trans = (double)pMofData->CompleteCount;
if (trans > 0) {
bTable = TRUE;
break;
}
DNext = DNext->Flink;
}
Next = Next->Flink;
}
if( !bTable ){
return;
}
fprintf( procFile, "<table title='Transaction CPU Utilization'>\n" );
Head = &CurrentSystem.EventListHead;
Next = Head->Flink;
while (Head != Next) {
pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
Dhead = &pMofInfo->DataListHead;
DNext = Dhead->Flink;
while(DNext!=Dhead){
pMofData = CONTAINING_RECORD(DNext, MOF_DATA, Entry);
trans = (double)pMofData->CompleteCount;
if (trans > 0) {
UCPU = pMofData->UserCPU;
UCPU /= trans;
KCPU = pMofData->KernelCPU;
KCPU /= trans;
PerCpu = (((pMofData->UserCPU + pMofData->KernelCPU + 0.0)/1000.0)/duration) * 100.0;
if( !(ReportFlags & TRACE_TOTALS_REPORT) ){
trans /= duration;
}
if(CurrentSystem.NumberOfProcessors){
PerCpu/=CurrentSystem.NumberOfProcessors;
}
// NOTE: RATE should be COUNT if TRACE_TOTALS_REPORT
fprintf(procFile,
"<transaction name='%ws'>"
"<rate>%1.2f</rate>"
"<min_kernel>%d</min_kernel>"
"<min_user>%d</min_user>"
"<max_kernel>%d</max_kernel>"
"<max_user>%d</max_user>"
"<per_trans_kernel>%1.0f</per_trans_kernel>"
"<per_trans_user>%1.0f</per_trans_user>"
"<total_kernel>%d</total_kernel>"
"<total_user>%d</total_user>"
"<cpu>%1.2f</cpu>"
"</transaction>\n",
(pMofInfo->strDescription) ? pMofInfo->strDescription : CpdiGuidToString( str, MAXSTR, &pMofInfo->Guid ),
trans,
pMofData->MinKCpu,
pMofData->MinUCpu,
pMofData->MaxKCpu,
pMofData->MaxUCpu,
KCPU,
UCPU,
pMofData->KernelCPU,
pMofData->UserCPU,
PerCpu
);
}
DNext = DNext->Flink;
}
Next = Next->Flink;
}
fprintf(procFile, "</table>\n" );
}
PWCHAR CpdiGuidToString(
PWCHAR s,
ULONG len,
LPGUID piid
)
{
StringCchPrintf(s, len,
L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
piid->Data1, piid->Data2,
piid->Data3,
piid->Data4[0], piid->Data4[1],
piid->Data4[2], piid->Data4[3],
piid->Data4[4], piid->Data4[5],
piid->Data4[6], piid->Data4[7]);
return(s);
}
#define MAX_LOGS 1024 * 1024
typedef struct _PTR_RECORD
{
PVOID ptrRecord;
ULONG keySort;
} PTR_RECORD, * PPTR_RECORD;
static PPTR_RECORD PtrBuffer = NULL;
static ULONG PtrMax = MAX_LOGS;
static ULONG PtrTotal = 0;
static ULONG PtrIndex;
int __cdecl
CompareFileRecord(const void * p1, const void * p2)
{
PPTR_RECORD pp1 = (PPTR_RECORD) p1;
PPTR_RECORD pp2 = (PPTR_RECORD) p2;
PFILE_RECORD pFile1 = (PFILE_RECORD) pp1->ptrRecord;
PFILE_RECORD pFile2 = (PFILE_RECORD) pp2->ptrRecord;
LONG diffFault = pp2->keySort - pp1->keySort;
if (diffFault == 0)
{
diffFault = pFile1->DiskNumber - pFile2->DiskNumber;
if (diffFault == 0)
{
diffFault = wcscmp(pFile1->FileName, pFile2->FileName);
}
}
return diffFault;
}
void
ReportHotFileInfo()
{
PLIST_ENTRY pHead = & CurrentSystem.HotFileListHead;
PLIST_ENTRY pNext = pHead->Flink;
PFILE_RECORD pFile;
BOOLEAN fDone = FALSE;
ULONGLONG Duration = ((CurrentSystem.EndTime - CurrentSystem.StartTime) / 10000000);
PMOF_INFO pMofInfo;
pMofInfo = GetMofInfoHead ((LPCGUID)&ProcessGuid);
if ( pMofInfo == NULL ) {
return;
}
pMofInfo = GetMofInfoHead ((LPCGUID)&ThreadGuid);
if ( pMofInfo == NULL ) {
return;
}
ASSERT(!PtrBuffer);
PtrBuffer = (PPTR_RECORD) VirtualAlloc(
NULL,
sizeof(PTR_RECORD) * PtrMax,
MEM_COMMIT,
PAGE_READWRITE);
if( NULL == PtrBuffer ){
goto Cleanup;
}
while (!fDone)
{
for (PtrTotal = 0, fDone = TRUE;
pNext != pHead;
pNext = pNext->Flink)
{
if (PtrTotal == PtrMax)
{
fDone = FALSE;
break;
}
pFile = CONTAINING_RECORD(pNext, FILE_RECORD, Entry);
if (pFile->ReadCount + pFile->WriteCount > 0)
{
PtrBuffer[PtrTotal].ptrRecord = (PVOID) pFile;
PtrBuffer[PtrTotal].keySort =
pFile->ReadCount + pFile->WriteCount;
PtrTotal ++;
}
}
if (!fDone)
{
VirtualFree(PtrBuffer, 0, MEM_RELEASE);
PtrMax += MAX_LOGS;
PtrBuffer = (PPTR_RECORD) VirtualAlloc(
NULL,
sizeof(PTR_RECORD) * PtrMax,
MEM_COMMIT,
PAGE_READWRITE);
if (PtrBuffer == NULL)
{
goto Cleanup;
}
}
}
if (PtrTotal > 1) {
qsort((void *) PtrBuffer,
(size_t) PtrTotal,
(size_t) sizeof(PTR_RECORD),
CompareFileRecord);
}
else {
return;
}
if (PtrTotal > DISPLAY_SIZE) {
PtrTotal = DISPLAY_SIZE;
}
// output HotFile report title
//
fprintf( procFile, "<table title='Files Causing Most Disk IOs' top='%d'>\n", DISPLAY_SIZE );
for (PtrIndex = 0; PtrIndex < PtrTotal; PtrIndex ++)
{
PLIST_ENTRY pProtoHead;
PLIST_ENTRY pProtoNext;
PPROTO_PROCESS_RECORD pProto;
WCHAR ReducedFileName[FILE_NAME_COLUMN_SIZE + 1];
LPWSTR szFile;
PWCHAR szLongFile;
LPWSTR szDrive = L"";
pFile = (PFILE_RECORD) PtrBuffer[PtrIndex].ptrRecord;
if (NULL != pFile->Drive) {
szDrive = pFile->Drive;
}
if (_wcsnicmp(pFile->FileName, L"\\Device\\", 8) == 0) {
szLongFile = (PWCHAR)(pFile->FileName) + 8;
while (*szLongFile != L'\\' && *szLongFile != L'\0') {
szLongFile++;
}
}
else {
szLongFile = (PWCHAR)(pFile->FileName);
}
if (wcslen(szLongFile) > FILE_NAME_COLUMN_SIZE) {
ReduceStringW(ReducedFileName, FILE_NAME_COLUMN_SIZE + 1, szLongFile);
szFile = ReducedFileName;
}else{
szFile = szLongFile;
}
fprintf(procFile,
"<file name='%ws'>"
"<disk>%d</disk>"
"<drive>%ws</drive>"
"<read_rate>%1.3f</read_rate>"
"<read_size>%d</read_size>"
"<write_rate>%1.3f</write_rate>"
"<write_size>%d</write_size>\n",
szFile,
pFile->DiskNumber,
szDrive,
Duration ? ((double)pFile->ReadCount / (double)Duration) : 0.0,
(pFile->ReadCount) ? (pFile->ReadSize / pFile->ReadCount) : 0,
Duration ? ((double)pFile->WriteCount / (double)Duration) : 0.0,
(pFile->WriteCount) ? (pFile->WriteSize / pFile->WriteCount) : 0);
pProtoHead = & pFile->ProtoProcessListHead;
pProtoNext = pProtoHead->Flink;
while (pProtoNext != pProtoHead)
{
pProto = CONTAINING_RECORD(pProtoNext, PROTO_PROCESS_RECORD, Entry);
pProtoNext = pProtoNext->Flink;
if (pProto->ReadCount + pProto->WriteCount > 0)
{
fprintf(procFile,
"<image name='%ws'>"
"<pid>0x%08X</pid>"
"<read_rate>%1.3f</read_rate>"
"<read_size>%d</read_size>"
"<write_rate>%1.3f</write_rate>"
"<write_size>%d</write_size>"
"</image>\n",
pProto->ProcessRecord->ImageName,
pProto->ProcessRecord->PID,
Duration ? ((double)pProto->ReadCount / (double)Duration) : 0.0,
(pProto->ReadCount) ? (pProto->ReadSize / pProto->ReadCount) : 0,
Duration ? ((double)pProto->WriteCount / (double)Duration) : 0.0,
(pProto->WriteCount) ? (pProto->WriteSize / pProto->WriteCount) : 0);
}
}
fprintf( procFile, "</file>\n" );
}
fprintf( procFile, "</table>\n" );
Cleanup:
if (PtrBuffer)
{
VirtualFree(PtrBuffer, 0, MEM_RELEASE);
}
}
#define CHECKTOK( x ) if( NULL == x ) { continue; }
static void ReportPrintJobInfo2(void)
{
PRINT_JOB_RECORD Job, *pJob;
char* s;
char line[MAXSTR];
ULONG TotalCount = 0;
ULONGLONG TotalRT = 0;
ULONG TotalCPUTime = 0;
pJob = &Job;
if( NULL == CurrentSystem.TempPrintFile ){
return;
}
rewind( CurrentSystem.TempPrintFile );
while ( fgets(line, MAXSTR, CurrentSystem.TempPrintFile) != NULL ) {
s = strtok( line, (","));
CHECKTOK( s );
pJob->JobId = atol(s);
if (pJob == NULL){
return;
}
}
fprintf(procFile, "<table title='Spooler Transaction Instance (Job) Data'>\n");
RtlZeroMemory(pJob, sizeof(PRINT_JOB_RECORD));
RtlZeroMemory(line, MAXSTR * sizeof(char));
rewind( CurrentSystem.TempPrintFile );
while ( fgets(line, MAXSTR, CurrentSystem.TempPrintFile) != NULL ) {
s = strtok( line, (","));
CHECKTOK( s );
pJob->JobId = atol(s);
if (pJob == NULL){
continue;
}
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->KCPUTime = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->UCPUTime = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->ReadIO = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->StartTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->EndTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->ResponseTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->PrintJobTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->WriteIO = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->DataType = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->JobSize = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->Pages = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->PagesPerSide = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->FilesOpened = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->GdiJobSize = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->Color = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->XRes = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->YRes = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->Quality = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->Copies = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->TTOption = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->NumberOfThreads = atol(s);
fprintf(procFile,
"<job id='%d'>"
"<type>%d</type>"
"<size>%d</size>"
"<pages>%d</pages>"
"<PPS>%d</PPS>"
"<files>%hd</files>"
"<gdisize>%d</gdisize>"
"<color>%hd</color>"
"<xres>%hd</xres>"
"<yres>%hd</yres>"
"<qlty>%hd</qlty>"
"<copies>%hd</copies>"
"<ttopt>%hd</ttopt>"
"<threads>%d</threads>"
"</job>\n",
pJob->JobId,
pJob->DataType,
((pJob->JobSize) / 1024),
pJob->Pages,
pJob->PagesPerSide,
pJob->FilesOpened,
pJob->GdiJobSize,
pJob->Color,
pJob->XRes,
pJob->YRes,
pJob->Quality,
pJob->Copies,
pJob->TTOption,
pJob->NumberOfThreads
);
}
fprintf(procFile, "</table>\n" );
}
static void ReportPrintJobInfo(void)
{
PRINT_JOB_RECORD Job, *pJob;
char* s;
char line[MAXSTR];
FILETIME StTm, StlTm;
LARGE_INTEGER LargeTmp;
SYSTEMTIME stStart, stEnd, stDequeue;
ULONG TotalCount = 0;
ULONGLONG TotalRT = 0;
ULONG TotalCPUTime = 0;
if( NULL == CurrentSystem.TempPrintFile ){
return;
}
pJob = &Job;
rewind( CurrentSystem.TempPrintFile );
while ( fgets(line, MAXSTR, CurrentSystem.TempPrintFile) != NULL ) {
s = strtok( line, (","));
CHECKTOK( s );
pJob->JobId = atol(s);
if (pJob == NULL){
return;
}
}
fprintf(procFile, "<table title='Transaction Instance (Job) Statistics'>\n" );
RtlZeroMemory(pJob, sizeof(PRINT_JOB_RECORD));
RtlZeroMemory(line, MAXSTR * sizeof(char));
rewind( CurrentSystem.TempPrintFile );
while ( fgets(line, MAXSTR, CurrentSystem.TempPrintFile) != NULL ) {
s = strtok( line, (","));
CHECKTOK( s );
pJob->JobId = atol(s);
if (pJob == NULL){
continue;
}
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->KCPUTime = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->UCPUTime = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->ReadIO = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->StartTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->EndTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->ResponseTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->PrintJobTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->WriteIO = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->DataType = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->JobSize = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->Pages = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->PagesPerSide = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->FilesOpened = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->GdiJobSize = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->Color = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->XRes = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->YRes = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->Quality = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->Copies = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->TTOption = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pJob->NumberOfThreads = atol(s);
LargeTmp.QuadPart = pJob->StartTime;
StTm.dwHighDateTime = LargeTmp.HighPart;
StTm.dwLowDateTime = LargeTmp.LowPart;
FileTimeToLocalFileTime(&StTm, &StlTm);
FileTimeToSystemTime (
&StlTm,
&stStart
);
LargeTmp.QuadPart = pJob->EndTime;
StTm.dwHighDateTime = LargeTmp.HighPart;
StTm.dwLowDateTime = LargeTmp.LowPart;
FileTimeToLocalFileTime(&StTm, &StlTm);
FileTimeToSystemTime (
&StlTm,
&stEnd
);
LargeTmp.QuadPart = pJob->PrintJobTime;
StTm.dwHighDateTime = LargeTmp.HighPart;
StTm.dwLowDateTime = LargeTmp.LowPart;
FileTimeToLocalFileTime(&StTm, &StlTm);
FileTimeToSystemTime (
&StlTm,
&stDequeue
);
fprintf(procFile,
"<job id='%d'>"
"<start>%2d:%02d:%02d.%03d</start>"
"<dequeue>%2d:%02d:%02d.%03d</dequeue>"
"<end>%2d:%02d:%02d.%03d</end>"
"<response_time>%I64u</response_time>"
"<cpu>%d</cpu>"
"</job>\n",
pJob->JobId,
stStart.wHour, stStart.wMinute, stStart.wSecond, stStart.wMilliseconds,
stDequeue.wHour, stDequeue.wMinute, stDequeue.wSecond, stDequeue.wMilliseconds,
stEnd.wHour, stEnd.wMinute, stEnd.wSecond, stEnd.wMilliseconds,
pJob->ResponseTime,
pJob->KCPUTime + pJob->UCPUTime
);
TotalCount++;
TotalRT += pJob->ResponseTime;
TotalCPUTime += (pJob->KCPUTime + pJob->UCPUTime);
}
if (TotalCount > 0) {
TotalRT /= TotalCount;
TotalCPUTime /= TotalCount;
}
fprintf(procFile,
"<summary>"
"<count>%d</count>"
"<total_response_time>%I64u</total_response_time>"
"<total_cpu>%d</total_cpu>"
"</summary>\n",
TotalCount, TotalRT, TotalCPUTime );
fprintf(procFile, "</table>\n" );
ReportPrintJobInfo2();
}
PUCHAR CopyUrlStr(PUCHAR UrlStr) {
PUCHAR CopiedStr;
if (UrlStr == NULL) {
return NULL;
}
CopiedStr = (PUCHAR)malloc(strlen(UrlStr) + 1);
if (CopiedStr != NULL) {
RtlCopyMemory(CopiedStr, UrlStr, strlen(UrlStr) + 1);
return CopiedStr;
}
else {
return NULL;
}
}
void ProcessIisRequest(HTTP_REQUEST_RECORD *pReq)
{
// Global variable IIS must not be NULL here.
PURL_RECORD pUrl;
PCLIENT_RECORD pClient;
PSITE_RECORD pSite;
pUrl = FindOrAddUrlRecord(pReq->URL);
if (pUrl != NULL) {
pUrl->SiteId = pReq->SiteId;
pUrl->Requests++;
pUrl->TotalResponseTime += pReq->ULResponseTime;
pUrl->KCPUTime += pReq->KCPUTime;
pUrl->UCPUTime += pReq->UCPUTime;
pUrl->ReadIO += pReq->ReadIO;
pUrl->WriteIO += pReq->WriteIO;
pUrl->BytesSent += pReq->BytesSent;
// Cached responses don't have this field filled
// Thus need to check for Hits field as well
pUrl->UrlType = pReq->W3ProcessType;
}
pClient = FindOrAddClientRecord(pReq->IpAddrType, pReq->IpAddrV4, pReq->IpAddrV6);
if (pClient != NULL) {
pClient->Requests++;
pClient->TotalResponseTime += pReq->ULResponseTime;
pClient->BytesSent += pReq->BytesSent;
}
pSite = FindOrAddSiteRecord(pReq->SiteId);
if (pSite != NULL) {
pSite->Requests++;
pSite->TotalResponseTime += pReq->ULResponseTime;
pSite->KCPUTime += pReq->KCPUTime;
pSite->UCPUTime += pReq->UCPUTime;
pSite->ReadIO += pReq->ReadIO;
pSite->WriteIO += pReq->WriteIO;
pSite->BytesSent += pReq->BytesSent;
}
if (pReq->ULEndType == EVENT_TRACE_TYPE_UL_CACHEDEND) {
IIS->CachedResponses++;
IIS->TotalCachedResponseTime += pReq->ULResponseTime;
IIS->CachedCPUTime += pReq->KCPUTime + pReq->UCPUTime;
if (pUrl != NULL) {
pUrl->Hits++;
}
if (pClient != NULL) {
pClient->Hits++;
}
if (pSite != NULL) {
pSite->Hits++;
}
}
else {
ULONGLONG localCGIEndTime = pReq->CGIEndTime;
ULONGLONG localISAPIEndTime = pReq->ISAPIEndTime;
ULONGLONG localASPEndTime = pReq->ASPEndTime;
ULONGLONG W3ResponseTime;
#ifdef DBG
// we'll check the validity of HTTP Requests Here.
ULONGLONG ULSum = 0, W3Res = 0;
if (pReq->ULDeliverTime == 0 || pReq->ULReceiveTime == 0) {
TrctrDbgPrint(("TRACERPT Error Req: %I64u UL DeliverTime nad/or ReceiveTime not available, should throw this away.\n", pReq->RequestId));
}
else {
ULSum = (pReq->ULDeliverTime - pReq->ULStartTime) + (pReq->ULEndTime - pReq->ULReceiveTime);
}
if (pReq->W3StartTime == 0) {
TrctrDbgPrint(("TRACERPT Error Req: %I64u W3 StartTime not available, should throw this away.\n", pReq->RequestId));
}
if (pReq->W3EndTime == 0) {
TrctrDbgPrint(("TRACERPT Warning Req: %I64u W3 EndTime not available.\n", pReq->RequestId));
}
if (pReq->W3StartTime != 0 && pReq->W3EndTime != 0 && pReq->W3EndTime < pReq->W3StartTime) {
TrctrDbgPrint(("TRACERPT Warning Req: %I64u W3 EndTime smaller than pReq->W3StartTime.\n", pReq->RequestId));
}
if (ULSum != 0 && pReq->W3StartTime != 0 && pReq->W3EndTime != 0) {
double ULRatio = 0.0;
W3Res = pReq->W3EndTime - pReq->W3StartTime;
ULRatio = (double)ULSum / (double)(pReq->ULResponseTime - W3Res);
if (ULRatio < 0.5 || ULRatio > 2.0) {
TrctrDbgPrint(("TRACERPT Warning Req: %I64u UL Ratio is unreal.\n", pReq->RequestId));
}
}
if (pReq->W3ProcessType == EVENT_TRACE_TYPE_W3CORE_CGIREQ) {
if (pReq->CGIStartTime == 0) {
TrctrDbgPrint(("TRACERPT Error Req: %I64u CGI StartTime not available, should throw this away.\n", pReq->RequestId));
}
if (pReq->CGIEndTime == 0) {
TrctrDbgPrint(("TRACERPT Warning Req: %I64u CGI EndTime not available.\n", pReq->RequestId));
if (pReq->W3EndTime != 0 && (pReq->CGIStartTime > pReq->W3EndTime)) {
TrctrDbgPrint(("TRACERPT Warning Req: %I64u CGI StartTime > pReq->W3EndTime.\n", pReq->RequestId));
}
else if (pReq->W3EndTime == 0 && (pReq->CGIStartTime > pReq->ULReceiveTime)) {
TrctrDbgPrint(("TRACERPT Warning Req: %I64u CGI StartTime > pReq->ULReceiveTime.\n", pReq->RequestId));
}
}
}
else if (pReq->W3ProcessType == EVENT_TRACE_TYPE_W3CORE_ISAPIREQ) {
if (pReq->ISAPIStartTime == 0) {
TrctrDbgPrint(("TRACERPT Error Req: %I64u ISAPI StartTime not available, should throw this away.\n", pReq->RequestId));
}
if (pReq->ISAPIEndTime == 0) {
TrctrDbgPrint(("TRACERPT Warning Req: %I64u ISAPI EndTime not available.\n", pReq->RequestId));
if (pReq->W3EndTime != 0 && (pReq->ISAPIStartTime > pReq->W3EndTime)) {
TrctrDbgPrint(("TRACERPT Warning Req: %I64u ISAPI StartTime > pReq->W3EndTime.\n", pReq->RequestId));
}
else if (pReq->W3EndTime == 0 && (pReq->ISAPIStartTime > pReq->ULReceiveTime)) {
TrctrDbgPrint(("TRACERPT Warning Req: %I64u ISAPI StartTime > pReq->ULReceiveTime.\n", pReq->RequestId));
}
}
if (pReq->ASPStartTime == 0) {
TrctrDbgPrint(("TRACERPT Warning Req: %I64u ASP StartTime not available.\n", pReq->RequestId));
}
if (pReq->ASPEndTime == 0) {
TrctrDbgPrint(("TRACERPT Warning Req: %I64u ASP EndTime not available.\n", pReq->RequestId));
if (pReq->ISAPIEndTime != 0 && (pReq->ASPStartTime > pReq->ISAPIEndTime)) {
TrctrDbgPrint(("TRACERPT Warning Req: %I64u ASP StartTime > pReq->ISAPIEndTime.\n", pReq->RequestId));
}
else if (pReq->W3EndTime != 0 && (pReq->ASPStartTime > pReq->W3EndTime)) {
TrctrDbgPrint(("TRACERPT Warning Req: %I64u ASP StartTime > pReq->W3EndTime.\n", pReq->RequestId));
}
else if (pReq->W3EndTime == 0 && (pReq->ASPStartTime > pReq->ULReceiveTime)) {
TrctrDbgPrint(("TRACERPT Warning Req: %I64u ASP StartTime > pReq->ULReceiveTime.\n", pReq->RequestId));
}
}
}
#endif
// Fix the time inconsistency in transactions
if (pReq->W3StartTime == 0 || (pReq->W3EndTime != 0 && pReq->W3EndTime < pReq->W3StartTime)) {
RequestsDiscarded++;
if (pReq->URL != NULL) {
free(pReq->URL);
}
return;
}
if (pReq->W3EndTime == 0 || pReq->W3EndTime > pReq->ULReceiveTime) {
pReq->W3EndTime = pReq->ULReceiveTime;
if (pReq->W3EndTime == 0 || pReq->W3EndTime < pReq->W3StartTime) {
RequestsDiscarded++;
if (pReq->URL != NULL) {
free(pReq->URL);
}
return;
}
}
W3ResponseTime = pReq->W3EndTime - pReq->W3StartTime;
if (W3ResponseTime < pReq->W3FilterResponseTime) {
pReq->W3FilterResponseTime = W3ResponseTime;
}
if (pReq->W3ProcessType == EVENT_TRACE_TYPE_W3CORE_CGIREQ) {
if (pReq->CGIStartTime == 0) {
RequestsDiscarded++;
if (pReq->URL != NULL) {
free(pReq->URL);
}
return;
}
else if (pReq->CGIEndTime == 0 || pReq->CGIEndTime > pReq->W3EndTime) {
localCGIEndTime = pReq->W3EndTime;
if (pReq->CGIStartTime > localCGIEndTime) {
RequestsDiscarded++;
if (pReq->URL != NULL) {
free(pReq->URL);
}
return;
}
}
else {
localCGIEndTime = pReq->CGIEndTime;
}
if (pReq->CGIStartTime < pReq->W3StartTime) {
pReq->CGIStartTime = pReq->W3StartTime;
}
if (localCGIEndTime < pReq->CGIStartTime) {
localCGIEndTime = pReq->CGIStartTime;
}
if ((pReq->W3FilterResponseTime + (localCGIEndTime - pReq->CGIStartTime)) > W3ResponseTime) {
pReq->W3FilterResponseTime = W3ResponseTime - (localCGIEndTime - pReq->CGIStartTime);
}
}
else if (pReq->W3ProcessType == EVENT_TRACE_TYPE_W3CORE_ISAPIREQ) {
if (pReq->ISAPIStartTime == 0) {
RequestsDiscarded++;
if (pReq->URL != NULL) {
free(pReq->URL);
}
return;
}
if (pReq->ISAPIEndTime == 0 || pReq->ISAPIEndTime > pReq->W3EndTime) {
localISAPIEndTime = pReq->W3EndTime;
if (pReq->ISAPIStartTime > localISAPIEndTime) {
RequestsDiscarded++;
if (pReq->URL != NULL) {
free(pReq->URL);
}
return;
}
}
else {
localISAPIEndTime = pReq->ISAPIEndTime;
}
if (pReq->ISAPIStartTime < pReq->W3StartTime) {
pReq->ISAPIStartTime = pReq->W3StartTime;
}
if (localISAPIEndTime < pReq->ISAPIStartTime) {
localISAPIEndTime = pReq->ISAPIStartTime;
}
if ((pReq->W3FilterResponseTime + (localISAPIEndTime - pReq->ISAPIStartTime)) > W3ResponseTime) {
pReq->W3FilterResponseTime = W3ResponseTime - (localISAPIEndTime - pReq->ISAPIStartTime);
}
if (pReq->ASPStartTime != 0) {
if (pReq->ASPEndTime == 0) {
localASPEndTime = localISAPIEndTime;
if (pReq->ASPStartTime > localASPEndTime) {
RequestsDiscarded++;
if (pReq->URL != NULL) {
free(pReq->URL);
}
return;
}
}
else {
localASPEndTime = pReq->ASPEndTime;
}
if (pReq->ASPStartTime < pReq->ISAPIStartTime) {
pReq->ASPStartTime = pReq->ISAPIStartTime;
}
if (localASPEndTime < pReq->ASPStartTime) {
localASPEndTime = pReq->ASPStartTime;
}
if ((localISAPIEndTime - pReq->ISAPIStartTime) < (localASPEndTime - pReq->ASPStartTime)) {
localASPEndTime = localISAPIEndTime;
}
}
} // Fix done. All end times are fixed.
IIS->TotalNonCachedResponseTime += pReq->ULResponseTime;
IIS->NonCachedCPUTime += pReq->KCPUTime + pReq->UCPUTime;
if (pReq->W3FilterResponseTime != 0) {
IIS->W3FilterRequests += pReq->W3FilterVisits;
IIS->TotalW3FilterResponseTime += pReq->W3FilterResponseTime;
IIS->TotalW3FilterCPUTime += pReq->W3FltrCPUTime;
}
if (pReq->ULEndType == EVENT_TRACE_TYPE_UL_SENDERROR && pReq->ISAPIStartTime == 0) {
// This is a request ended with SENDERROR.
SendErrorRequests++;
}
if (pReq->HttpStatus != 0 && pReq->HttpStatus >= 400) {
// This is a request with http error.
IIS->W3Error++;
IIS->TotalErrorResponseTime += pReq->ULResponseTime;
IIS->ErrorCPUTime += pReq->KCPUTime + pReq->UCPUTime;
IIS->TotalErrorULOnlyCPUTime += pReq->ULCPUTime;
IIS->TotalErrorW3OnlyCPUTime += pReq->W3CPUTime;
IIS->TotalErrorW3FilterCPUTime += pReq->W3FltrCPUTime;
IIS->TotalErrorCGIOnlyCPUTime += pReq->CGICPUTime;
IIS->TotalErrorISAPIOnlyCPUTime += pReq->ISAPICPUTime;
IIS->TotalErrorASPOnlyCPUTime += pReq->ASPCPUTime;
IIS->TotalErrorW3OnlyResponseTime += (pReq->W3EndTime - pReq->W3StartTime)
- pReq->W3FilterResponseTime;
if (pReq->ULStartTime != 0 && pReq->ULEndTime != 0 && pReq->ULDeliverTime != 0 && pReq->ULReceiveTime != 0) {
// ????????????????????????????????????????????????????????????????????????
// TotalErrorULOnlyResponseTime += (pReq->ULDeliverTime - pReq->ULStartTime)
// + (pReq->ULEndTime - pReq->ULReceiveTime);
IIS->TotalErrorULOnlyResponseTime += pReq->ULResponseTime - (pReq->W3EndTime - pReq->W3StartTime);
}
else {
IIS->TotalErrorULOnlyResponseTime += pReq->ULResponseTime - (pReq->W3EndTime - pReq->W3StartTime);
}
IIS->TotalErrorW3FilterResponseTime += pReq->W3FilterResponseTime;
}
else if (pReq->W3ProcessType == EVENT_TRACE_TYPE_W3CORE_FILEREQ) {
IIS->W3FileRequests++;
IIS->TotalFileResponseTime += pReq->ULResponseTime;
IIS->FileCPUTime += pReq->KCPUTime + pReq->UCPUTime;
IIS->TotalFileULOnlyCPUTime += pReq->ULCPUTime;
IIS->TotalFileW3OnlyCPUTime += pReq->W3CPUTime;
IIS->TotalFileW3FilterCPUTime += pReq->W3FltrCPUTime;
if (pSite != NULL) {
pSite->FileRequests++;
}
IIS->TotalFileW3OnlyResponseTime += (pReq->W3EndTime - pReq->W3StartTime)
- pReq->W3FilterResponseTime;
if (pReq->ULStartTime != 0 && pReq->ULEndTime != 0 && pReq->ULDeliverTime != 0 && pReq->ULReceiveTime != 0) {
// ????????????????????????????????????????????????????????????????????????
// TotalFileULOnlyResponseTime += (pReq->ULDeliverTime - pReq->ULStartTime)
// + (pReq->ULEndTime - pReq->ULReceiveTime);
IIS->TotalFileULOnlyResponseTime += pReq->ULResponseTime - (pReq->W3EndTime - pReq->W3StartTime);
}
else {
IIS->TotalFileULOnlyResponseTime += pReq->ULResponseTime - (pReq->W3EndTime - pReq->W3StartTime);
}
IIS->TotalFileW3FilterResponseTime += pReq->W3FilterResponseTime;
}
else if (pReq->W3ProcessType == EVENT_TRACE_TYPE_W3CORE_CGIREQ) {
IIS->W3CGIRequests++;
IIS->TotalCGIResponseTime += pReq->ULResponseTime;
IIS->TotalCGIOnlyResponseTime += (localCGIEndTime - pReq->CGIStartTime);
IIS->CGICPUTime += pReq->KCPUTime + pReq->UCPUTime;
IIS->TotalCGIOnlyCPUTime += pReq->CGICPUTime;
IIS->TotalCGIULOnlyCPUTime += pReq->ULCPUTime;
IIS->TotalCGIW3OnlyCPUTime += pReq->W3CPUTime;
IIS->TotalCGIW3FilterCPUTime += pReq->W3FltrCPUTime;
if (pSite != NULL) {
pSite->CGIRequests++;
}
IIS->TotalCGIW3OnlyResponseTime += (pReq->W3EndTime - pReq->W3StartTime)
- (localCGIEndTime - pReq->CGIStartTime)
- pReq->W3FilterResponseTime;
if (pReq->ULStartTime != 0 && pReq->ULEndTime != 0 && pReq->ULDeliverTime != 0 && pReq->ULReceiveTime != 0) {
// ????????????????????????????????????????????????????????????????????????
// TotalCGIULOnlyResponseTime += (pReq->ULDeliverTime - pReq->ULStartTime)
// + (pReq->ULEndTime - pReq->ULReceiveTime);
IIS->TotalCGIULOnlyResponseTime += pReq->ULResponseTime - (pReq->W3EndTime - pReq->W3StartTime);
}
else {
IIS->TotalCGIULOnlyResponseTime += pReq->ULResponseTime - (pReq->W3EndTime - pReq->W3StartTime);
}
IIS->TotalCGIW3FilterResponseTime += pReq->W3FilterResponseTime;
}
else if (pReq->W3ProcessType == EVENT_TRACE_TYPE_W3CORE_ISAPIREQ) {
ULONGLONG TimeSpentInAsp = 0;
ULONGLONG TimeSpentInISAPI = 0;
if (pReq->ASPStartTime != 0 && localASPEndTime != 0) {
TimeSpentInAsp = localASPEndTime - pReq->ASPStartTime;
}
if (pReq->ISAPIStartTime != 0 && localISAPIEndTime != 0) {
TimeSpentInISAPI = localISAPIEndTime - pReq->ISAPIStartTime;
if (TimeSpentInAsp > TimeSpentInISAPI) {
TimeSpentInISAPI = 0;
}
else {
TimeSpentInISAPI -= TimeSpentInAsp;
}
}
IIS->W3ISAPIRequests++;
IIS->TotalISAPIResponseTime += pReq->ULResponseTime;
IIS->ISAPICPUTime += pReq->KCPUTime + pReq->UCPUTime;
if (pSite != NULL) {
pSite->ISAPIRequests++;
}
IIS->TotalASPW3OnlyResponseTime += (((pReq->W3EndTime - pReq->W3StartTime) - pReq->W3FilterResponseTime)
- (TimeSpentInISAPI + TimeSpentInAsp));
IIS->W3ASPRequests++;
IIS->TotalASPResponseTime += pReq->ULResponseTime;
IIS->TotalASPOnlyResponseTime += TimeSpentInAsp;
IIS->ASPCPUTime += pReq->KCPUTime + pReq->UCPUTime;
IIS->TotalASPOnlyCPUTime += pReq->ASPCPUTime;
IIS->TotalASPULOnlyCPUTime += pReq->ULCPUTime;
IIS->TotalASPW3OnlyCPUTime += pReq->W3CPUTime;
IIS->TotalASPW3FilterCPUTime += pReq->W3FltrCPUTime;
IIS->TotalASPISAPIOnlyCPUTime += pReq->ISAPICPUTime;
if (pSite != NULL) {
pSite->ASPRequests++;
}
IIS->TotalASPISAPIOnlyResponseTime += TimeSpentInISAPI;
if (pReq->ULStartTime != 0 && pReq->ULEndTime != 0 && pReq->ULDeliverTime != 0 && pReq->ULReceiveTime != 0) {
// ????????????????????????????????????????????????????????????????????????
// TotalASPULOnlyResponseTime += (pReq->ULDeliverTime - pReq->ULStartTime)
// + (pReq->ULEndTime - pReq->ULReceiveTime);
IIS->TotalASPULOnlyResponseTime += pReq->ULResponseTime - (pReq->W3EndTime - pReq->W3StartTime);
}
else {
IIS->TotalASPULOnlyResponseTime += pReq->ULResponseTime - (pReq->W3EndTime - pReq->W3StartTime);
}
IIS->TotalASPW3FilterResponseTime += pReq->W3FilterResponseTime;
}
else if (pReq->W3ProcessType == EVENT_TRACE_TYPE_W3CORE_OOPREQ) { // ???
IIS->W3OOPRequests++;
IIS->TotalOOPResponseTime += pReq->ULResponseTime;
IIS->OOPCPUTime += pReq->KCPUTime + pReq->UCPUTime;
if (pSite != NULL) {
pSite->OOPRequests++;
}
}
}
IIS->TotalRequests++;
IIS->TotalCPUTime += pReq->KCPUTime + pReq->UCPUTime;
if (pReq->URL != NULL) {
free(pReq->URL);
}
}
static void ReportIisEvents(void)
{
HTTP_REQUEST_RECORD Req, *pReq;
char* s;
char line[MAXSTR];
URL_RECORD TopHitURLs[DISPLAY_SIZE];
URL_RECORD TopHitStaticURLs[DISPLAY_SIZE];
URL_RECORD TopSlowURLs[DISPLAY_SIZE];
URL_RECORD TopConsumingURLs[DISPLAY_SIZE];
URL_RECORD TopBytesURLs[DISPLAY_SIZE];
PURL_RECORD pUrl;
CLIENT_RECORD TopHitClients[DISPLAY_SIZE];
CLIENT_RECORD TopSlowClients[DISPLAY_SIZE];
CLIENT_RECORD TopBytesClients[DISPLAY_SIZE];
PCLIENT_RECORD pClient;
SITE_RECORD TopHitSites[DISPLAY_SIZE];
SITE_RECORD TopSlowSites[DISPLAY_SIZE];
SITE_RECORD TopConsumingSites[DISPLAY_SIZE];
SITE_RECORD TopBytesSites[DISPLAY_SIZE];
PSITE_RECORD pSite;
ULONG i, k;
ULONG Duration = (ULONG)((CurrentSystem.IISEndTime - CurrentSystem.IISStartTime) / 10000000);
ULONG MilDuration = (ULONG)((CurrentSystem.IISEndTime - CurrentSystem.IISStartTime) * CurrentSystem.NumberOfProcessors / 10000);
double Rates = 0.0;
PLIST_ENTRY Next, Head;
ULONG PrintCPUUsage = TRUE;
if( NULL == CurrentSystem.TempIisFile ){
return;
}
IIS = (PIIS_REPORT_RECORD)malloc(sizeof(IIS_REPORT_RECORD));
if (IIS == NULL) {
return;
}
RtlZeroMemory(IIS, sizeof(IIS_REPORT_RECORD));
Head = &CurrentSystem.ProcessListHead;
Next = Head->Flink;
if( Head == Next ){
PrintCPUUsage = FALSE;
}
pReq = &Req;
RtlZeroMemory(pReq, sizeof(HTTP_REQUEST_RECORD));
RtlZeroMemory(line, MAXSTR * sizeof(char));
// Process requests written in the file
rewind( CurrentSystem.TempIisFile );
while ( fgets(line, MAXSTR, CurrentSystem.TempIisFile) != NULL ) {
s = strtok( line, (","));
CHECKTOK( s );
pReq->RequestId = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->SiteId = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->KCPUTime = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->UCPUTime = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->ReadIO = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->WriteIO = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->ULStartTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->ULEndTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->ULResponseTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->ULParseTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->ULDeliverTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->ULReceiveTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->ULReceiveType = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->ULEndType = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->W3StartTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->W3EndTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->W3FilterResponseTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->W3ProcessType = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->W3EndType = (SHORT) atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->FileReqTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->CGIStartTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->CGIEndTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->ISAPIStartTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->ISAPIEndTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->ASPStartTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->ASPEndTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->SSLResponseTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->StrmFltrResponseTime = _atoi64(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->HttpStatus = (USHORT) atol(s);;
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->IsapiExt = (USHORT) atol(s);;
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->IpAddrType = (USHORT) atol(s);;
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->IpAddrV4 = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->IpAddrV6[0] = (USHORT) atol(s);;
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->IpAddrV6[1] = (USHORT) atol(s);;
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->IpAddrV6[2] = (USHORT) atol(s);;
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->IpAddrV6[3] = (USHORT) atol(s);;
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->IpAddrV6[4] = (USHORT) atol(s);;
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->IpAddrV6[5] = (USHORT) atol(s);;
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->IpAddrV6[6] = (USHORT) atol(s);;
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->IpAddrV6[7] = (USHORT) atol(s);;
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->NumberOfThreads = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->BytesSent = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->ULCPUTime = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->W3CPUTime = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->W3FltrCPUTime = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->ISAPICPUTime = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->ASPCPUTime = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
pReq->CGICPUTime = atol(s);
s = strtok( NULL, (","));
CHECKTOK( s );
if (strlen(s) > 0) {
LPSTR strptr = (LPSTR)malloc(strlen(s) + 1);
if (strptr != NULL) {
RtlCopyMemory((PUCHAR)strptr, (PUCHAR)s, strlen(s));
if (*(strptr + strlen(s) - 1) == '\n') {
*(strptr + strlen(s) - 1) = '\0';
}
else {
*(strptr + strlen(s)) = '\0';
}
pReq->URL = (PCHAR)strptr;
}
else {
continue;
}
}
else {
continue;
}
ProcessIisRequest(pReq);
}
if (IIS->TotalRequests != 0) {
if (Duration != 0) {
Rates = (double)(IIS->TotalRequests) / (double)Duration;
}
else {
Rates = 0.0;
}
}
else {
free(IIS);
return;
}
fprintf(procFile, "<table title='Http Requests Response Time Statistics'>\n");
fprintf(procFile,
"<requests cached='true' type='Static HTTP'>"
"<rate>%1.3f</rate>"
"<response_time>%1.3f</response_time>"
"<component name='UL'>%3d.0</component>"
"<component name='W3'>0.0</component>"
"<component name='W3Fltr'>0.0</component>"
"<component name='ISAPI'>0.0</component>"
"<component name='ASP'>0.0</component>"
"<component name='CGI'>0.0</component>"
"</requests>\n",
Duration ? (double)(IIS->CachedResponses) / (double)Duration : 0.0,
IIS->CachedResponses ? (double)(IIS->TotalCachedResponseTime / IIS->CachedResponses) / 10000.0 : 0.0,
IIS->CachedResponses ? 100 : 0);
fprintf(procFile,
"<requests cached='false' type='ASP'>"
"<rate>%1.3f</rate>"
"<response_time>%1.3f</response_time>"
"<component name='UL'>%1.1f</component>"
"<component name='W3'>%1.1f</component>"
"<component name='W3Fltr'>%1.1f</component>"
"<component name='ISAPI'>%1.1f</component>"
"<component name='ASP'>%1.1f</component>"
"<component name='CGI'>%1.1f</component>"
"</requests>\n",
Duration ? (double)(IIS->W3ISAPIRequests) / (double)Duration : 0.0,
(IIS->W3ISAPIRequests) ? ((double)IIS->TotalISAPIResponseTime / (double)IIS->W3ISAPIRequests) / 10000.0 : 0.0,
((IIS->TotalASPResponseTime) ? ((double)(IIS->TotalASPULOnlyResponseTime) / (double)(IIS->TotalASPResponseTime)) * 100.0 : 0.0),
((IIS->TotalASPResponseTime) ? ((double)(IIS->TotalASPW3OnlyResponseTime) / (double)(IIS->TotalASPResponseTime)) * 100.0 : 0.0),
((IIS->TotalASPResponseTime) ? ((double)(IIS->TotalASPW3FilterResponseTime) / (double)(IIS->TotalASPResponseTime)) * 100.0 : 0.0),
((IIS->TotalASPResponseTime) ? ((double)(IIS->TotalASPISAPIOnlyResponseTime) / (double)(IIS->TotalASPResponseTime)) * 100.0 : 0.0),
((IIS->TotalASPResponseTime) ? ((double)(IIS->TotalASPOnlyResponseTime) / (double)(IIS->TotalASPResponseTime)) * 100.0 : 0.0),
0.0);
fprintf(procFile,
"<requests cached='false' type='Static HTTP'>"
"<rate>%1.3f</rate>"
"<response_time>%1.3f</response_time>"
"<component name='UL'>%1.1f</component>"
"<component name='W3'>%1.1f</component>"
"<component name='W3Fltr'>%1.1f</component>"
"<component name='ISAPI'>%1.1f</component>"
"<component name='ASP'>%1.1f</component>"
"<component name='CGI'>%1.1f</component>"
"</requests>\n",
Duration ? (double)(IIS->W3FileRequests) / (double)Duration : 0.0,
(IIS->W3FileRequests) ? ((double)IIS->TotalFileResponseTime / (double)IIS->W3FileRequests) / 10000.0 : 0.0,
(IIS->TotalFileResponseTime ? ((double)(IIS->TotalFileULOnlyResponseTime) / (double)(IIS->TotalFileResponseTime)) * 100.0 : 0.0),
(IIS->TotalFileResponseTime ? ((double)(IIS->TotalFileW3OnlyResponseTime) / (double)(IIS->TotalFileResponseTime)) * 100.0 : 0.0),
(IIS->TotalFileResponseTime ? ((double)(IIS->TotalFileW3FilterResponseTime) / (double)(IIS->TotalFileResponseTime)) * 100.0 : 0.0),
0.0,
0.0,
0.0);
fprintf(procFile,
"<requests cached='false' type='CGI'>"
"<rate>%1.3f</rate>"
"<response_time>%1.3f</response_time>"
"<component name='UL'>%1.1f</component>"
"<component name='W3'>%1.1f</component>"
"<component name='W3Fltr'>%1.1f</component>"
"<component name='ISAPI'>%1.1f</component>"
"<component name='ASP'>%1.1f</component>"
"<component name='CGI'>%1.1f</component>"
"</requests>\n",
Duration ? (double)(IIS->W3CGIRequests) / (double)Duration : 0.0,
(IIS->W3CGIRequests) ? ((double)IIS->TotalCGIResponseTime / (double)IIS->W3CGIRequests) / 10000.0 : 0.0,
((IIS->TotalCGIResponseTime) ? ((double)(IIS->TotalCGIULOnlyResponseTime) / (double)(IIS->TotalCGIResponseTime)) * 100.0 : 0.0),
((IIS->TotalCGIResponseTime) ? ((double)(IIS->TotalCGIW3OnlyResponseTime) / (double)(IIS->TotalCGIResponseTime)) * 100.0 : 0.0),
((IIS->TotalCGIResponseTime) ? ((double)(IIS->TotalCGIW3FilterResponseTime) / (double)(IIS->TotalCGIResponseTime)) * 100.0 : 0.0),
0.0,
0.0,
((IIS->TotalCGIResponseTime) ? ((double)(IIS->TotalCGIOnlyResponseTime) / (double)(IIS->TotalCGIResponseTime)) * 100.0 : 0.0));
if (IIS->W3Error != 0) {
fprintf(procFile,
"<requests cached='false' type='Error'>"
"<rate>%1.3f</rate>"
"<response_time>%1.3f</response_time>"
"<component name='UL'>%1.1f</component>"
"<component name='W3'>%1.1f</component>"
"<component name='W3Fltr'>%1.1f</component>"
"<component name='ISAPI'>%1.1f</component>"
"<component name='ASP'>%1.1f</component>"
"<component name='CGI'>%1.1f</component>"
"</requests>\n",
Duration ? (double)(IIS->W3Error) / (double)Duration : 0.0,
(IIS->W3Error) ? ((double)IIS->TotalErrorResponseTime / (double)IIS->W3Error) / 10000.0 : 0.0,
((IIS->TotalErrorResponseTime) ? ((double)(IIS->TotalErrorULOnlyResponseTime) / (double)(IIS->TotalErrorResponseTime)) * 100.0 : 0.0),
((IIS->TotalErrorResponseTime) ? ((double)(IIS->TotalErrorW3OnlyResponseTime) / (double)(IIS->TotalErrorResponseTime)) * 100.0 : 0.0),
((IIS->TotalErrorResponseTime) ? ((double)(IIS->TotalErrorW3FilterResponseTime) / (double)(IIS->TotalErrorResponseTime)) * 100.0 : 0.0),
0.0,
0.0,
0.0);
}
fprintf(procFile,
"<summary cached='true'>"
"<rate>%1.3f</rate>"
"<response_time>%1.3f</response_time>"
"<component name='UL'>%3d.0</component>"
"<component name='W3'>0.0</component>"
"<component name='W3Fltr'>0.0</component>"
"<component name='ISAPI'>0.0</component>"
"<component name='ASP'>0.0</component>"
"<component name='CGI'>0.0</component>"
"</summary>\n",
Duration ? (double)(IIS->CachedResponses) / (double)Duration : 0.0,
IIS->CachedResponses ? (double)(IIS->TotalCachedResponseTime / IIS->CachedResponses) / 10000.0 : 0.0,
IIS->CachedResponses ? 100 : 0);
fprintf(procFile,
"<summary cached='false'>"
"<rate percent='%1.3f'>%1.3f</rate>"
"<response_time>%1.3f</response_time>"
"<component name='UL'>%1.1f</component>"
"<component name='W3'>%1.1f</component>"
"<component name='W3Fltr'>%1.1f</component>"
"<component name='ISAPI'>%1.1f</component>"
"<component name='ASP'>%1.1f</component>"
"<component name='CGI'>%1.1f</component>"
"</summary>\n",
((double)(IIS->TotalRequests - IIS->CachedResponses) / ((double)IIS->TotalRequests)) * 100.0,
Duration ? (double)(IIS->TotalRequests - IIS->CachedResponses) / (double)Duration : 0.0,
(IIS->TotalRequests - IIS->CachedResponses) ? ((double)IIS->TotalNonCachedResponseTime / (double)(IIS->TotalRequests - IIS->CachedResponses)) / 10000.0 : 0.0,
((IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalFileULOnlyResponseTime + IIS->TotalCGIULOnlyResponseTime + IIS->TotalASPULOnlyResponseTime + IIS->TotalErrorULOnlyResponseTime) / (double)(IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
((IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalFileW3OnlyResponseTime + IIS->TotalCGIW3OnlyResponseTime + IIS->TotalASPW3OnlyResponseTime + IIS->TotalErrorW3OnlyResponseTime) / (double)(IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
((IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalW3FilterResponseTime) / (double)(IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
((IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalASPISAPIOnlyResponseTime) / (double)(IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
((IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalASPOnlyResponseTime) / (double)(IIS->TotalNonCachedResponseTime)) * 100.0: 0.0),
((IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalCGIOnlyResponseTime) / (double)(IIS->TotalNonCachedResponseTime)) * 100.0: 0.0));
fprintf(procFile,
"<summary type='totals'>"
"<rate>%1.3f</rate>"
"<response_time>%1.3f</response_time>"
"<component name='UL'>%1.1f</component>"
"<component name='W3'>%1.1f</component>"
"<component name='W3Fltr'>%1.1f</component>"
"<component name='ISAPI'>%1.1f</component>"
"<component name='ASP'>%1.1f</component>"
"<component name='CGI'>%1.1f</component>"
"</summary>\n",
Duration ? (double)(IIS->TotalRequests) / (double)Duration : 0.0,
((double)(IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime) / (double)IIS->TotalRequests) / 10000.0,
((IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalCachedResponseTime + IIS->TotalFileULOnlyResponseTime + IIS->TotalCGIULOnlyResponseTime + IIS->TotalASPULOnlyResponseTime + IIS->TotalErrorULOnlyResponseTime) / (double)(IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
((IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalFileW3OnlyResponseTime + IIS->TotalCGIW3OnlyResponseTime + IIS->TotalASPW3OnlyResponseTime + IIS->TotalErrorW3OnlyResponseTime) / (double)(IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
((IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalW3FilterResponseTime) / (double)(IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
((IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalASPISAPIOnlyResponseTime) / (double)(IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
((IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalASPOnlyResponseTime) / (double)(IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
((IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalCGIOnlyResponseTime) / (double)(IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0));
fprintf(procFile, "</table>\n");
if (PrintCPUUsage) {
fprintf(procFile, "<table title='Http Requests CPU Time Usage Statistics'>\n");
fprintf(procFile,
"<requests cached='true' type='Static HTTP'>"
"<rate>%1.3f</rate>"
"<cpu>%1.1f</cpu>"
"<component name='UL'>%3d.0</component>"
"<component name='W3'>0.0</component>"
"<component name='W3Fltr'>0.0</component>"
"<component name='ISAPI'>0.0</component>"
"<component name='ASP'>0.0</component>"
"<component name='CGI'>0.0</component>"
"</requests>\n",
Duration ? (double)(IIS->CachedResponses) / (double)Duration : 0.0,
MilDuration ? (((double)(IIS->CachedCPUTime) / (double)MilDuration) * 100.0) : 0.0,
IIS->CachedResponses ? 100 : 0);
fprintf(procFile,
"<requests cached='false' type='ASP'>"
"<rate>%1.3f</rate>"
"<cpu>%1.1f</cpu>"
"<component name='UL'>%1.1f</component>"
"<component name='W3'>%1.1f</component>"
"<component name='W3Fltr'>%1.1f</component>"
"<component name='ISAPI'>%1.1f</component>"
"<component name='ASP'>%1.1f</component>"
"<component name='CGI'>%1.1f</component>"
"</requests>\n",
Duration ? (double)(IIS->W3ISAPIRequests) / (double)Duration : 0.0,
MilDuration ? (((double)(IIS->ISAPICPUTime) / (double)MilDuration) * 100.0) : 0.0,
((IIS->ASPCPUTime) ? ((double)(IIS->TotalASPULOnlyCPUTime) / (double)(IIS->ASPCPUTime)) * 100.0 : 0.0),
((IIS->ASPCPUTime) ? ((double)(IIS->TotalASPW3OnlyCPUTime) / (double)(IIS->ASPCPUTime)) * 100.0 : 0.0),
((IIS->ASPCPUTime) ? ((double)(IIS->TotalASPW3FilterCPUTime) / (double)(IIS->ASPCPUTime)) * 100.0 : 0.0),
((IIS->ASPCPUTime) ? ((double)(IIS->TotalASPISAPIOnlyCPUTime) / (double)(IIS->ASPCPUTime)) * 100.0 : 0.0),
((IIS->ASPCPUTime) ? ((double)(IIS->TotalASPOnlyCPUTime) / (double)(IIS->ASPCPUTime)) * 100.0: 0.0),
0.0);
fprintf(procFile,
"<requests cached='false' type='Static HTTP'>"
"<rate>%1.3f</rate>"
"<cpu>%1.1f</cpu>"
"<component name='UL'>%1.1f</component>"
"<component name='W3'>%1.1f</component>"
"<component name='W3Fltr'>%1.1f</component>"
"<component name='ISAPI'>%1.1f</component>"
"<component name='ASP'>%1.1f</component>"
"<component name='CGI'>%1.1f</component>"
"</requests>\n",
Duration ? (double)(IIS->W3FileRequests) / (double)Duration : 0.0,
MilDuration ? (((double)(IIS->FileCPUTime) / (double)MilDuration) * 100.0) : 0.0,
((IIS->FileCPUTime) ? ((double)(IIS->TotalFileULOnlyCPUTime) / (double)(IIS->FileCPUTime)) * 100.0 : 0.0),
((IIS->FileCPUTime) ? ((double)(IIS->TotalFileW3OnlyCPUTime) / (double)(IIS->FileCPUTime)) * 100.0 : 0.0),
((IIS->FileCPUTime) ? ((double)(IIS->TotalFileW3FilterCPUTime) / (double)(IIS->FileCPUTime)) * 100.0 : 0.0),
0.0,
0.0,
0.0);
fprintf(procFile,
"<requests cached='false' type='CGI'>"
"<rate>%1.3f</rate>"
"<cpu>%1.1f</cpu>"
"<component name='UL'>%1.1f</component>"
"<component name='W3'>%1.1f</component>"
"<component name='W3Fltr'>%1.1f</component>"
"<component name='ISAPI'>%1.1f</component>"
"<component name='ASP'>%1.1f</component>"
"<component name='CGI'>%1.1f</component>"
"</requests>\n",
Duration ? (double)(IIS->W3CGIRequests) / (double)Duration : 0.0,
MilDuration ? (((double)(IIS->CGICPUTime) / (double)MilDuration) * 100.0) : 0.0,
((IIS->CGICPUTime) ? ((double)(IIS->TotalCGIULOnlyCPUTime) / (double)(IIS->CGICPUTime)) * 100.0 : 0.0),
((IIS->CGICPUTime) ? ((double)(IIS->TotalCGIW3OnlyCPUTime) / (double)(IIS->CGICPUTime)) * 100.0 : 0.0),
((IIS->CGICPUTime) ? ((double)(IIS->TotalCGIW3FilterCPUTime) / (double)(IIS->CGICPUTime)) * 100.0 : 0.0),
0.0,
0.0,
((IIS->CGICPUTime) ? ((double)(IIS->TotalCGIOnlyCPUTime) / (double)(IIS->CGICPUTime)) * 100.0 : 0.0));
if (IIS->W3Error != 0) {
fprintf(procFile,
"<requests cached='false' type='Error'>"
"<rate>%1.3f</rate>"
"<cpu>%1.1f</cpu>"
"<component name='UL'>%1.1f</component>"
"<component name='W3'>%1.1f</component>"
"<component name='W3Fltr'>%1.1f</component>"
"<component name='ISAPI'>%1.1f</component>"
"<component name='ASP'>%1.1f</component>"
"<component name='CGI'>%1.1f</component>"
"</requests>\n",
Duration ? (double)(IIS->W3Error) / (double)Duration : 0.0,
MilDuration ? (((double)(IIS->ErrorCPUTime) / (double)MilDuration) * 100.0) : 0.0,
((IIS->ErrorCPUTime) ? ((double)(IIS->TotalErrorULOnlyCPUTime) / (double)(IIS->ErrorCPUTime)) * 100.0 : 0.0),
((IIS->ErrorCPUTime) ? ((double)(IIS->TotalErrorW3OnlyCPUTime) / (double)(IIS->ErrorCPUTime)) * 100.0 : 0.0),
((IIS->ErrorCPUTime) ? ((double)(IIS->TotalErrorW3FilterCPUTime) / (double)(IIS->ErrorCPUTime)) * 100.0 : 0.0),
0.0,
0.0,
0.0);
}
fprintf(procFile,
"<summary cached='true'>"
"<rate>%1.3f</rate>"
"<cpu>%1.1f</cpu>"
"<component name='UL'>%3d.0</component>"
"<component name='W3'>0.0</component>"
"<component name='W3Fltr'>0.0</component>"
"<component name='ISAPI'>0.0</component>"
"<component name='ASP'>0.0</component>"
"<component name='CGI'>0.0</component>"
"</summary>\n",
Duration ? (double)(IIS->CachedResponses) / (double)Duration : 0.0,
MilDuration ? (((double)(IIS->CachedCPUTime) / (double)MilDuration) * 100.0) : 0.0,
IIS->CachedResponses ? 100 : 0);
fprintf(procFile,
"<summary cached='false'>"
"<rate percent='%1.1f'>%1.3f</rate>"
"<cpu>%1.1f</cpu>"
"<component name='UL'>%1.1f</component>"
"<component name='W3'>%1.1f</component>"
"<component name='W3Fltr'>%1.1f</component>"
"<component name='ISAPI'>%1.1f</component>"
"<component name='ASP'>%1.1f</component>"
"<component name='CGI'>%1.1f</component>"
"</summary>\n",
((double)(IIS->TotalRequests - IIS->CachedResponses) / ((double)IIS->TotalRequests)) * 100.0,
Duration ? (double)(IIS->TotalRequests - IIS->CachedResponses) / (double)Duration : 0.0,
MilDuration ? (((double)(IIS->NonCachedCPUTime) / (double)MilDuration) * 100.0) : 0.0,
((IIS->NonCachedCPUTime) ? ((double)(IIS->TotalFileULOnlyCPUTime + IIS->TotalCGIULOnlyCPUTime + IIS->TotalASPULOnlyCPUTime + IIS->TotalErrorULOnlyCPUTime) / (double)(IIS->NonCachedCPUTime)) * 100.0 : 0.0),
((IIS->NonCachedCPUTime) ? ((double)(IIS->TotalFileW3OnlyCPUTime + IIS->TotalCGIW3OnlyCPUTime + IIS->TotalASPW3OnlyCPUTime + IIS->TotalErrorW3OnlyCPUTime) / (double)(IIS->NonCachedCPUTime)) * 100.0 : 0.0),
((IIS->NonCachedCPUTime) ? ((double)(IIS->TotalW3FilterCPUTime) / (double)(IIS->NonCachedCPUTime)) * 100.0 : 0.0),
((IIS->NonCachedCPUTime) ? ((double)(IIS->TotalASPISAPIOnlyCPUTime) / (double)(IIS->NonCachedCPUTime)) * 100.0 : 0.0),
((IIS->NonCachedCPUTime) ? ((double)(IIS->TotalASPOnlyCPUTime) / (double)(IIS->NonCachedCPUTime)) * 100.0: 0.0),
((IIS->NonCachedCPUTime) ? ((double)(IIS->TotalCGIOnlyCPUTime) / (double)(IIS->NonCachedCPUTime)) * 100.0: 0.0));
fprintf(procFile,
"<summary type='totals'>"
"<rate>%1.3f</rate>"
"<cpu>%1.1f</cpu>"
"<component name='UL'>%1.1f</component>"
"<component name='W3'>%1.1f</component>"
"<component name='W3Fltr'>%1.1f</component>"
"<component name='ISAPI'>%1.1f</component>"
"<component name='ASP'>%1.1f</component>"
"<component name='CGI'>%1.1f</component>"
"</summary>\n",
Duration ? (double)IIS->TotalRequests / (double)Duration : 0.0,
MilDuration ? (((double)(IIS->TotalCPUTime) / (double)MilDuration) * 100.0) : 0.0,
((IIS->TotalCPUTime) ? ((double)(IIS->CachedCPUTime + IIS->TotalFileULOnlyCPUTime + IIS->TotalCGIULOnlyCPUTime + IIS->TotalASPULOnlyCPUTime + IIS->TotalErrorULOnlyCPUTime) / (double)(IIS->TotalCPUTime)) * 100.0 : 0.0),
((IIS->TotalCPUTime) ? ((double)(IIS->TotalFileW3OnlyCPUTime + IIS->TotalCGIW3OnlyCPUTime + IIS->TotalASPW3OnlyCPUTime + IIS->TotalErrorW3OnlyCPUTime) / (double)(IIS->TotalCPUTime)) * 100.0 : 0.0),
((IIS->TotalCPUTime) ? ((double)(IIS->TotalW3FilterCPUTime) / (double)(IIS->TotalCPUTime)) * 100.0 : 0.0),
((IIS->TotalCPUTime) ? ((double)(IIS->TotalASPISAPIOnlyCPUTime) / (double)(IIS->TotalCPUTime)) * 100.0 : 0.0),
((IIS->TotalCPUTime) ? ((double)(IIS->TotalASPOnlyCPUTime) / (double)(IIS->TotalCPUTime)) * 100.0: 0.0),
((IIS->TotalCPUTime) ? ((double)(IIS->TotalCGIOnlyCPUTime) / (double)(IIS->TotalCPUTime)) * 100.0: 0.0));
fprintf(procFile, "</table>\n");
}
RtlZeroMemory(TopHitURLs, sizeof(URL_RECORD) * DISPLAY_SIZE);
RtlZeroMemory(TopHitStaticURLs, sizeof(URL_RECORD) * DISPLAY_SIZE);
RtlZeroMemory(TopSlowURLs, sizeof(URL_RECORD) * DISPLAY_SIZE);
RtlZeroMemory(TopConsumingURLs, sizeof(URL_RECORD) * DISPLAY_SIZE);
RtlZeroMemory(TopBytesURLs, sizeof(URL_RECORD) * DISPLAY_SIZE);
for (k = 0; k < URL_HASH_TABLESIZE; k++) {
pUrl = GetHeadUrlRecord(k);
while (pUrl != NULL) {
ULONGLONG AverageURLResponseTime = 0;
ULONG Found;
URL_RECORD tmpUrl1, tmpUrl2;
if (pUrl->Requests != 0) {
RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
RtlZeroMemory(&tmpUrl2, sizeof(URL_RECORD));
Found = FALSE;
for (i = 0; i < DISPLAY_SIZE; i++) {
if (Found && tmpUrl1.Requests != 0) {
RtlCopyMemory(&tmpUrl2, &TopHitURLs[i], sizeof(URL_RECORD));
RtlCopyMemory(&TopHitURLs[i], &tmpUrl1, sizeof(URL_RECORD));
RtlCopyMemory(&tmpUrl1, &tmpUrl2, sizeof(URL_RECORD));
}
else if (!Found) {
if (TopHitURLs[i].Requests == 0) {
RtlCopyMemory(&TopHitURLs[i], pUrl, sizeof(URL_RECORD));
TopHitURLs[i].URL = CopyUrlStr(pUrl->URL);
if (TopHitURLs[i].URL != NULL) {
Found = TRUE;
}
else {
RtlZeroMemory(&TopHitURLs[i], sizeof(URL_RECORD));
}
}
else if (pUrl->Requests > TopHitURLs[i].Requests) {
RtlCopyMemory(&tmpUrl1, &TopHitURLs[i], sizeof(URL_RECORD));
RtlCopyMemory(&TopHitURLs[i], pUrl, sizeof(URL_RECORD));
TopHitURLs[i].URL = CopyUrlStr(pUrl->URL);
if (TopHitURLs[i].URL != NULL) {
Found = TRUE;
}
else {
RtlCopyMemory(&TopHitURLs[i], &tmpUrl1, sizeof(URL_RECORD));
RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
}
}
}
}
if (tmpUrl1.Requests != 0) {
free(tmpUrl1.URL);
}
RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
RtlZeroMemory(&tmpUrl2, sizeof(URL_RECORD));
Found = FALSE;
for (i = 0; i < DISPLAY_SIZE; i++) {
if (Found && tmpUrl1.Requests != 0) {
RtlCopyMemory(&tmpUrl2, &TopHitStaticURLs[i], sizeof(URL_RECORD));
RtlCopyMemory(&TopHitStaticURLs[i], &tmpUrl1, sizeof(URL_RECORD));
RtlCopyMemory(&tmpUrl1, &tmpUrl2, sizeof(URL_RECORD));
}
else if (!Found) {
if ((pUrl->UrlType == EVENT_TRACE_TYPE_W3CORE_FILEREQ || pUrl->Hits > 0) &&
TopHitStaticURLs[i].Requests == 0) {
RtlCopyMemory(&TopHitStaticURLs[i], pUrl, sizeof(URL_RECORD));
TopHitStaticURLs[i].URL = CopyUrlStr(pUrl->URL);
if (TopHitStaticURLs[i].URL != NULL) {
Found = TRUE;
}
else {
RtlZeroMemory(&TopHitStaticURLs[i], sizeof(URL_RECORD));
}
}
else if ((pUrl->UrlType == EVENT_TRACE_TYPE_W3CORE_FILEREQ || pUrl->Hits > 0) &&
pUrl->Requests > TopHitStaticURLs[i].Requests) {
RtlCopyMemory(&tmpUrl1, &TopHitStaticURLs[i], sizeof(URL_RECORD));
RtlCopyMemory(&TopHitStaticURLs[i], pUrl, sizeof(URL_RECORD));
TopHitStaticURLs[i].URL = CopyUrlStr(pUrl->URL);
if (TopHitStaticURLs[i].URL != NULL) {
Found = TRUE;
}
else {
RtlCopyMemory(&TopHitStaticURLs[i], &tmpUrl1, sizeof(URL_RECORD));
RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
}
}
}
}
if (tmpUrl1.Requests != 0) {
free(tmpUrl1.URL);
}
AverageURLResponseTime = pUrl->TotalResponseTime / pUrl->Requests;
RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
RtlZeroMemory(&tmpUrl2, sizeof(URL_RECORD));
Found = FALSE;
for (i = 0; i < DISPLAY_SIZE; i++) {
if (Found && tmpUrl1.Requests != 0) {
RtlCopyMemory(&tmpUrl2, &TopSlowURLs[i], sizeof(URL_RECORD));
RtlCopyMemory(&TopSlowURLs[i], &tmpUrl1, sizeof(URL_RECORD));
RtlCopyMemory(&tmpUrl1, &tmpUrl2, sizeof(URL_RECORD));
}
else if (!Found) {
if (TopSlowURLs[i].Requests == 0) {
RtlCopyMemory(&TopSlowURLs[i], pUrl, sizeof(URL_RECORD));
TopSlowURLs[i].URL = CopyUrlStr(pUrl->URL);
if (TopSlowURLs[i].URL != NULL) {
Found = TRUE;
}
else {
RtlZeroMemory(&TopSlowURLs[i], sizeof(URL_RECORD));
}
}
else if (AverageURLResponseTime > (TopSlowURLs[i].TotalResponseTime / TopSlowURLs[i].Requests)) {
RtlCopyMemory(&tmpUrl1, &TopSlowURLs[i], sizeof(URL_RECORD));
RtlCopyMemory(&TopSlowURLs[i], pUrl, sizeof(URL_RECORD));
TopSlowURLs[i].URL = CopyUrlStr(pUrl->URL);
if (TopSlowURLs[i].URL != NULL) {
Found = TRUE;
}
else {
RtlCopyMemory(&TopSlowURLs[i], &tmpUrl1, sizeof(URL_RECORD));
RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
}
}
}
}
if (tmpUrl1.Requests != 0) {
free(tmpUrl1.URL);
}
RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
RtlZeroMemory(&tmpUrl2, sizeof(URL_RECORD));
Found = FALSE;
for (i = 0; i < DISPLAY_SIZE; i++) {
if (Found && tmpUrl1.Requests != 0) {
RtlCopyMemory(&tmpUrl2, &TopConsumingURLs[i], sizeof(URL_RECORD));
RtlCopyMemory(&TopConsumingURLs[i], &tmpUrl1, sizeof(URL_RECORD));
RtlCopyMemory(&tmpUrl1, &tmpUrl2, sizeof(URL_RECORD));
}
else if (!Found) {
if (TopConsumingURLs[i].Requests == 0) {
RtlCopyMemory(&TopConsumingURLs[i], pUrl, sizeof(URL_RECORD));
TopConsumingURLs[i].URL = CopyUrlStr(pUrl->URL);
if (TopConsumingURLs[i].URL != NULL) {
Found = TRUE;
}
else {
RtlZeroMemory(&TopConsumingURLs[i], sizeof(URL_RECORD));
}
}
else if ((pUrl->KCPUTime + pUrl->UCPUTime) > (TopConsumingURLs[i].KCPUTime + TopConsumingURLs[i].UCPUTime)) {
RtlCopyMemory(&tmpUrl1, &TopConsumingURLs[i], sizeof(URL_RECORD));
RtlCopyMemory(&TopConsumingURLs[i], pUrl, sizeof(URL_RECORD));
TopConsumingURLs[i].URL = CopyUrlStr(pUrl->URL);
if (TopConsumingURLs[i].URL != NULL) {
Found = TRUE;
}
else {
RtlCopyMemory(&TopConsumingURLs[i], &tmpUrl1, sizeof(URL_RECORD));
RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
}
}
}
}
if (tmpUrl1.Requests != 0) {
free(tmpUrl1.URL);
}
RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
RtlZeroMemory(&tmpUrl2, sizeof(URL_RECORD));
Found = FALSE;
for (i = 0; i < DISPLAY_SIZE; i++) {
if (Found && tmpUrl1.Requests != 0) {
RtlCopyMemory(&tmpUrl2, &TopBytesURLs[i], sizeof(URL_RECORD));
RtlCopyMemory(&TopBytesURLs[i], &tmpUrl1, sizeof(URL_RECORD));
RtlCopyMemory(&tmpUrl1, &tmpUrl2, sizeof(URL_RECORD));
}
else if (!Found) {
if (TopBytesURLs[i].Requests == 0) {
RtlCopyMemory(&TopBytesURLs[i], pUrl, sizeof(URL_RECORD));
TopBytesURLs[i].URL = CopyUrlStr(pUrl->URL);
if (TopBytesURLs[i].URL != NULL) {
Found = TRUE;
}
else {
RtlZeroMemory(&TopBytesURLs[i], sizeof(URL_RECORD));
}
}
else if (pUrl->BytesSent > TopBytesURLs[i].BytesSent) {
RtlCopyMemory(&tmpUrl1, &TopBytesURLs[i], sizeof(URL_RECORD));
RtlCopyMemory(&TopBytesURLs[i], pUrl, sizeof(URL_RECORD));
TopBytesURLs[i].URL = CopyUrlStr(pUrl->URL);
if (TopBytesURLs[i].URL != NULL) {
Found = TRUE;
}
else {
RtlCopyMemory(&TopBytesURLs[i], &tmpUrl1, sizeof(URL_RECORD));
RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
}
}
}
}
if (tmpUrl1.Requests != 0) {
free(tmpUrl1.URL);
}
}
if (pUrl->URL) {
free(pUrl->URL);
}
free(pUrl);
pUrl = GetHeadUrlRecord(k);
}
}
fprintf( procFile, "<table title='Most Requested URLs' top='%d'>", DISPLAY_SIZE);
for (i = 0; i < DISPLAY_SIZE && TopHitURLs[i].Requests != 0; i++) {
ULONGLONG AverageURLResponseTime = 0;
CHAR ReducedUrl[URL_NAME_COLUMN_SIZE + 1];
char* strPrint;
if (TopHitURLs[i].Requests != 0) {
AverageURLResponseTime = TopHitURLs[i].TotalResponseTime / TopHitURLs[i].Requests;
}
RemoveCtrlCharA(TopHitURLs[i].URL, strlen(TopHitURLs[i].URL));
if (strlen(TopHitURLs[i].URL) > URL_NAME_COLUMN_SIZE) {
ReduceStringA(ReducedUrl, URL_NAME_COLUMN_SIZE + 1, TopHitURLs[i].URL);
strPrint = ReducedUrl;
}else{
strPrint = TopHitURLs[i].URL;
}
fprintf(procFile,
"<url name='%s'>"
"<site_id>%d</site_id>"
"<rate>%1.3f</rate>"
"<cache_hit>%1.1f</cache_hit>"
"<response_time>%1.1f</response_time>"
"</url>\n",
strPrint,
TopHitURLs[i].SiteId,
(Duration ? ((double)TopHitURLs[i].Requests / (double)Duration) : 0.0),
TopHitURLs[i].Requests ? ((double)TopHitURLs[i].Hits / (double)TopHitURLs[i].Requests * 100.0) : 0.0,
((double)AverageURLResponseTime) / 10000.0);
}
fprintf( procFile, "</table>\n" );
fprintf(procFile, "<table title='Most Requested Static URLs' top='%d'>\n", DISPLAY_SIZE);
for (i = 0; i < DISPLAY_SIZE && TopHitStaticURLs[i].Requests != 0; i++) {
char* strPrint;
ULONGLONG AverageURLResponseTime = 0;
CHAR ReducedUrl[URL_NAME_COLUMN_SIZE + 1];
if (TopHitStaticURLs[i].Requests != 0) {
AverageURLResponseTime = TopHitStaticURLs[i].TotalResponseTime / TopHitStaticURLs[i].Requests;
}
RemoveCtrlCharA(TopHitStaticURLs[i].URL, strlen(TopHitStaticURLs[i].URL));
if (strlen(TopHitStaticURLs[i].URL) > URL_NAME_COLUMN_SIZE) {
ReduceStringA(ReducedUrl, URL_NAME_COLUMN_SIZE + 1, TopHitStaticURLs[i].URL);
strPrint = ReducedUrl;
}else{
strPrint = TopHitStaticURLs[i].URL;
}
fprintf(procFile,
"<url name='%s'>"
"<site_id>%d</site_id>"
"<rate>%1.3f</rate>"
"<cache_hit>%1.1f</cache_hit>"
"<response_time>%1.1f</response_time>"
"</url>\n",
strPrint,
TopHitStaticURLs[i].SiteId,
(Duration ? ((double)TopHitStaticURLs[i].Requests / (double)Duration) : 0.0),
TopHitStaticURLs[i].Requests ? ((double)TopHitStaticURLs[i].Hits / (double)TopHitStaticURLs[i].Requests * 100.0) : 0.0,
((double)AverageURLResponseTime) / 10000.0);
}
fprintf(procFile, "</table>\n");
fprintf(procFile, "<table title='Slowest URLs' top='%d'>\n", DISPLAY_SIZE );
for (i = 0; i < DISPLAY_SIZE && TopSlowURLs[i].Requests != 0; i++) {
char* strPrint;
ULONGLONG AverageURLResponseTime = 0;
CHAR ReducedUrl[URL_NAME_COLUMN_SIZE + 1];
if (TopSlowURLs[i].Requests != 0) {
AverageURLResponseTime = TopSlowURLs[i].TotalResponseTime / TopSlowURLs[i].Requests;
}
RemoveCtrlCharA(TopSlowURLs[i].URL, strlen(TopSlowURLs[i].URL));
if (strlen(TopSlowURLs[i].URL) > URL_NAME_COLUMN_SIZE) {
ReduceStringA(ReducedUrl, URL_NAME_COLUMN_SIZE + 1, TopSlowURLs[i].URL);
strPrint = ReducedUrl;
}else{
strPrint = TopSlowURLs[i].URL;
}
fprintf(procFile,
"<url name='%s'>"
"<site_id>%d</site_id>"
"<rate>%1.3f</rate>"
"<cache_hit>%1.1f</cache_hit>"
"<response_time>%1.1f</response_time>"
"</url>\n",
strPrint,
TopSlowURLs[i].SiteId,
(Duration ? ((double)TopSlowURLs[i].Requests / (double)Duration) : 0.0),
TopSlowURLs[i].Requests ? ((double)TopSlowURLs[i].Hits / (double)TopSlowURLs[i].Requests * 100.0) : 0.0,
((double)AverageURLResponseTime) / 10000.0);
}
fprintf(procFile, "</table>\n" );
if (PrintCPUUsage) {
fprintf(procFile, "<table title='URLs with the Most CPU Usage' top='%d'>\n", DISPLAY_SIZE);
for (i = 0; i < DISPLAY_SIZE && TopConsumingURLs[i].Requests != 0; i++) {
char* strPrint;
CHAR ReducedUrl[URL_NAME_COLUMN_SIZE + 1];
RemoveCtrlCharA(TopConsumingURLs[i].URL, strlen(TopConsumingURLs[i].URL));
if (strlen(TopConsumingURLs[i].URL) > URL_NAME_COLUMN_SIZE) {
ReduceStringA(ReducedUrl, URL_NAME_COLUMN_SIZE + 1, TopConsumingURLs[i].URL);
strPrint = ReducedUrl;
}else{
strPrint = TopConsumingURLs[i].URL;
}
fprintf(procFile,
"<url name='%s'>"
"<site_id>%d</site_id>"
"<rate>%1.3f</rate>"
"<cpu>%1.2f</cpu>"
"</url>\n",
strPrint,
TopConsumingURLs[i].SiteId,
(Duration ? ((double)TopConsumingURLs[i].Requests / (double)Duration) : 0.0),
MilDuration ? ((((double)TopConsumingURLs[i].KCPUTime + (double)TopConsumingURLs[i].UCPUTime) / (double)MilDuration) * 100.0) : 0.0);
}
fprintf(procFile, "</table>\n" );
}
fprintf(procFile, "<table title='URLs with the Most Bytes Sent' top='%d'>\n", DISPLAY_SIZE);
for (i = 0; i < DISPLAY_SIZE && TopBytesURLs[i].Requests != 0; i++) {
char* strPrint;
CHAR ReducedUrl[URL_NAME_COLUMN_SIZE + 1];
RemoveCtrlCharA(TopBytesURLs[i].URL, strlen(TopBytesURLs[i].URL));
if (strlen(TopBytesURLs[i].URL) > URL_NAME_COLUMN_SIZE) {
ReduceStringA(ReducedUrl, URL_NAME_COLUMN_SIZE + 1, TopBytesURLs[i].URL);
strPrint = ReducedUrl;
}else{
strPrint = TopBytesURLs[i].URL;
}
fprintf(procFile,
"<url name='%s'>"
"<site_id>%d</site_id>"
"<rate>%1.3f</rate>"
"<cache_hit>%1.1f</cache_hit>"
"<bytes_sent_per_sec>%d</bytes_sent_per_sec>"
"</url>\n",
strPrint,
TopBytesURLs[i].SiteId,
(Duration ? ((double)TopBytesURLs[i].Requests / (double)Duration) : 0.0),
TopBytesURLs[i].Requests ? ((double)TopBytesURLs[i].Hits / (double)TopBytesURLs[i].Requests * 100.0) : 0.0,
Duration ? TopBytesURLs[i].BytesSent/ Duration : 0);
}
fprintf(procFile, "</table>\n" );
for (i = 0; i < DISPLAY_SIZE; i++) {
if (TopHitURLs[i].Requests != 0 && TopHitURLs[i].URL != NULL) {
free(TopHitURLs[i].URL);
}
if (TopHitStaticURLs[i].Requests != 0 && TopHitStaticURLs[i].URL != NULL) {
free(TopHitStaticURLs[i].URL);
}
if (TopSlowURLs[i].Requests != 0 && TopSlowURLs[i].URL != NULL) {
free(TopSlowURLs[i].URL);
}
if (TopConsumingURLs[i].Requests != 0 && TopConsumingURLs[i].URL != NULL) {
free(TopConsumingURLs[i].URL);
}
if (TopBytesURLs[i].Requests != 0 && TopBytesURLs[i].URL != NULL) {
free(TopBytesURLs[i].URL);
}
}
RtlZeroMemory(TopHitClients, sizeof(CLIENT_RECORD) * DISPLAY_SIZE);
RtlZeroMemory(TopSlowClients, sizeof(CLIENT_RECORD) * DISPLAY_SIZE);
pClient = GetHeadClientRecord();
while (pClient != NULL) {
ULONGLONG AverageClientResponseTime = 0;
ULONG Found;
CLIENT_RECORD tmpClient1, tmpClient2;
if (pClient->Requests != 0) {
RtlZeroMemory(&tmpClient1, sizeof(CLIENT_RECORD));
RtlZeroMemory(&tmpClient2, sizeof(CLIENT_RECORD));
Found = FALSE;
for (i = 0; i < DISPLAY_SIZE; i++) {
if (Found && tmpClient1.Requests != 0) {
RtlCopyMemory(&tmpClient2, &TopHitClients[i], sizeof(CLIENT_RECORD));
RtlCopyMemory(&TopHitClients[i], &tmpClient1, sizeof(CLIENT_RECORD));
RtlCopyMemory(&tmpClient1, &tmpClient2, sizeof(CLIENT_RECORD));
}
else if (!Found) {
if (TopHitClients[i].Requests == 0) {
RtlCopyMemory(&TopHitClients[i], pClient, sizeof(CLIENT_RECORD));
Found = TRUE;
}
else if (pClient->Requests > TopHitClients[i].Requests) {
RtlCopyMemory(&tmpClient1, &TopHitClients[i], sizeof(CLIENT_RECORD));
RtlCopyMemory(&TopHitClients[i], pClient, sizeof(CLIENT_RECORD));
Found = TRUE;
}
}
}
AverageClientResponseTime = pClient->TotalResponseTime / pClient->Requests;
RtlZeroMemory(&tmpClient1, sizeof(CLIENT_RECORD));
RtlZeroMemory(&tmpClient2, sizeof(CLIENT_RECORD));
Found = FALSE;
for (i = 0; i < DISPLAY_SIZE; i++) {
if (Found && tmpClient1.Requests != 0) {
RtlCopyMemory(&tmpClient2, &TopSlowClients[i], sizeof(CLIENT_RECORD));
RtlCopyMemory(&TopSlowClients[i], &tmpClient1, sizeof(CLIENT_RECORD));
RtlCopyMemory(&tmpClient1, &tmpClient2, sizeof(CLIENT_RECORD));
}
else if (!Found) {
if (TopSlowClients[i].Requests == 0) {
RtlCopyMemory(&TopSlowClients[i], pClient, sizeof(CLIENT_RECORD));
Found = TRUE;
}
else if (AverageClientResponseTime > (TopSlowClients[i].TotalResponseTime / TopSlowClients[i].Requests)) {
RtlCopyMemory(&tmpClient1, &TopSlowClients[i], sizeof(CLIENT_RECORD));
RtlCopyMemory(&TopSlowClients[i], pClient, sizeof(CLIENT_RECORD));
Found = TRUE;
}
}
}
}
free(pClient);
pClient = GetHeadClientRecord();
}
fprintf(procFile, "<table title='Clients with the Most Requests' top='%d'>\n", DISPLAY_SIZE);
for (i = 0; i < DISPLAY_SIZE && TopHitClients[i].Requests != 0; i++) {
ULONGLONG AverageClientResponseTime = 0;
CHAR ipAddrBuffer[MAX_ADDRESS_LENGTH];
PCHAR pszA = &ipAddrBuffer[0];
if (TopHitClients[i].Requests != 0) {
AverageClientResponseTime = TopHitClients[i].TotalResponseTime / TopHitClients[i].Requests;
}
DecodeIpAddressA(TopHitClients[i].IpAddrType,
&TopHitClients[i].IpAddrV4,
&TopHitClients[i].IpAddrV6[0],
pszA);
fprintf(procFile,
"<client ip='%s'>"
"<rate>%1.3f</rate>"
"<cache_hit>%1.1f</cache_hit>"
"<response_time>%I64u</response_time>"
"</client>\n",
ipAddrBuffer,
(Duration ? ((double)TopHitClients[i].Requests / (double)Duration) : 0.0),
TopHitClients[i].Requests ? ((double)TopHitClients[i].Hits / (double)TopHitClients[i].Requests * 100.0) : 0.0,
AverageClientResponseTime / 10000);
}
fprintf(procFile, "</table>\n" );
fprintf(procFile, "<table title='Clients with the Slowest Responses' top='%d'>", DISPLAY_SIZE);
for (i = 0; i < DISPLAY_SIZE && TopSlowClients[i].Requests != 0; i++) {
ULONGLONG AverageClientResponseTime = 0;
CHAR ipAddrBuffer[MAX_ADDRESS_LENGTH];
PCHAR pszA = &ipAddrBuffer[0];
if (TopSlowClients[i].Requests != 0) {
AverageClientResponseTime = TopSlowClients[i].TotalResponseTime / TopSlowClients[i].Requests;
}
DecodeIpAddressA(TopHitClients[i].IpAddrType,
&TopHitClients[i].IpAddrV4,
&TopHitClients[i].IpAddrV6[0],
pszA);
fprintf(procFile,
"<client ip='%s'>"
"<rate>%1.3f</rate>"
"<cache_hit>%1.1f</cache_hit>"
"<response_time>%I64u</response_time>"
"</client>\n",
ipAddrBuffer,
(Duration ? ((double)TopSlowClients[i].Requests / (double)Duration) : 0.0),
TopSlowClients[i].Requests ? ((double)TopSlowClients[i].Hits / (double)TopSlowClients[i].Requests * 100.0) : 0.0,
AverageClientResponseTime / 10000);
}
fprintf(procFile, "</table>" );
RtlZeroMemory(TopHitSites, sizeof(SITE_RECORD) * DISPLAY_SIZE);
RtlZeroMemory(TopSlowSites, sizeof(SITE_RECORD) * DISPLAY_SIZE);
RtlZeroMemory(TopConsumingSites, sizeof(SITE_RECORD) * DISPLAY_SIZE);
RtlZeroMemory(TopBytesSites, sizeof(SITE_RECORD) * DISPLAY_SIZE);
pSite = GetHeadSiteRecord();
while (pSite != NULL) {
ULONGLONG AverageSiteResponseTime = 0;
ULONG Found;
SITE_RECORD tmpSite1, tmpSite2;
if (pSite->Requests != 0) {
RtlZeroMemory(&tmpSite1, sizeof(SITE_RECORD));
RtlZeroMemory(&tmpSite2, sizeof(SITE_RECORD));
Found = FALSE;
for (i = 0; i < DISPLAY_SIZE; i++) {
if (Found && tmpSite1.Requests != 0) {
RtlCopyMemory(&tmpSite2, &TopHitSites[i], sizeof(SITE_RECORD));
RtlCopyMemory(&TopHitSites[i], &tmpSite1, sizeof(SITE_RECORD));
RtlCopyMemory(&tmpSite1, &tmpSite2, sizeof(SITE_RECORD));
}
else if (!Found) {
if (TopHitSites[i].Requests == 0) {
RtlCopyMemory(&TopHitSites[i], pSite, sizeof(SITE_RECORD));
Found = TRUE;
}
else if (pSite->Requests > TopHitSites[i].Requests) {
RtlCopyMemory(&tmpSite1, &TopHitSites[i], sizeof(SITE_RECORD));
RtlCopyMemory(&TopHitSites[i], pSite, sizeof(SITE_RECORD));
Found = TRUE;
}
}
}
AverageSiteResponseTime = pSite->TotalResponseTime / pSite->Requests;
RtlZeroMemory(&tmpSite1, sizeof(SITE_RECORD));
RtlZeroMemory(&tmpSite2, sizeof(SITE_RECORD));
Found = FALSE;
for (i = 0; i < DISPLAY_SIZE; i++) {
if (Found && tmpSite1.Requests != 0) {
RtlCopyMemory(&tmpSite2, &TopSlowSites[i], sizeof(SITE_RECORD));
RtlCopyMemory(&TopSlowSites[i], &tmpSite1, sizeof(SITE_RECORD));
RtlCopyMemory(&tmpSite1, &tmpSite2, sizeof(SITE_RECORD));
}
else if (!Found) {
if (TopSlowSites[i].Requests == 0) {
RtlCopyMemory(&TopSlowSites[i], pSite, sizeof(SITE_RECORD));
Found = TRUE;
}
else if (AverageSiteResponseTime > (TopSlowSites[i].TotalResponseTime / TopSlowSites[i].Requests)) {
RtlCopyMemory(&tmpSite1, &TopSlowSites[i], sizeof(SITE_RECORD));
RtlCopyMemory(&TopSlowSites[i], pSite, sizeof(SITE_RECORD));
Found = TRUE;
}
}
}
RtlZeroMemory(&tmpSite1, sizeof(SITE_RECORD));
RtlZeroMemory(&tmpSite2, sizeof(SITE_RECORD));
Found = FALSE;
for (i = 0; i < DISPLAY_SIZE; i++) {
if (Found && tmpSite1.Requests != 0) {
RtlCopyMemory(&tmpSite2, &TopConsumingSites[i], sizeof(SITE_RECORD));
RtlCopyMemory(&TopConsumingSites[i], &tmpSite1, sizeof(SITE_RECORD));
RtlCopyMemory(&tmpSite1, &tmpSite2, sizeof(SITE_RECORD));
}
else if (!Found) {
if (TopConsumingSites[i].Requests == 0) {
RtlCopyMemory(&TopConsumingSites[i], pSite, sizeof(SITE_RECORD));
Found = TRUE;
}
else if ((pSite->KCPUTime + pSite->UCPUTime) > (TopConsumingSites[i].KCPUTime + TopConsumingSites[i].UCPUTime)) {
RtlCopyMemory(&tmpSite1, &TopConsumingSites[i], sizeof(SITE_RECORD));
RtlCopyMemory(&TopConsumingSites[i], pSite, sizeof(SITE_RECORD));
Found = TRUE;
}
}
}
RtlZeroMemory(&tmpSite1, sizeof(SITE_RECORD));
RtlZeroMemory(&tmpSite2, sizeof(SITE_RECORD));
Found = FALSE;
for (i = 0; i < DISPLAY_SIZE; i++) {
if (Found && tmpSite1.Requests != 0) {
RtlCopyMemory(&tmpSite2, &TopBytesSites[i], sizeof(SITE_RECORD));
RtlCopyMemory(&TopBytesSites[i], &tmpSite1, sizeof(SITE_RECORD));
RtlCopyMemory(&tmpSite1, &tmpSite2, sizeof(SITE_RECORD));
}
else if (!Found) {
if (TopBytesSites[i].Requests == 0) {
RtlCopyMemory(&TopBytesSites[i], pSite, sizeof(SITE_RECORD));
Found = TRUE;
}
else if (pSite->BytesSent > TopBytesSites[i].BytesSent) {
RtlCopyMemory(&tmpSite1, &TopBytesSites[i], sizeof(SITE_RECORD));
RtlCopyMemory(&TopBytesSites[i], pSite, sizeof(SITE_RECORD));
Found = TRUE;
}
}
}
}
free(pSite);
pSite = GetHeadSiteRecord();
}
fprintf(procFile, "<table title='Sites with the Most Requests' top='%d'>\n", DISPLAY_SIZE);
for (i = 0; i < DISPLAY_SIZE && TopHitSites[i].Requests != 0; i++) {
ULONGLONG AverageSiteResponseTime = 0;
if (TopHitSites[i].Requests != 0) {
AverageSiteResponseTime = TopHitSites[i].TotalResponseTime / TopHitSites[i].Requests;
}
fprintf(procFile,
"<site id='%d'>"
"<rate>%1.3f</rate>"
"<response_time>%I64u</response_time>"
"<cache_hits>%1.1f</cache_hits>"
"<static>%1.1f</static>"
"<cgi>%1.1f</cgi>"
"<asp>%1.1f</asp>"
"</site>\n",
TopHitSites[i].SiteId,
(Duration ? ((double)TopHitSites[i].Requests / (double)Duration) : 0.0),
AverageSiteResponseTime / 10000,
TopHitSites[i].Requests ? ((double)TopHitSites[i].Hits / (double)TopHitSites[i].Requests * 100.0) : 0.0,
TopHitSites[i].Requests ? ((double)TopHitSites[i].FileRequests / (double)TopHitSites[i].Requests * 100.0) : 0.0,
TopHitSites[i].Requests ? ((double)TopHitSites[i].CGIRequests / (double)TopHitSites[i].Requests * 100.0) : 0.0,
TopHitSites[i].Requests ? ((double)TopHitSites[i].ISAPIRequests / (double)TopHitSites[i].Requests * 100.0) : 0.0);
}
fprintf(procFile, "</table>\n" );
fprintf(procFile, "<table title='Sites with the Slowest Responses' top='%d'>\n", DISPLAY_SIZE);
for (i = 0; i < DISPLAY_SIZE && TopSlowSites[i].Requests != 0; i++) {
ULONGLONG AverageSiteResponseTime = 0;
if (TopSlowSites[i].Requests != 0) {
AverageSiteResponseTime = TopSlowSites[i].TotalResponseTime / TopSlowSites[i].Requests;
}
fprintf(procFile,
"<site id='%d'>"
"<rate>%1.3f</rate>"
"<response_time>%I64u</response_time>"
"<cache_hits>%1.1f</cache_hits>"
"<static>%1.1f</static>"
"<cgi>%1.1f</cgi>"
"<asp>%1.1f</asp>"
"</site>\n",
TopSlowSites[i].SiteId,
(Duration ? ((double)TopSlowSites[i].Requests / (double)Duration) : 0.0),
AverageSiteResponseTime / 10000,
TopSlowSites[i].Requests ? ((double)TopSlowSites[i].Hits / (double)TopSlowSites[i].Requests * 100.0) : 0.0,
TopSlowSites[i].Requests ? ((double)TopSlowSites[i].FileRequests / (double)TopSlowSites[i].Requests * 100.0) : 0.0,
TopSlowSites[i].Requests ? ((double)TopSlowSites[i].CGIRequests / (double)TopSlowSites[i].Requests * 100.0) : 0.0,
TopSlowSites[i].Requests ? ((double)TopSlowSites[i].ISAPIRequests / (double)TopSlowSites[i].Requests * 100.0) : 0.0);
}
fprintf(procFile, "</table>\n" );
if (PrintCPUUsage) {
fprintf(procFile, "<table title='Sites with the Most CPU Time Usage' top='%d'>\n", DISPLAY_SIZE );
for (i = 0; i < DISPLAY_SIZE && TopConsumingSites[i].Requests != 0; i++) {
ULONGLONG AverageSiteResponseTime = 0;
if (TopConsumingSites[i].Requests != 0) {
AverageSiteResponseTime = TopConsumingSites[i].TotalResponseTime / TopConsumingSites[i].Requests;
}
fprintf(procFile,
"<site id='%d'>"
"<rate>%1.3f</rate>"
"<cache_hits>%1.1f</cache_hits>"
"<response_time>%I64u</response_time>"
"<cpu_time units='ms'>%d</cpu_time>"
"<cpu>%1.1f</cpu>"
"</site>\n",
TopConsumingSites[i].SiteId,
(Duration ? ((double)TopConsumingSites[i].Requests / (double)Duration) : 0.0),
TopConsumingSites[i].Requests ? ((double)TopConsumingSites[i].Hits / (double)TopConsumingSites[i].Requests * 100.0) : 0.0,
AverageSiteResponseTime / 10000,
TopConsumingSites[i].Requests ? (TopConsumingSites[i].KCPUTime + TopConsumingSites[i].UCPUTime) / TopConsumingSites[i].Requests : 0,
MilDuration ? ((((double)TopConsumingSites[i].KCPUTime + (double)TopConsumingSites[i].UCPUTime) / (double)MilDuration) * 100.0) : 0.0);
}
fprintf(procFile, "</table>\n" );
}
fprintf(procFile, "<table title='Sites with the Most Bytes Sent' top='%d'>\n", DISPLAY_SIZE );
for (i = 0; i < DISPLAY_SIZE && TopBytesSites[i].Requests != 0; i++) {
fprintf(procFile,
"<site id='%d'>"
"<rate>%1.3f</rate>"
"<bytes>%d</bytes>"
"<cache_hits>%1.1f</cache_hits>"
"<static>%1.1f</static>"
"<cgi>%1.1f</cgi>"
"<asp>%1.1f</asp>"
"</site>\n",
TopBytesSites[i].SiteId,
(Duration ? ((double)TopBytesSites[i].Requests / (double)Duration) : 0.0),
Duration ? TopBytesSites[i].BytesSent / Duration : 0,
TopBytesSites[i].Requests ? ((double)TopBytesSites[i].Hits / (double)TopBytesSites[i].Requests * 100.0) : 0.0,
TopBytesSites[i].Requests ? ((double)TopBytesSites[i].FileRequests / (double)TopBytesSites[i].Requests * 100.0) : 0.0,
TopBytesSites[i].Requests ? ((double)TopBytesSites[i].CGIRequests / (double)TopBytesSites[i].Requests * 100.0) : 0.0,
TopBytesSites[i].Requests ? ((double)TopBytesSites[i].ISAPIRequests / (double)TopBytesSites[i].Requests * 100.0) : 0.0);
}
fprintf(procFile, "</table>\n" );
free(IIS);
}
void
WriteSummary()
{
FILE* SummaryFile;
PLIST_ENTRY Head, Next;
PMOF_INFO pMofInfo;
ULONG i;
WCHAR buffer[MAXSTR];
FILETIME StTm, StlTm;
LARGE_INTEGER LargeTmp;
SYSTEMTIME tmf, emf;
BOOL bResult;
if( NULL == TraceContext->SummaryFileName ){
return;
}
if( 0 == TotalEventCount ){
return;
}
SummaryFile = _wfopen( TraceContext->SummaryFileName, L"w" );
if (SummaryFile == NULL){
return;
}
fwprintf(SummaryFile,L"Files Processed:\n");
for (i=0; i<TraceContext->LogFileCount; i++) {
fwprintf(SummaryFile,L"\t%s\n",TraceContext->LogFileName[i]);
}
LargeTmp.QuadPart = CurrentSystem.StartTime;
StTm.dwHighDateTime = LargeTmp.HighPart;
StTm.dwLowDateTime = LargeTmp.LowPart;
FileTimeToLocalFileTime(&StTm, &StlTm);
bResult = FileTimeToSystemTime (
&StlTm,
&tmf
);
if( ! bResult || tmf.wMonth > 12 ){
ZeroMemory( &tmf, sizeof(SYSTEMTIME) );
buffer[0] = '\0';
}else{
GetDateFormatW( LOCALE_USER_DEFAULT, DATE_LONGDATE, &tmf, NULL, buffer, MAXSTR );
}
fwprintf(SummaryFile,
L"Total Buffers Processed %d\n"
L"Total Events Processed %d\n"
L"Total Events Lost %d\n"
L"Start Time %ws\n",
TotalBuffersRead,
TotalEventCount,
TotalEventsLost,
buffer );
LargeTmp.QuadPart = CurrentSystem.EndTime;
StTm.dwHighDateTime = LargeTmp.HighPart;
StTm.dwLowDateTime = LargeTmp.LowPart;
FileTimeToLocalFileTime(&StTm, &StlTm);
bResult = FileTimeToSystemTime (
&StlTm,
&emf
);
if( ! bResult || tmf.wMonth > 12 ){
ZeroMemory( &tmf, sizeof(SYSTEMTIME) );
buffer[0] = '\0';
}else{
GetDateFormatW( LOCALE_USER_DEFAULT, DATE_LONGDATE, &emf, NULL, buffer, MAXSTR );
}
ElapseTime = CurrentSystem.EndTime - CurrentSystem.StartTime;
fwprintf(SummaryFile,
L"End Time %ws\n"
L"Elapsed Time %I64d sec\n",
buffer,
(ElapseTime / 10000000) );
fwprintf(SummaryFile,
L"+-------------------------------------------------------------------------------------+\n"
L"|%10s %-20s %-10s %-38s|\n"
L"+-------------------------------------------------------------------------------------+\n",
L"Event Count",
L"Event Name",
L"Event Type",
L"Guid"
);
Head = &CurrentSystem.EventListHead;
Next = Head->Flink;
while (Head != Next) {
WCHAR wstr[MAXSTR];
PWCHAR str;
WCHAR s[MAX_GUID_STRING_SIZE];
PLIST_ENTRY vHead, vNext;
PMOF_VERSION pMofVersion;
RtlZeroMemory(&wstr[0], MAXSTR*sizeof(WCHAR));
pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
Next = Next->Flink;
if (pMofInfo->EventCount > 0) {
str = CpdiGuidToString(&s[0], MAX_GUID_STRING_SIZE, (LPGUID)&pMofInfo->Guid);
if( pMofInfo->strDescription != NULL ){
StringCchCopyW( wstr, MAXSTR, pMofInfo->strDescription );
}
//
// Get event count by type from MOF_VERSION structure
//
vHead = &pMofInfo->VersionHeader;
vNext = vHead->Flink;
while (vHead != vNext) {
pMofVersion = CONTAINING_RECORD(vNext, MOF_VERSION, Entry);
vNext = vNext->Flink;
if (pMofVersion->EventCountByType != 0) {
fwprintf(SummaryFile,L"| %10d %-20s %-10s %38s|\n",
pMofVersion->EventCountByType,
wstr,
pMofVersion->strType ? pMofVersion->strType : GUID_TYPE_DEFAULT,
str);
}
}
}
}
fwprintf(SummaryFile,
L"+-------------------------------------------------------------------------------------+\n"
);
fclose( SummaryFile );
}