Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4060 lines
152 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. report.c
  5. Abstract:
  6. Manipulation routines for cpdata structures.
  7. Author:
  8. Melur Raghuraman (mraghu) 03-Oct-1997
  9. Environment:
  10. Revision History:
  11. Corey Morgan (coreym) 04-June-2002
  12. Reformatted report output to XML.
  13. --*/
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include "cpdata.h"
  17. #include "tracectr.h"
  18. #include <ntverp.h>
  19. #include "item.h"
  20. #define MODULE_STRING_SIZE 256
  21. #define FILE_NAME_COLUMN_SIZE 80
  22. #define URL_NAME_COLUMN_SIZE 79
  23. #define MAX_GUID_STRING_SIZE 64
  24. #define DISPLAY_SIZE 10
  25. extern PTRACE_CONTEXT_BLOCK TraceContext;
  26. extern ULONG TotalEventsLost;
  27. extern ULONG TotalEventCount;
  28. extern ULONG TimerResolution;
  29. extern __int64 ElapseTime;
  30. extern ULONG TotalBuffersRead;
  31. extern BOOLEAN XPorHigher;
  32. extern FARPROC EtwpIpv4ToStringA;
  33. extern FARPROC EtwpIpv4ToStringW;
  34. extern FARPROC EtwpIpv6ToStringA;
  35. extern FARPROC EtwpIpv6ToStringW;
  36. static FILE* procFile;
  37. static void PrintDiskTotals();
  38. static void PrintProcessCpuTime();
  39. static void PrintProcessData();
  40. static void PrintPerThreadPerDiskTable();
  41. static void WriteTransactionStatistics();
  42. static void WriteTransactionCPUTime();
  43. static void PrintProcessSubDataInclusive();
  44. static void PrintProcessSubDataExclusive();
  45. void TransInclusive(
  46. PLIST_ENTRY TrHead,
  47. ULONG level
  48. );
  49. static void ReportHotFileInfo();
  50. static void ReportPrintJobInfo();
  51. PIIS_REPORT_RECORD IIS = NULL;
  52. ULONG RequestsDiscarded = 0;
  53. ULONG SendErrorRequests = 0;
  54. void ProcessIisRequest(HTTP_REQUEST_RECORD *pReq);
  55. static void ReportIisEvents();
  56. extern GUID PrintJobGuid;
  57. extern GUID UlGuid;
  58. #ifdef DBG
  59. BOOLEAN TracectrDbgEnabled = FALSE;
  60. #endif
  61. PWCHAR CpdiGuidToString(
  62. PWCHAR s,
  63. ULONG len,
  64. LPGUID piid
  65. );
  66. PCHAR RemoveCtrlCharA(
  67. PCHAR String,
  68. ULONG NumChars
  69. );
  70. PCHAR ReduceStringA(
  71. PCHAR OutString,
  72. ULONG NumChars,
  73. PCHAR LongString
  74. );
  75. PWCHAR ReduceStringW(
  76. PWCHAR OutString,
  77. ULONG NumChars,
  78. PWCHAR LongString
  79. );
  80. ULONG ReportFlags = 0;
  81. void DecodeIpAddressA(
  82. USHORT AddrType,
  83. PULONG IpAddrV4,
  84. PUSHORT IpAddrV6,
  85. PCHAR pszA
  86. )
  87. {
  88. if (AddrType == TDI_ADDRESS_TYPE_IP) {
  89. if (XPorHigher && EtwpIpv4ToStringA != NULL) {
  90. struct in_addr IPv4Addr
  91. = * (struct in_addr UNALIGNED*) IpAddrV4;
  92. pszA = (PCHAR)(*EtwpIpv4ToStringA)(&IPv4Addr, pszA);
  93. *pszA = '\0';
  94. }
  95. else {
  96. StringCchCopyA(pszA, MAX_ADDRESS_LENGTH, "Undecodable IP Address");
  97. }
  98. }
  99. else if (AddrType == TDI_ADDRESS_TYPE_IP6) {
  100. if (XPorHigher && EtwpIpv6ToStringA != NULL) {
  101. struct in6_addr IPv6Addr
  102. = * (struct in6_addr UNALIGNED*) IpAddrV6;
  103. pszA = (PCHAR)(*EtwpIpv6ToStringA)(&IPv6Addr, pszA);
  104. *pszA = '\0';
  105. }
  106. else {
  107. StringCchCopyA(pszA, MAX_ADDRESS_LENGTH, "Undecodable IP Address");
  108. }
  109. }
  110. else {
  111. StringCchCopyA(pszA, MAX_ADDRESS_LENGTH, "Unknown IP Address Type");
  112. }
  113. }
  114. void DecodeIpAddressW(
  115. USHORT AddrType,
  116. PULONG IpAddrV4,
  117. PUSHORT IpAddrV6,
  118. PWCHAR pszW
  119. )
  120. {
  121. if (AddrType == TDI_ADDRESS_TYPE_IP) {
  122. if (XPorHigher && EtwpIpv4ToStringW != NULL) {
  123. struct in_addr IPv4Addr
  124. = * (struct in_addr UNALIGNED*) IpAddrV4;
  125. pszW = (PWCHAR)(*EtwpIpv4ToStringW)(&IPv4Addr, pszW);
  126. *pszW = L'\0';
  127. }
  128. else {
  129. StringCchCopyW(pszW, MAX_ADDRESS_LENGTH, L"Undecodable IP Address");
  130. }
  131. }
  132. else if (AddrType == TDI_ADDRESS_TYPE_IP6) {
  133. if (XPorHigher && EtwpIpv6ToStringW != NULL) {
  134. struct in6_addr IPv6Addr
  135. = * (struct in6_addr UNALIGNED*) IpAddrV6;
  136. pszW = (PWCHAR)(*EtwpIpv6ToStringW)(&IPv6Addr, pszW);
  137. *pszW = L'\0';
  138. }
  139. else {
  140. StringCchCopyW(pszW, MAX_ADDRESS_LENGTH, L"Undecodable IP Address");
  141. }
  142. }
  143. else {
  144. StringCchCopyW(pszW, MAX_ADDRESS_LENGTH, L"Unknown IP Address Type");
  145. }
  146. }
  147. // URLs may contain non-printable characters. This routine removes them.
  148. PCHAR RemoveCtrlCharA(
  149. PCHAR String,
  150. ULONG NumChars
  151. )
  152. {
  153. ULONG i;
  154. for (i = 0 ; i <= NumChars && String[i] != '\0'; i++) {
  155. if ( isprint(String[i]) == 0 ||
  156. String[i] == '\t' ||
  157. String[i] == '\b' ||
  158. String[i] == '\n' ||
  159. String[i] == '\'' ||
  160. String[i] == '\"') {
  161. String[i] = '?';
  162. }
  163. }
  164. return String;
  165. }
  166. PCHAR ReduceStringA(
  167. PCHAR OutString,
  168. ULONG NumChars,
  169. PCHAR LongString
  170. )
  171. {
  172. ULONG Size;
  173. ULONG i;
  174. if (LongString == NULL) {
  175. return NULL;
  176. }
  177. // We assume here that LongString is not junk.
  178. Size = strlen(LongString);
  179. if (OutString == NULL) {
  180. return NULL;
  181. }
  182. RtlZeroMemory(OutString, NumChars);
  183. // This function is only useful when the length of LongString exceeds NumChars.
  184. // However, it still works when the length of LongString is smaller than NumChars.
  185. if (Size <= (NumChars - 1)) {
  186. StringCchCopyA(OutString, NumChars, LongString);
  187. return OutString;
  188. }
  189. i = Size - 1;
  190. while (LongString[i] != '\\' && LongString[i] != '/' && i > 0) {
  191. i--;
  192. }
  193. if (i == 0) { // there's no /s or \s. Just truncate.
  194. StringCchCopyA(OutString, NumChars, LongString);
  195. return OutString;
  196. }
  197. else {
  198. if ((Size - i) >= NumChars - 3) { // only name exceeds given chars.
  199. StringCchPrintfA(OutString, NumChars, "..%s", &LongString[1]);
  200. return OutString;
  201. }
  202. else {
  203. ULONG SpareChars = (NumChars - 3) - (Size - i);
  204. StringCchCopyA(OutString, SpareChars + 1, LongString);
  205. StringCchCatA(OutString, NumChars + 1, "..");
  206. StringCchCatA(OutString, NumChars + 1, &LongString[i]);
  207. return OutString;
  208. }
  209. }
  210. }
  211. PWCHAR ReduceStringW(
  212. PWCHAR OutString,
  213. ULONG NumChars,
  214. PWCHAR LongString
  215. )
  216. {
  217. ULONG Size;
  218. ULONG i;
  219. if (LongString == NULL) {
  220. return NULL;
  221. }
  222. // We assume here that LongString is not junk.
  223. Size = wcslen(LongString);
  224. if (OutString == NULL) {
  225. return NULL;
  226. }
  227. RtlZeroMemory(OutString, NumChars * sizeof(WCHAR));
  228. // This function is only useful when the length of LongString exceeds NumChars.
  229. // However, it still works when the length of LongString is smaller than NumChars.
  230. if (Size <= (NumChars - 1)) {
  231. StringCchCopyW(OutString, NumChars, LongString);
  232. return OutString;
  233. }
  234. i = Size - 1;
  235. while (LongString[i] != L'\\' && LongString[i] != L'/' && i > 0) {
  236. i--;
  237. }
  238. if (i == 0) { // there's no /s or \s. Just truncate.
  239. StringCchCopyW(OutString, NumChars, LongString);
  240. return OutString;
  241. }
  242. else {
  243. if ((Size - i) >= NumChars - 3) { // only name exceeds given chars.
  244. StringCchPrintfW(OutString, NumChars, L"..%ws", &LongString[1]);
  245. return OutString;
  246. }
  247. else {
  248. ULONG SpareChars = (NumChars - 3) - (Size - i);
  249. StringCchCopyW(OutString, SpareChars + 1, LongString);
  250. StringCchCatW(OutString, NumChars + 1, L"..");
  251. StringCchCatW(OutString, NumChars + 1, &LongString[i]);
  252. return OutString;
  253. }
  254. }
  255. }
  256. void CollapseTree(
  257. PLIST_ENTRY OldTree,
  258. PLIST_ENTRY NewTree,
  259. BOOL flat
  260. )
  261. {
  262. PLIST_ENTRY OldNext;
  263. PTRANS_RECORD pTrans;
  264. PTRANS_RECORD pNewTrans;
  265. OldNext = OldTree->Flink;
  266. while (OldNext != OldTree)
  267. {
  268. pTrans = CONTAINING_RECORD(OldNext, TRANS_RECORD, Entry);
  269. OldNext = OldNext->Flink;
  270. pNewTrans = FindTransByList(NewTree, pTrans->pGuid, 0);
  271. if( NULL != pNewTrans ){
  272. pNewTrans->KCpu += pTrans->KCpu;
  273. pNewTrans->UCpu += pTrans->UCpu;
  274. pNewTrans->RefCount += pTrans->RefCount;
  275. pNewTrans->RefCount1 += pTrans->RefCount1;
  276. if (flat)
  277. {
  278. CollapseTree(&pTrans->SubTransListHead, NewTree, TRUE );
  279. }
  280. else
  281. {
  282. CollapseTree(& pTrans->SubTransListHead,
  283. & pNewTrans->SubTransListHead,
  284. FALSE);
  285. }
  286. }
  287. }
  288. }
  289. #define BARLEN 70
  290. char*
  291. TimeWindowBar(
  292. char* buffer,
  293. ULONGLONG min,
  294. ULONGLONG max
  295. )
  296. {
  297. double unit;
  298. ULONGLONG duration;
  299. int pre, bar, count, index;
  300. if(buffer == NULL){
  301. return NULL;
  302. }
  303. duration = ((CurrentSystem.EndTime - CurrentSystem.StartTime) / 10000000);
  304. unit = (double)BARLEN/(ULONG)duration;
  305. pre = (int)((ULONG)((min - CurrentSystem.StartTime)/10000000) * unit);
  306. bar = (int)((ULONG)((max - min)/10000000) * unit);
  307. buffer[0] = '\0';
  308. count = 0;
  309. index = 0;
  310. while(count < pre) {
  311. buffer[index] = ' ';
  312. index++;
  313. count++;
  314. }
  315. buffer[index] = '|';
  316. index++;
  317. count = 0;
  318. while(count < bar) {
  319. buffer[index] = '_';
  320. index++;
  321. count++;
  322. }
  323. buffer[index] = '|';
  324. buffer[index + 1] = '\0';
  325. return buffer;
  326. }
  327. char*
  328. GetDateString( char* buffer, size_t cchBuffer, ULONGLONG llTime )
  329. {
  330. FILETIME ft, lft;
  331. SYSTEMTIME st;
  332. LARGE_INTEGER LargeTmp;
  333. BOOL bResult;
  334. HRESULT hr;
  335. WCHAR wDate[128];
  336. CHAR aDate[128];
  337. LargeTmp.QuadPart = llTime;
  338. ft.dwHighDateTime = LargeTmp.HighPart;
  339. ft.dwLowDateTime = LargeTmp.LowPart;
  340. FileTimeToLocalFileTime(&ft, &lft);
  341. bResult = FileTimeToSystemTime (
  342. &lft,
  343. &st
  344. );
  345. if( ! bResult || st.wMonth > 12 ){
  346. buffer[0] = '\0';
  347. }else{
  348. GetDateFormatW(
  349. LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, wDate, 128 );
  350. WideCharToMultiByte(
  351. CP_UTF8, 0, wDate, wcslen(wDate)+1, aDate, 128, NULL, NULL );
  352. hr = StringCchCopyA( buffer, cchBuffer, aDate );
  353. hr = StringCchCatA( buffer, cchBuffer, " " );
  354. GetTimeFormatW(
  355. LOCALE_USER_DEFAULT, 0, &st, NULL, wDate, 128 );
  356. WideCharToMultiByte(
  357. CP_UTF8, 0, wDate, wcslen(wDate)+1, aDate, 128, NULL, NULL );
  358. hr = StringCchCatA( buffer, cchBuffer, aDate );
  359. }
  360. return buffer;
  361. }
  362. void
  363. WriteProc(
  364. LPWSTR ProcFileName,
  365. ULONG flags,
  366. PVOID pUserContext
  367. )
  368. {
  369. ULONGLONG duration;
  370. PLIST_ENTRY Next, Head;
  371. PPROCESS_FILE_RECORD pFileRec;
  372. char buffer[MAXSTR];
  373. BOOL bResult;
  374. ReportFlags = flags;
  375. procFile = _wfopen(ProcFileName, L"w");
  376. if (procFile == NULL)
  377. return;
  378. fprintf( procFile, "<?xml version=\"1.0\" encoding='UTF-8'?>\n" );
  379. if( !(TraceContext->Flags & TRACE_TRANSFORM_XML ) && TraceContext->XSLDocName != NULL ){
  380. fprintf( procFile, "<?xml-stylesheet type=\"text/xsl\" href=\"%ws\"?>\n", TraceContext->XSLDocName );
  381. }
  382. fprintf( procFile, "<report>\n<header>\n" );
  383. fprintf( procFile, "<version>%d</version>\n", VER_PRODUCTBUILD );
  384. fprintf( procFile, "<type>%s</type>\n", ( ReportFlags & TRACE_TOTALS_REPORT ) ? "Total" : "Default" );
  385. fprintf( procFile, "<build>%d</build>\n",CurrentSystem.BuildNumber );
  386. fprintf( procFile, "<processors>%d</processors>\n", CurrentSystem.NumberOfProcessors );
  387. if (CurrentSystem.CpuSpeed > 0) {
  388. fprintf(procFile,
  389. "<cpu_speed units='MHz'>%d</cpu_speed>\n",
  390. CurrentSystem.CpuSpeed
  391. );
  392. } else {
  393. fprintf(procFile, "<cpu_speed/>\n" );
  394. }
  395. if (CurrentSystem.MemorySize > 0) {
  396. fprintf(procFile,
  397. "<memory units='Mb'>%d</memory>\n",
  398. CurrentSystem.MemorySize
  399. );
  400. } else {
  401. fprintf(procFile, "<memory/>\n" );
  402. }
  403. if (CurrentSystem.ComputerName != NULL) {
  404. fprintf(procFile,
  405. "<computer_name>%ws</computer_name>\n",
  406. CurrentSystem.ComputerName
  407. );
  408. } else {
  409. fprintf(procFile, "<computer_name/>\n" );
  410. }
  411. fprintf( procFile, "<start>%s</start>\n",
  412. GetDateString( buffer, MAXSTR, CurrentSystem.StartTime ) );
  413. fprintf( procFile, "<end>%s</end>\n",
  414. GetDateString( buffer, MAXSTR, CurrentSystem.EndTime) );
  415. duration = (CurrentSystem.EndTime - CurrentSystem.StartTime) / 10000000;
  416. fprintf( procFile, "<duration>%I64u</duration>\n",duration );
  417. Head = &CurrentSystem.ProcessFileListHead;
  418. Next = Head->Flink;
  419. while (Next != Head) {
  420. pFileRec = CONTAINING_RECORD( Next, PROCESS_FILE_RECORD, Entry );
  421. Next = Next->Flink;
  422. fprintf( procFile, "<trace name=\"%ws\">\n", pFileRec->TraceName ? pFileRec->TraceName : L"-" );
  423. fprintf( procFile, "<file>%ws</file>\n", pFileRec->FileName ? pFileRec->FileName : L"-" );
  424. if (pFileRec->StartTime == 0){
  425. pFileRec->StartTime = CurrentSystem.StartTime;
  426. }
  427. if (pFileRec->EndTime == 0){
  428. pFileRec->EndTime = CurrentSystem.EndTime;
  429. }
  430. fprintf( procFile, "<start>%s</start>\n",
  431. GetDateString( buffer, MAXSTR, pFileRec->StartTime ) );
  432. duration = (pFileRec->EndTime - pFileRec->StartTime) / 10000000;
  433. fprintf( procFile,
  434. "<end>%s</end>\n"
  435. "<duration>%I64u</duration>\n",
  436. GetDateString( buffer, MAXSTR, pFileRec->EndTime ),
  437. duration );
  438. fprintf( procFile,
  439. "<duration_window xml:space='preserve'>%s</duration_window>\n",
  440. TimeWindowBar(buffer, pFileRec->StartTime, pFileRec->EndTime) );
  441. fprintf( procFile, "</trace>\n" );
  442. }
  443. fprintf( procFile, "</header>\n" );
  444. if (flags & (TRACE_BASIC_REPORT|TRACE_TOTALS_REPORT)){
  445. PMOF_INFO pMofInfo;
  446. WriteTransactionStatistics();
  447. WriteTransactionCPUTime();
  448. pMofInfo = GetMofInfoHead ((LPCGUID)&PrintJobGuid);
  449. if ( pMofInfo != NULL ){
  450. if (pMofInfo->EventCount > 0) {
  451. ReportPrintJobInfo();
  452. }
  453. }
  454. pMofInfo = GetMofInfoHead ((LPCGUID)&UlGuid);
  455. if ( pMofInfo != NULL ){
  456. if (pMofInfo->EventCount > 0) {
  457. ReportIisEvents();
  458. }
  459. }
  460. // PrintProcessData() must be run before others to set the process
  461. // time from the added thread times
  462. PrintProcessData();
  463. PrintProcessSubDataExclusive();
  464. PrintProcessSubDataInclusive();
  465. /*
  466. PrintProcessCpuTime();
  467. */
  468. PrintDiskTotals();
  469. PrintPerThreadPerDiskTable();
  470. pMofInfo = GetMofInfoHead ((LPCGUID)&FileIoGuid);
  471. if ( pMofInfo != NULL ) {
  472. pMofInfo = GetMofInfoHead ((LPCGUID)&DiskIoGuid);
  473. if ( pMofInfo != NULL ) {
  474. ReportHotFileInfo();
  475. }
  476. }
  477. }
  478. fprintf( procFile, "</report>\n" );
  479. fclose(procFile);
  480. }
  481. static void
  482. PrintDiskTotals()
  483. {
  484. // Print the Disk Table.
  485. PTDISK_RECORD pDisk;
  486. PLIST_ENTRY Next, Head;
  487. ULONG rio, wio;
  488. ULONGLONG Duration = (ULONGLONG)((CurrentSystem.EndTime - CurrentSystem.StartTime) / 10000000);
  489. if (Duration == 0) {
  490. return;
  491. }
  492. Head = &CurrentSystem.GlobalDiskListHead;
  493. Next = Head->Flink;
  494. if( Next == Head ){
  495. return;
  496. }
  497. fprintf(procFile, "<table title='Disk Totals'>\n" );
  498. Head = &CurrentSystem.GlobalDiskListHead;
  499. Next = Head->Flink;
  500. while (Next != Head) {
  501. pDisk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
  502. rio = pDisk->ReadCount + pDisk->HPF;
  503. wio = pDisk->WriteCount;
  504. fprintf( procFile, "<disk number=\"%d\">\n", pDisk->DiskNumber );
  505. fprintf( procFile, "<read_rate>%1.3f</read_rate>\n", (double)rio / ((double)Duration) );
  506. fprintf( procFile, "<read_size>%d</read_size>\n", (rio == 0) ? 0 : (pDisk->ReadSize + pDisk->HPFSize) / rio );
  507. fprintf( procFile, "<write_rate>%1.3f</write_rate>\n", (double)wio / ((double)Duration));
  508. fprintf( procFile, "<write_size>%d</write_size>\n", (wio == 0) ? 0 : pDisk->WriteSize / wio );
  509. fprintf( procFile, "</disk>\n" );
  510. Next = Next->Flink;
  511. }
  512. fprintf(procFile, "</table>\n" );
  513. }
  514. void TotalTransChildren(
  515. PLIST_ENTRY Head,
  516. ULONG *Kernel,
  517. ULONG *User,
  518. LONG level )
  519. {
  520. PTRANS_RECORD pTrans;
  521. PLIST_ENTRY Next;
  522. Next = Head->Flink;
  523. while( Next != Head ){
  524. pTrans = CONTAINING_RECORD( Next, TRANS_RECORD, Entry );
  525. Next = Next->Flink;
  526. TotalTransChildren( &pTrans->SubTransListHead, Kernel, User, level+1 );
  527. *Kernel += pTrans->KCpu;
  528. *User += pTrans->UCpu;
  529. }
  530. }
  531. void PrintTransList( PLIST_ENTRY TrHead, LONG level )
  532. {
  533. PTRANS_RECORD pTrans;
  534. PMOF_INFO pMofInfo;
  535. ULONG Kernel;
  536. ULONG User;
  537. WCHAR str[MAXSTR];
  538. WCHAR buffer[MAXSTR];
  539. PLIST_ENTRY TrNext = TrHead->Flink;
  540. while( TrNext != TrHead ){
  541. int count = 0;
  542. pTrans = CONTAINING_RECORD( TrNext, TRANS_RECORD, Entry );
  543. TrNext = TrNext->Flink;
  544. Kernel = pTrans->KCpu;
  545. User = pTrans->UCpu;
  546. pMofInfo = GetMofInfoHead( pTrans->pGuid);
  547. if (pMofInfo == NULL) {
  548. return;
  549. }
  550. StringCchCopyW ( buffer,
  551. MAXSTR,
  552. ( pMofInfo->strDescription ?
  553. pMofInfo->strDescription :
  554. CpdiGuidToString( str, MAXSTR, &pMofInfo->Guid ) ));
  555. TotalTransChildren( &pTrans->SubTransListHead, &Kernel, &User, 0 );
  556. fprintf( procFile, "<transaction name=\"%ws\">\n", buffer );
  557. fprintf( procFile, "<count>%d</count>\n", pTrans->RefCount );
  558. fprintf( procFile, "<kernel>%d</kernel>\n", Kernel );
  559. fprintf( procFile, "<user>%d</user>\n", User );
  560. fprintf( procFile, "\n<transaction>\n" );
  561. if( level <= MAX_TRANS_LEVEL ){
  562. PrintTransList( &pTrans->SubTransListHead, level+1 );
  563. }
  564. }
  565. }
  566. static void PrintProcessCpuTime()
  567. {
  568. PTHREAD_RECORD pThread;
  569. PPROCESS_RECORD pProcess;
  570. ULONGLONG lLifeTime;
  571. ULONG TotalUserTime = 0;
  572. ULONG TotalKernelTime = 0;
  573. ULONG TotalCPUTime = 0;
  574. PLIST_ENTRY Next, Head;
  575. PLIST_ENTRY ThNext, ThHead;
  576. BOOL titled;
  577. ULONG usedThreadCount;
  578. ULONG ThreadCount;
  579. ULONG ProcessUTime;
  580. ULONG ProcessKTime;
  581. ULONG ThreadKCPU;
  582. ULONG ThreadUCPU;
  583. Head = &CurrentSystem.ProcessListHead;
  584. Next = Head->Flink;
  585. if( Head == Next ){
  586. return;
  587. }
  588. fprintf( procFile, "<table title='Process/Thread CPU Time Statistics'>\n" );
  589. Head = &CurrentSystem.ProcessListHead;
  590. Next = Head->Flink;
  591. while (Next != Head) {
  592. pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  593. lLifeTime = CalculateProcessLifeTime(pProcess);
  594. fprintf(procFile,
  595. "<process name=\"%ws\">"
  596. "<pid>0x%04X</pid>"
  597. "<kernel>%d</kernel>"
  598. "<user>%d</user>"
  599. "<read>%d</read>"
  600. "<read_size>%1.2f</read_size>"
  601. "<write>%d</write>"
  602. "<write_size>%1.2f</write_size>"
  603. "<send>%d</send>"
  604. "<send_size>%1.2f</send_size>"
  605. "<recv>%5d</recv>"
  606. "<recv_size>%.2f</recv_size>"
  607. "<duation>%I64u</duation>\n",
  608. (pProcess->ImageName) ? pProcess->ImageName : L"Idle",
  609. pProcess->PID,
  610. CalculateProcessKCPU(pProcess),
  611. CalculateProcessUCPU(pProcess),
  612. pProcess->ReadIO + pProcess->HPF,
  613. (pProcess->ReadIO + pProcess->HPF) ?
  614. (double)(pProcess->ReadIOSize + pProcess->HPFSize)/
  615. (double)(pProcess->ReadIO + pProcess->HPF) : 0,
  616. pProcess->WriteIO,
  617. pProcess->WriteIO ? (double)pProcess->WriteIOSize/(double)pProcess->WriteIO : 0,
  618. pProcess->SendCount,
  619. pProcess->SendCount ?
  620. (double)(pProcess->SendSize / 1024)/(double)pProcess->SendCount : 0,
  621. pProcess->RecvCount,
  622. pProcess->RecvCount ?
  623. (double)(pProcess->RecvSize / 1024) / (double)pProcess->RecvCount : 0,
  624. (lLifeTime / 10000000 )
  625. );
  626. ThHead = &pProcess->ThreadListHead;
  627. ThNext = ThHead->Flink;
  628. titled = FALSE;
  629. usedThreadCount = 0;
  630. ThreadCount = 0;
  631. ProcessUTime = 0;
  632. ProcessKTime = 0;
  633. while (ThNext != ThHead) {
  634. pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
  635. ThreadKCPU = (pThread->KCPUEnd - pThread->KCPUStart)
  636. * CurrentSystem.TimerResolution;
  637. ThreadUCPU = (pThread->UCPUEnd - pThread->UCPUStart)
  638. * CurrentSystem.TimerResolution;
  639. if( pThread->ReadIO
  640. || pThread->WriteIO
  641. || ThreadKCPU
  642. || ThreadUCPU
  643. || pThread->SendCount
  644. || pThread->RecvCount
  645. || pThread->HPF ){
  646. fprintf(procFile,
  647. "<thread>"
  648. "<tid>0x%04I64X</tid>"
  649. "<kernel>%d</kernel>"
  650. "<user>%d</user>"
  651. "<read>%d</read>"
  652. "<read_size>%1.2f</read_size>"
  653. "<write>%d</write>"
  654. "<write_size>%1.2f</write_size>"
  655. "<send>%d</send>"
  656. "<send_size>%1.2f</send_size>"
  657. "<recv>%d</recv>"
  658. "<recv_size>%1.2f</recv_size>"
  659. "<duration>%I64u</duration>"
  660. "</thread>\n",
  661. pThread->TID,
  662. ThreadKCPU,
  663. ThreadUCPU,
  664. pThread->ReadIO + pThread->HPF,
  665. pThread->ReadIO + pThread->HPF ?
  666. (double)(pThread->ReadIOSize + pThread->HPFSize)/
  667. (double)(pThread->ReadIO + pThread->HPF) : 0,
  668. pThread->WriteIO,
  669. pThread->WriteIO ? (double)pThread->WriteIOSize/
  670. (double)pThread->WriteIO : 0,
  671. pThread->SendCount,
  672. pThread->SendCount ?
  673. (double)(pThread->SendSize / 1024)/(double)pThread->SendCount : 0,
  674. pThread->RecvCount,
  675. pThread->RecvCount ?
  676. (double)(pThread->RecvSize / 1024)/(double)pThread->RecvCount : 0,
  677. ((pThread->TimeEnd - pThread->TimeStart) / 10000000)
  678. );
  679. }
  680. PrintTransList( &pThread->TransListHead, 0 );
  681. TotalUserTime += ThreadUCPU;
  682. TotalKernelTime += ThreadKCPU;
  683. TotalCPUTime += ThreadKCPU + ThreadUCPU;
  684. ThNext = ThNext->Flink;
  685. }
  686. fprintf( procFile, "</process>\n" );
  687. Next = Next->Flink;
  688. }
  689. fprintf( procFile, "</table>\n" );
  690. }
  691. static void PrintProcessData()
  692. {
  693. PTHREAD_RECORD pThread;
  694. PPROCESS_RECORD pProcess;
  695. PTRANS_RECORD pTrans;
  696. PLIST_ENTRY Next, Head;
  697. PLIST_ENTRY ThNext, ThHead;
  698. PLIST_ENTRY TrNext, TrHead;
  699. ULONG usedThreadCount;
  700. ULONG ThreadCount;
  701. ULONG TotalusedThreadCount = 0;
  702. ULONG TotalThreadCount = 0;
  703. ULONG ThreadUTime;
  704. ULONG ThreadKTime;
  705. ULONG ThreadUTimeTrans;
  706. ULONG ThreadKTimeTrans;
  707. ULONG ThreadUTimeNoTrans;
  708. ULONG ThreadKTimeNoTrans;
  709. ULONG CountThreadNoTrans;
  710. ULONG TotalKCPUThreadNoTrans;
  711. ULONG TotalUCPUThreadNoTrans;
  712. double PercentThreadNoTrans;
  713. ULONG CountThreadTrans;
  714. ULONG TotalKCPUThreadTrans;
  715. ULONG TotalUCPUThreadTrans;
  716. double PercentThreadTrans;
  717. ULONG TransUTime;
  718. ULONG TransKTime;
  719. ULONG Processors;
  720. ULONG TotalKThread = 0;
  721. ULONG TotalUThread = 0;
  722. ULONG TotalKTrans = 0;
  723. ULONG TotalUTrans = 0;
  724. double PerTotal = 0.0;
  725. double IdlePercent = 0.0;
  726. double percent;
  727. double percentTrans;
  728. double lDuration;
  729. Head = &CurrentSystem.ProcessListHead;
  730. Next = Head->Flink;
  731. if( Head == Next ){
  732. return;
  733. }
  734. Processors = CurrentSystem.NumberOfProcessors ? CurrentSystem.NumberOfProcessors : 1;
  735. lDuration = ((double)((LONGLONG)(CurrentSystem.EndTime - CurrentSystem.StartTime)))
  736. / 10000000.00;
  737. fprintf( procFile, "<table title='Image Statistics'>\n" );
  738. Head = &CurrentSystem.ProcessListHead;
  739. Next = Head->Flink;
  740. while (Next != Head) {
  741. pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  742. ThHead = &pProcess->ThreadListHead;
  743. ThNext = ThHead->Flink;
  744. usedThreadCount = 0;
  745. ThreadCount = 0;
  746. ThreadUTime = 0;
  747. ThreadKTime = 0;
  748. ThreadUTimeTrans = 0;
  749. ThreadKTimeTrans = 0;
  750. ThreadUTimeNoTrans = 0;
  751. ThreadKTimeNoTrans = 0;
  752. TransKTime = 0;
  753. TransUTime = 0;
  754. percent = 0;
  755. CountThreadNoTrans = 0;
  756. TotalKCPUThreadNoTrans = 0;
  757. TotalUCPUThreadNoTrans = 0;
  758. CountThreadTrans = 0;
  759. TotalKCPUThreadTrans = 0;
  760. TotalUCPUThreadTrans = 0;
  761. while (ThNext != ThHead) {
  762. LIST_ENTRY NewTransList;
  763. pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
  764. if( pThread->ReadIO
  765. || pThread->WriteIO
  766. || pThread->KCPUEnd > pThread->KCPUStart
  767. || pThread->UCPUEnd > pThread->UCPUStart
  768. || pThread->SendCount
  769. || pThread->RecvCount
  770. || pThread->HPF )
  771. {
  772. usedThreadCount++;
  773. TotalusedThreadCount++;
  774. }
  775. ThreadCount++;
  776. TotalThreadCount++;
  777. ThreadUTime += (pThread->UCPUEnd - pThread->UCPUStart)
  778. * CurrentSystem.TimerResolution;
  779. ThreadKTime += (pThread->KCPUEnd - pThread->KCPUStart)
  780. * CurrentSystem.TimerResolution;
  781. ThreadKTimeTrans += pThread->KCPU_Trans
  782. * CurrentSystem.TimerResolution;
  783. ThreadUTimeTrans += pThread->UCPU_Trans
  784. * CurrentSystem.TimerResolution;
  785. ThreadKTimeNoTrans += pThread->KCPU_NoTrans
  786. * CurrentSystem.TimerResolution;
  787. ThreadUTimeNoTrans += pThread->UCPU_NoTrans
  788. * CurrentSystem.TimerResolution;
  789. if (pThread->KCPU_Trans + pThread->UCPU_Trans == 0)
  790. {
  791. CountThreadNoTrans ++;
  792. TotalKCPUThreadNoTrans += pThread->KCPU_NoTrans
  793. * CurrentSystem.TimerResolution;
  794. TotalUCPUThreadNoTrans += pThread->UCPU_NoTrans
  795. * CurrentSystem.TimerResolution;
  796. }
  797. else
  798. {
  799. CountThreadTrans ++;
  800. TotalKCPUThreadTrans += ( pThread->KCPU_Trans
  801. + pThread->KCPU_NoTrans)
  802. * CurrentSystem.TimerResolution;
  803. TotalUCPUThreadTrans += ( pThread->UCPU_Trans
  804. + pThread->UCPU_NoTrans)
  805. * CurrentSystem.TimerResolution;
  806. }
  807. InitializeListHead(& NewTransList);
  808. CollapseTree(& pThread->TransListHead, & NewTransList, TRUE);
  809. TrHead = & NewTransList;
  810. TrNext = TrHead->Flink;
  811. while( TrNext != TrHead ){
  812. pTrans = CONTAINING_RECORD( TrNext, TRANS_RECORD, Entry );
  813. TransUTime += pTrans->UCpu;
  814. TransKTime += pTrans->KCpu;
  815. TrNext = TrNext->Flink;
  816. }
  817. DeleteTransList(& NewTransList, 0);
  818. ThNext = ThNext->Flink;
  819. }
  820. TotalKThread += ThreadKTime;
  821. TotalUThread += ThreadUTime;
  822. TotalKTrans += TransKTime;
  823. TotalUTrans += TransUTime;
  824. percent = (((ThreadKTime + ThreadUTime + 0.0)/lDuration)/1000.0) * 100.0;
  825. if (ThreadKTime + ThreadUTime == 0)
  826. {
  827. percentTrans = 0.0;
  828. PercentThreadTrans = 0.0;
  829. PercentThreadNoTrans = 0.0;
  830. }
  831. else
  832. {
  833. percentTrans = ( (ThreadKTimeTrans + ThreadUTimeTrans + 0.0)
  834. / (ThreadKTime + ThreadUTime + 0.0))
  835. * 100.00;
  836. PercentThreadTrans = ((TotalKCPUThreadTrans + TotalUCPUThreadTrans + 0.0)
  837. / (ThreadKTime + ThreadUTime + 0.0)) * 100.00;
  838. PercentThreadNoTrans = ((TotalKCPUThreadNoTrans + TotalUCPUThreadNoTrans + 0.0)
  839. / (ThreadKTime + ThreadUTime + 0.0)) * 100.00;
  840. }
  841. PerTotal += percent;
  842. fprintf(procFile,
  843. "<image name=\"%ws\">"
  844. "<pid>0x%08X</pid>"
  845. "<threads>%d</threads>"
  846. "<used_threads>%d</used_threads>"
  847. "<process_kernel>%d</process_kernel>"
  848. "<process_user>%d</process_user>"
  849. "<transaction_kernel>%d</transaction_kernel>"
  850. "<transaction_user>%d</transaction_user>"
  851. "<cpu>%1.2f</cpu>"
  852. "</image>\n",
  853. (pProcess->ImageName) ? pProcess->ImageName : L"Idle",
  854. pProcess->PID,
  855. ThreadCount,
  856. usedThreadCount,
  857. ThreadKTime,
  858. ThreadUTime,
  859. ThreadKTimeTrans,
  860. ThreadUTimeTrans,
  861. (percent / Processors)
  862. );
  863. if(pProcess->PID == 0){
  864. IdlePercent += (percent / Processors );
  865. }
  866. Next = Next->Flink;
  867. }
  868. fprintf( procFile, "</table>\n" );
  869. }
  870. void TransInclusive(
  871. PLIST_ENTRY TrHead,
  872. ULONG level
  873. )
  874. {
  875. ULONG Kernel, User;
  876. PLIST_ENTRY TrNext = TrHead->Flink;
  877. PMOF_INFO pMofInfo;
  878. PTRANS_RECORD pTrans;
  879. WCHAR buffer[MAXSTR];
  880. WCHAR str[MAXSTR];
  881. while( TrNext != TrHead ){
  882. ULONG count = 0;
  883. pTrans = CONTAINING_RECORD( TrNext, TRANS_RECORD, Entry );
  884. TrNext = TrNext->Flink;
  885. pMofInfo = GetMofInfoHead( pTrans->pGuid);
  886. if (pMofInfo == NULL) {
  887. return;
  888. }
  889. Kernel = pTrans->KCpu;
  890. User = pTrans->UCpu;
  891. TotalTransChildren( &pTrans->SubTransListHead, &Kernel, &User, 0 );
  892. StringCchCopyW ( buffer,
  893. MAXSTR,
  894. ( pMofInfo->strDescription ?
  895. pMofInfo->strDescription :
  896. CpdiGuidToString( str, MAXSTR, &pMofInfo->Guid ) ));
  897. fprintf(procFile,
  898. "<transaction level='%d' name=\"%ws\">"
  899. "<count>%d</count>"
  900. "<kernel>%d</kernel>"
  901. "<user>%d</user>",
  902. level,
  903. buffer,
  904. pTrans->RefCount,
  905. Kernel,
  906. User
  907. );
  908. TransInclusive( &pTrans->SubTransListHead, level+1 );
  909. fprintf(procFile, "</transaction>\n" );
  910. }
  911. }
  912. static void PrintProcessSubDataInclusive()
  913. {
  914. PPROCESS_RECORD pProcess;
  915. PTHREAD_RECORD pThread;
  916. PLIST_ENTRY Next, Head;
  917. PLIST_ENTRY TrNext;
  918. PLIST_ENTRY ThNext, ThHead;
  919. LIST_ENTRY NewHead;
  920. BOOL bTable = FALSE;
  921. Head = &CurrentSystem.ProcessListHead;
  922. Next = Head->Flink;
  923. while (Next != Head && !bTable ) {
  924. pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  925. Next = Next->Flink;
  926. if( pProcess->PID == 0 ){
  927. continue;
  928. }
  929. // Total up all the threads into one list
  930. InitializeListHead( &NewHead );
  931. ThHead = &pProcess->ThreadListHead;
  932. ThNext = ThHead->Flink;
  933. while( ThNext != ThHead ){
  934. pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
  935. ThNext = ThNext->Flink;
  936. CollapseTree(&pThread->TransListHead, &NewHead, FALSE );
  937. }
  938. TrNext = NewHead.Flink;
  939. if( TrNext != &NewHead ){
  940. bTable = TRUE;
  941. }
  942. DeleteTransList( &NewHead, 0 );
  943. }
  944. if( !bTable ){
  945. return;
  946. }
  947. // Walk through the Process List and Print the report.
  948. fprintf(procFile, "<table title='Inclusive Transactions Per Process'>\n" );
  949. Head = &CurrentSystem.ProcessListHead;
  950. Next = Head->Flink;
  951. while (Next != Head) {
  952. pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  953. Next = Next->Flink;
  954. if( pProcess->PID == 0 ){
  955. continue;
  956. }
  957. // Total up all the threads into one list
  958. InitializeListHead( &NewHead );
  959. ThHead = &pProcess->ThreadListHead;
  960. ThNext = ThHead->Flink;
  961. while( ThNext != ThHead ){
  962. pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
  963. ThNext = ThNext->Flink;
  964. CollapseTree(&pThread->TransListHead, &NewHead, FALSE );
  965. }
  966. TrNext = NewHead.Flink;
  967. if( TrNext != &NewHead ){
  968. fprintf(procFile,
  969. "<process name=\"%ws\">"
  970. "<pid>0x%04X</pid>\n",
  971. (pProcess->ImageName) ? pProcess->ImageName : L"Idle",
  972. pProcess->PID
  973. );
  974. TransInclusive( &NewHead, 0 );
  975. fprintf( procFile, "</process>\n" );
  976. }
  977. DeleteTransList( &NewHead, 0 );
  978. }
  979. fprintf(procFile, "</table>\n" );
  980. }
  981. static void PrintProcessSubDataExclusive()
  982. {
  983. PPROCESS_RECORD pProcess;
  984. PTRANS_RECORD pTrans;
  985. PTHREAD_RECORD pThread;
  986. PLIST_ENTRY ThNext, ThHead;
  987. PMOF_INFO pMofInfo;
  988. PLIST_ENTRY Next, Head;
  989. PLIST_ENTRY TrNext;
  990. LIST_ENTRY NewHead;
  991. double percent, percentCPU, totalPerCPU;
  992. double processPart;
  993. double transPart;
  994. double totalPercent;
  995. double trans, KCPU, UCPU;
  996. WCHAR str[MAXSTR];
  997. double duration = ((double)((LONGLONG)(CurrentSystem.EndTime - CurrentSystem.StartTime))) / 10000000.00;
  998. BOOL bTable = FALSE;
  999. Head = &CurrentSystem.ProcessListHead;
  1000. Next = Head->Flink;
  1001. while (Next != Head && !bTable ) {
  1002. pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  1003. Next = Next->Flink;
  1004. if( pProcess->PID == 0 ){
  1005. continue;
  1006. }
  1007. InitializeListHead( &NewHead );
  1008. ThHead = &pProcess->ThreadListHead;
  1009. ThNext = ThHead->Flink;
  1010. while( ThNext != ThHead ){
  1011. pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
  1012. ThNext = ThNext->Flink;
  1013. CollapseTree(&pThread->TransListHead, &NewHead, TRUE );
  1014. }
  1015. TrNext = NewHead.Flink;
  1016. if( TrNext != &NewHead ){
  1017. bTable = TRUE;
  1018. }
  1019. DeleteTransList( &NewHead, 0 );
  1020. }
  1021. if( !bTable ){
  1022. return;
  1023. }
  1024. // Walk through the Process List and Print the report.
  1025. fprintf(procFile, "<table title='Exclusive Transactions Per Process'>\n" );
  1026. Head = &CurrentSystem.ProcessListHead;
  1027. Next = Head->Flink;
  1028. while (Next != Head) {
  1029. BOOL titled = FALSE;
  1030. pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  1031. Next = Next->Flink;
  1032. if( pProcess->PID == 0 ){
  1033. continue;
  1034. }
  1035. InitializeListHead( &NewHead );
  1036. ThHead = &pProcess->ThreadListHead;
  1037. ThNext = ThHead->Flink;
  1038. while( ThNext != ThHead ){
  1039. pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
  1040. ThNext = ThNext->Flink;
  1041. CollapseTree(&pThread->TransListHead, &NewHead, TRUE );
  1042. }
  1043. TrNext = NewHead.Flink;
  1044. totalPercent = 0.0;
  1045. totalPerCPU = 0.0;
  1046. while( TrNext != &NewHead ){
  1047. if(!titled){
  1048. fprintf(procFile,
  1049. "<process name=\"%ws\">"
  1050. "<pid>0x%04X</pid>\n",
  1051. (pProcess->ImageName) ? pProcess->ImageName : L"Idle",
  1052. pProcess->PID
  1053. );
  1054. titled = TRUE;
  1055. }
  1056. pTrans = CONTAINING_RECORD( TrNext, TRANS_RECORD, Entry );
  1057. TrNext = TrNext->Flink;
  1058. pMofInfo = GetMofInfoHead( pTrans->pGuid);
  1059. if (pMofInfo == NULL) {
  1060. return;
  1061. }
  1062. transPart = pTrans->UCpu + pTrans->KCpu;
  1063. processPart = CalculateProcessKCPU(pProcess)
  1064. + CalculateProcessUCPU(pProcess);
  1065. percentCPU = ((((double)pTrans->KCpu + (double)pTrans->UCpu ) / 10.0 ) / duration) / ((double) CurrentSystem.NumberOfProcessors);
  1066. totalPerCPU += percentCPU;
  1067. if(processPart)
  1068. percent = (transPart/processPart) * 100.0;
  1069. else
  1070. percent = 0;
  1071. totalPercent += percent;
  1072. if (!(ReportFlags & TRACE_TOTALS_REPORT) ){
  1073. if (pTrans->RefCount == 0 && pTrans->RefCount1 == 0)
  1074. KCPU = UCPU = 0.0;
  1075. else if (pTrans->RefCount == 0) {
  1076. KCPU = (double) pTrans->KCpu;
  1077. UCPU = (double) pTrans->UCpu;
  1078. }
  1079. else {
  1080. KCPU = (double) pTrans->KCpu / (double) pTrans->RefCount;
  1081. UCPU = (double) pTrans->UCpu / (double) pTrans->RefCount;
  1082. }
  1083. }
  1084. else{
  1085. KCPU = (double)pTrans->KCpu;
  1086. UCPU = (double)pTrans->UCpu;
  1087. }
  1088. trans = (double)pTrans->RefCount / duration;
  1089. fprintf(procFile,
  1090. "<transaction name=\"%ws\">"
  1091. "<count>%d</count>"
  1092. "<rate>%1.2f</rate>"
  1093. "<kernel>%1.0f</kernel>"
  1094. "<user>%1.0f</user>"
  1095. "<process_cpu>%1.2f</process_cpu>"
  1096. "<cpu>%1.2f</cpu>"
  1097. "</transaction>\n",
  1098. (pMofInfo->strDescription != NULL) ? pMofInfo->strDescription : CpdiGuidToString( str, MAXSTR, &pMofInfo->Guid ),
  1099. pTrans->RefCount,
  1100. trans,
  1101. KCPU,
  1102. UCPU,
  1103. percent,
  1104. percentCPU
  1105. );
  1106. }
  1107. if( titled ){
  1108. fprintf( procFile, "</process>\n" );
  1109. }
  1110. DeleteTransList( &NewHead, 0 );
  1111. }
  1112. fprintf(procFile, "</table>\n" );
  1113. }
  1114. static void PrintPerThreadPerDiskTable( )
  1115. {
  1116. PPROCESS_RECORD pProcess;
  1117. PTDISK_RECORD pDisk;
  1118. PLIST_ENTRY Next, Head;
  1119. PLIST_ENTRY GNext, GHead;
  1120. PLIST_ENTRY DiNext, DiHead;
  1121. ULONG rio, wio, DiskNumber;
  1122. BOOL bTable = FALSE;
  1123. ULONGLONG Duration = (ULONGLONG)((CurrentSystem.EndTime - CurrentSystem.StartTime) / 10000000);
  1124. if (Duration == 0) {
  1125. return;
  1126. }
  1127. // Walk through the Process List and Print the report.
  1128. GHead = &CurrentSystem.GlobalDiskListHead;
  1129. GNext = GHead->Flink;
  1130. while (GNext != GHead && !bTable) {
  1131. pDisk = CONTAINING_RECORD( GNext, TDISK_RECORD, Entry);
  1132. DiskNumber = pDisk->DiskNumber;
  1133. Head = &CurrentSystem.ProcessListHead;
  1134. Next = Head->Flink;
  1135. while (Next != Head) {
  1136. pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  1137. DiHead = &pProcess->DiskListHead;
  1138. DiNext = DiHead->Flink;
  1139. while (DiNext != DiHead && !bTable) {
  1140. pDisk = CONTAINING_RECORD( DiNext, TDISK_RECORD, Entry );
  1141. if (DiskNumber != pDisk->DiskNumber) {
  1142. DiNext = DiNext->Flink;
  1143. continue;
  1144. }else{
  1145. bTable = TRUE;
  1146. break;
  1147. }
  1148. }
  1149. Next = Next->Flink;
  1150. }
  1151. GNext = GNext->Flink;
  1152. }
  1153. if( !bTable ){
  1154. return;
  1155. }
  1156. GHead = &CurrentSystem.GlobalDiskListHead;
  1157. GNext = GHead->Flink;
  1158. while (GNext != GHead) {
  1159. pDisk = CONTAINING_RECORD( GNext, TDISK_RECORD, Entry);
  1160. DiskNumber = pDisk->DiskNumber;
  1161. fprintf( procFile, "<table title='Disk' number='%d'>\n", DiskNumber );
  1162. Head = &CurrentSystem.ProcessListHead;
  1163. Next = Head->Flink;
  1164. while (Next != Head) {
  1165. pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  1166. DiHead = &pProcess->DiskListHead;
  1167. DiNext = DiHead->Flink;
  1168. while (DiNext != DiHead) {
  1169. pDisk = CONTAINING_RECORD( DiNext, TDISK_RECORD, Entry );
  1170. if (DiskNumber != pDisk->DiskNumber) {
  1171. DiNext = DiNext->Flink;
  1172. continue;
  1173. }
  1174. rio = pDisk->ReadCount + pDisk->HPF;
  1175. wio = pDisk->WriteCount;
  1176. fprintf(procFile,
  1177. "<image name='%ws'>"
  1178. "<pid>0x%08X</pid>"
  1179. "<authority>%ws</authority>"
  1180. "<read_rate>%1.3f</read_rate>"
  1181. "<read_size>%d</read_size>"
  1182. "<write_rate>%1.3f</write_rate>"
  1183. "<write_size>%d</write_size>"
  1184. "</image>\n",
  1185. (pProcess->ImageName) ? pProcess->ImageName : L"-",
  1186. pProcess->PID,
  1187. (pProcess->UserName) ? pProcess->UserName : L"-",
  1188. (double)rio / ((double)Duration),
  1189. (rio == 0) ? 0 : (pDisk->ReadSize + pDisk->HPFSize) / rio,
  1190. (double)wio / ((double)Duration),
  1191. (wio == 0) ? 0 : pDisk->WriteSize / wio
  1192. );
  1193. DiNext = DiNext->Flink;
  1194. }
  1195. Next = Next->Flink;
  1196. }
  1197. fprintf( procFile, "</table>\n" );
  1198. GNext = GNext->Flink;
  1199. }
  1200. }
  1201. static void WriteTransactionStatistics()
  1202. {
  1203. PLIST_ENTRY Head, Next;
  1204. PLIST_ENTRY Dhead, DNext;
  1205. ULONG trans;
  1206. double KCPU, UCPU, PerCpu;
  1207. double RIO, WIO, Send, Recv;
  1208. PMOF_INFO pMofInfo;
  1209. PMOF_DATA pMofData;
  1210. double AvgRT;
  1211. double TransRate;
  1212. WCHAR str[MAXSTR];
  1213. double duration = ((double)((LONGLONG)(CurrentSystem.EndTime - CurrentSystem.StartTime)))
  1214. / 10000000.00;
  1215. BOOL bTable = FALSE;
  1216. Head = &CurrentSystem.EventListHead;
  1217. Next = Head->Flink;
  1218. while (Head != Next && !bTable ) {
  1219. pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
  1220. Dhead = &pMofInfo->DataListHead;
  1221. DNext = Dhead->Flink;
  1222. while(DNext!=Dhead){
  1223. pMofData = CONTAINING_RECORD(DNext, MOF_DATA, Entry);
  1224. trans = pMofData->CompleteCount;
  1225. if (trans > 0) {
  1226. bTable = TRUE;
  1227. break;
  1228. }
  1229. DNext = DNext->Flink;
  1230. }
  1231. Next = Next->Flink;
  1232. }
  1233. if( !bTable ){
  1234. return;
  1235. }
  1236. fprintf( procFile, "<table title='Transaction Statistics'>\n" );
  1237. Head = &CurrentSystem.EventListHead;
  1238. Next = Head->Flink;
  1239. while (Head != Next) {
  1240. pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
  1241. Dhead = &pMofInfo->DataListHead;
  1242. DNext = Dhead->Flink;
  1243. while(DNext!=Dhead){
  1244. pMofData = CONTAINING_RECORD(DNext, MOF_DATA, Entry);
  1245. trans = pMofData->CompleteCount;
  1246. if (trans > 0) {
  1247. UCPU = pMofData->UserCPU;
  1248. KCPU = pMofData->KernelCPU;
  1249. PerCpu = (((UCPU + KCPU)/1000.0)/duration) * 100.0;
  1250. UCPU /= trans;
  1251. KCPU /= trans;
  1252. if(CurrentSystem.NumberOfProcessors)
  1253. PerCpu/=CurrentSystem.NumberOfProcessors;
  1254. if( ReportFlags & TRACE_TOTALS_REPORT ){
  1255. RIO = pMofData->ReadCount;
  1256. WIO = pMofData->WriteCount;
  1257. Send = pMofData->SendCount;
  1258. Recv = pMofData->RecvCount;
  1259. }else{
  1260. RIO = pMofData->ReadCount / trans;
  1261. WIO = pMofData->WriteCount / trans;
  1262. Send = pMofData->SendCount / trans;
  1263. Recv = pMofData->RecvCount / trans;
  1264. }
  1265. AvgRT = (double)pMofData->TotalResponseTime;
  1266. AvgRT /= trans;
  1267. TransRate = ( (float)trans / duration );
  1268. // TODO: NOT /trans if TRACE_TOTALS_REPORT
  1269. fprintf(procFile,
  1270. "<transaction name='%ws'>"
  1271. "<count>%d</count>"
  1272. "<response_time>%1.0f</response_time>"
  1273. "<rate>%1.2f</rate>"
  1274. "<cpu>%1.2f</cpu>"
  1275. "<disk_read_per_trans>%1.2f</disk_read_per_trans>"
  1276. "<disk_write_per_trans>%1.2f</disk_write_per_trans>"
  1277. "<tcp_send_per_trans>%1.2f</tcp_send_per_trans>"
  1278. "<tcp_recv_per_trans>%1.2f</tcp_recv_per_trans>"
  1279. "</transaction>\n",
  1280. (pMofInfo->strDescription) ? pMofInfo->strDescription : CpdiGuidToString( str, MAXSTR, &pMofInfo->Guid ),
  1281. pMofData->CompleteCount,
  1282. AvgRT,
  1283. TransRate,
  1284. PerCpu,
  1285. RIO,
  1286. WIO,
  1287. Send,
  1288. Recv
  1289. );
  1290. }
  1291. DNext = DNext->Flink;
  1292. }
  1293. Next = Next->Flink;
  1294. }
  1295. fprintf(procFile, "</table>" );
  1296. }
  1297. static void WriteTransactionCPUTime()
  1298. {
  1299. PLIST_ENTRY Head, Next;
  1300. PLIST_ENTRY Dhead, DNext;
  1301. double KCPU, UCPU;
  1302. PMOF_INFO pMofInfo;
  1303. PMOF_DATA pMofData;
  1304. double trans;
  1305. double PerCpu;
  1306. WCHAR str[MAXSTR];
  1307. double duration = ((double)((LONGLONG)(CurrentSystem.EndTime - CurrentSystem.StartTime))) / 10000000.00;
  1308. BOOL bTable = FALSE;
  1309. Head = &CurrentSystem.EventListHead;
  1310. Next = Head->Flink;
  1311. while (Head != Next && !bTable ) {
  1312. pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
  1313. Dhead = &pMofInfo->DataListHead;
  1314. DNext = Dhead->Flink;
  1315. while(DNext!=Dhead){
  1316. pMofData = CONTAINING_RECORD(DNext, MOF_DATA, Entry);
  1317. trans = (double)pMofData->CompleteCount;
  1318. if (trans > 0) {
  1319. bTable = TRUE;
  1320. break;
  1321. }
  1322. DNext = DNext->Flink;
  1323. }
  1324. Next = Next->Flink;
  1325. }
  1326. if( !bTable ){
  1327. return;
  1328. }
  1329. fprintf( procFile, "<table title='Transaction CPU Utilization'>\n" );
  1330. Head = &CurrentSystem.EventListHead;
  1331. Next = Head->Flink;
  1332. while (Head != Next) {
  1333. pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
  1334. Dhead = &pMofInfo->DataListHead;
  1335. DNext = Dhead->Flink;
  1336. while(DNext!=Dhead){
  1337. pMofData = CONTAINING_RECORD(DNext, MOF_DATA, Entry);
  1338. trans = (double)pMofData->CompleteCount;
  1339. if (trans > 0) {
  1340. UCPU = pMofData->UserCPU;
  1341. UCPU /= trans;
  1342. KCPU = pMofData->KernelCPU;
  1343. KCPU /= trans;
  1344. PerCpu = (((pMofData->UserCPU + pMofData->KernelCPU + 0.0)/1000.0)/duration) * 100.0;
  1345. if( !(ReportFlags & TRACE_TOTALS_REPORT) ){
  1346. trans /= duration;
  1347. }
  1348. if(CurrentSystem.NumberOfProcessors){
  1349. PerCpu/=CurrentSystem.NumberOfProcessors;
  1350. }
  1351. // NOTE: RATE should be COUNT if TRACE_TOTALS_REPORT
  1352. fprintf(procFile,
  1353. "<transaction name='%ws'>"
  1354. "<rate>%1.2f</rate>"
  1355. "<min_kernel>%d</min_kernel>"
  1356. "<min_user>%d</min_user>"
  1357. "<max_kernel>%d</max_kernel>"
  1358. "<max_user>%d</max_user>"
  1359. "<per_trans_kernel>%1.0f</per_trans_kernel>"
  1360. "<per_trans_user>%1.0f</per_trans_user>"
  1361. "<total_kernel>%d</total_kernel>"
  1362. "<total_user>%d</total_user>"
  1363. "<cpu>%1.2f</cpu>"
  1364. "</transaction>\n",
  1365. (pMofInfo->strDescription) ? pMofInfo->strDescription : CpdiGuidToString( str, MAXSTR, &pMofInfo->Guid ),
  1366. trans,
  1367. pMofData->MinKCpu,
  1368. pMofData->MinUCpu,
  1369. pMofData->MaxKCpu,
  1370. pMofData->MaxUCpu,
  1371. KCPU,
  1372. UCPU,
  1373. pMofData->KernelCPU,
  1374. pMofData->UserCPU,
  1375. PerCpu
  1376. );
  1377. }
  1378. DNext = DNext->Flink;
  1379. }
  1380. Next = Next->Flink;
  1381. }
  1382. fprintf(procFile, "</table>\n" );
  1383. }
  1384. PWCHAR CpdiGuidToString(
  1385. PWCHAR s,
  1386. ULONG len,
  1387. LPGUID piid
  1388. )
  1389. {
  1390. StringCchPrintf(s, len,
  1391. L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
  1392. piid->Data1, piid->Data2,
  1393. piid->Data3,
  1394. piid->Data4[0], piid->Data4[1],
  1395. piid->Data4[2], piid->Data4[3],
  1396. piid->Data4[4], piid->Data4[5],
  1397. piid->Data4[6], piid->Data4[7]);
  1398. return(s);
  1399. }
  1400. #define MAX_LOGS 1024 * 1024
  1401. typedef struct _PTR_RECORD
  1402. {
  1403. PVOID ptrRecord;
  1404. ULONG keySort;
  1405. } PTR_RECORD, * PPTR_RECORD;
  1406. static PPTR_RECORD PtrBuffer = NULL;
  1407. static ULONG PtrMax = MAX_LOGS;
  1408. static ULONG PtrTotal = 0;
  1409. static ULONG PtrIndex;
  1410. int __cdecl
  1411. CompareFileRecord(const void * p1, const void * p2)
  1412. {
  1413. PPTR_RECORD pp1 = (PPTR_RECORD) p1;
  1414. PPTR_RECORD pp2 = (PPTR_RECORD) p2;
  1415. PFILE_RECORD pFile1 = (PFILE_RECORD) pp1->ptrRecord;
  1416. PFILE_RECORD pFile2 = (PFILE_RECORD) pp2->ptrRecord;
  1417. LONG diffFault = pp2->keySort - pp1->keySort;
  1418. if (diffFault == 0)
  1419. {
  1420. diffFault = pFile1->DiskNumber - pFile2->DiskNumber;
  1421. if (diffFault == 0)
  1422. {
  1423. diffFault = wcscmp(pFile1->FileName, pFile2->FileName);
  1424. }
  1425. }
  1426. return diffFault;
  1427. }
  1428. void
  1429. ReportHotFileInfo()
  1430. {
  1431. PLIST_ENTRY pHead = & CurrentSystem.HotFileListHead;
  1432. PLIST_ENTRY pNext = pHead->Flink;
  1433. PFILE_RECORD pFile;
  1434. BOOLEAN fDone = FALSE;
  1435. ULONGLONG Duration = ((CurrentSystem.EndTime - CurrentSystem.StartTime) / 10000000);
  1436. PMOF_INFO pMofInfo;
  1437. pMofInfo = GetMofInfoHead ((LPCGUID)&ProcessGuid);
  1438. if ( pMofInfo == NULL ) {
  1439. return;
  1440. }
  1441. pMofInfo = GetMofInfoHead ((LPCGUID)&ThreadGuid);
  1442. if ( pMofInfo == NULL ) {
  1443. return;
  1444. }
  1445. ASSERT(!PtrBuffer);
  1446. PtrBuffer = (PPTR_RECORD) VirtualAlloc(
  1447. NULL,
  1448. sizeof(PTR_RECORD) * PtrMax,
  1449. MEM_COMMIT,
  1450. PAGE_READWRITE);
  1451. if( NULL == PtrBuffer ){
  1452. goto Cleanup;
  1453. }
  1454. while (!fDone)
  1455. {
  1456. for (PtrTotal = 0, fDone = TRUE;
  1457. pNext != pHead;
  1458. pNext = pNext->Flink)
  1459. {
  1460. if (PtrTotal == PtrMax)
  1461. {
  1462. fDone = FALSE;
  1463. break;
  1464. }
  1465. pFile = CONTAINING_RECORD(pNext, FILE_RECORD, Entry);
  1466. if (pFile->ReadCount + pFile->WriteCount > 0)
  1467. {
  1468. PtrBuffer[PtrTotal].ptrRecord = (PVOID) pFile;
  1469. PtrBuffer[PtrTotal].keySort =
  1470. pFile->ReadCount + pFile->WriteCount;
  1471. PtrTotal ++;
  1472. }
  1473. }
  1474. if (!fDone)
  1475. {
  1476. VirtualFree(PtrBuffer, 0, MEM_RELEASE);
  1477. PtrMax += MAX_LOGS;
  1478. PtrBuffer = (PPTR_RECORD) VirtualAlloc(
  1479. NULL,
  1480. sizeof(PTR_RECORD) * PtrMax,
  1481. MEM_COMMIT,
  1482. PAGE_READWRITE);
  1483. if (PtrBuffer == NULL)
  1484. {
  1485. goto Cleanup;
  1486. }
  1487. }
  1488. }
  1489. if (PtrTotal > 1) {
  1490. qsort((void *) PtrBuffer,
  1491. (size_t) PtrTotal,
  1492. (size_t) sizeof(PTR_RECORD),
  1493. CompareFileRecord);
  1494. }
  1495. else {
  1496. return;
  1497. }
  1498. if (PtrTotal > DISPLAY_SIZE) {
  1499. PtrTotal = DISPLAY_SIZE;
  1500. }
  1501. // output HotFile report title
  1502. //
  1503. fprintf( procFile, "<table title='Files Causing Most Disk IOs' top='%d'>\n", DISPLAY_SIZE );
  1504. for (PtrIndex = 0; PtrIndex < PtrTotal; PtrIndex ++)
  1505. {
  1506. PLIST_ENTRY pProtoHead;
  1507. PLIST_ENTRY pProtoNext;
  1508. PPROTO_PROCESS_RECORD pProto;
  1509. WCHAR ReducedFileName[FILE_NAME_COLUMN_SIZE + 1];
  1510. LPWSTR szFile;
  1511. PWCHAR szLongFile;
  1512. LPWSTR szDrive = L"";
  1513. pFile = (PFILE_RECORD) PtrBuffer[PtrIndex].ptrRecord;
  1514. if (NULL != pFile->Drive) {
  1515. szDrive = pFile->Drive;
  1516. }
  1517. if (_wcsnicmp(pFile->FileName, L"\\Device\\", 8) == 0) {
  1518. szLongFile = (PWCHAR)(pFile->FileName) + 8;
  1519. while (*szLongFile != L'\\' && *szLongFile != L'\0') {
  1520. szLongFile++;
  1521. }
  1522. }
  1523. else {
  1524. szLongFile = (PWCHAR)(pFile->FileName);
  1525. }
  1526. if (wcslen(szLongFile) > FILE_NAME_COLUMN_SIZE) {
  1527. ReduceStringW(ReducedFileName, FILE_NAME_COLUMN_SIZE + 1, szLongFile);
  1528. szFile = ReducedFileName;
  1529. }else{
  1530. szFile = szLongFile;
  1531. }
  1532. fprintf(procFile,
  1533. "<file name='%ws'>"
  1534. "<disk>%d</disk>"
  1535. "<drive>%ws</drive>"
  1536. "<read_rate>%1.3f</read_rate>"
  1537. "<read_size>%d</read_size>"
  1538. "<write_rate>%1.3f</write_rate>"
  1539. "<write_size>%d</write_size>\n",
  1540. szFile,
  1541. pFile->DiskNumber,
  1542. szDrive,
  1543. Duration ? ((double)pFile->ReadCount / (double)Duration) : 0.0,
  1544. (pFile->ReadCount) ? (pFile->ReadSize / pFile->ReadCount) : 0,
  1545. Duration ? ((double)pFile->WriteCount / (double)Duration) : 0.0,
  1546. (pFile->WriteCount) ? (pFile->WriteSize / pFile->WriteCount) : 0);
  1547. pProtoHead = & pFile->ProtoProcessListHead;
  1548. pProtoNext = pProtoHead->Flink;
  1549. while (pProtoNext != pProtoHead)
  1550. {
  1551. pProto = CONTAINING_RECORD(pProtoNext, PROTO_PROCESS_RECORD, Entry);
  1552. pProtoNext = pProtoNext->Flink;
  1553. if (pProto->ReadCount + pProto->WriteCount > 0)
  1554. {
  1555. fprintf(procFile,
  1556. "<image name='%ws'>"
  1557. "<pid>0x%08X</pid>"
  1558. "<read_rate>%1.3f</read_rate>"
  1559. "<read_size>%d</read_size>"
  1560. "<write_rate>%1.3f</write_rate>"
  1561. "<write_size>%d</write_size>"
  1562. "</image>\n",
  1563. pProto->ProcessRecord->ImageName,
  1564. pProto->ProcessRecord->PID,
  1565. Duration ? ((double)pProto->ReadCount / (double)Duration) : 0.0,
  1566. (pProto->ReadCount) ? (pProto->ReadSize / pProto->ReadCount) : 0,
  1567. Duration ? ((double)pProto->WriteCount / (double)Duration) : 0.0,
  1568. (pProto->WriteCount) ? (pProto->WriteSize / pProto->WriteCount) : 0);
  1569. }
  1570. }
  1571. fprintf( procFile, "</file>\n" );
  1572. }
  1573. fprintf( procFile, "</table>\n" );
  1574. Cleanup:
  1575. if (PtrBuffer)
  1576. {
  1577. VirtualFree(PtrBuffer, 0, MEM_RELEASE);
  1578. }
  1579. }
  1580. #define CHECKTOK( x ) if( NULL == x ) { continue; }
  1581. static void ReportPrintJobInfo2(void)
  1582. {
  1583. PRINT_JOB_RECORD Job, *pJob;
  1584. char* s;
  1585. char line[MAXSTR];
  1586. ULONG TotalCount = 0;
  1587. ULONGLONG TotalRT = 0;
  1588. ULONG TotalCPUTime = 0;
  1589. pJob = &Job;
  1590. if( NULL == CurrentSystem.TempPrintFile ){
  1591. return;
  1592. }
  1593. rewind( CurrentSystem.TempPrintFile );
  1594. while ( fgets(line, MAXSTR, CurrentSystem.TempPrintFile) != NULL ) {
  1595. s = strtok( line, (","));
  1596. CHECKTOK( s );
  1597. pJob->JobId = atol(s);
  1598. if (pJob == NULL){
  1599. return;
  1600. }
  1601. }
  1602. fprintf(procFile, "<table title='Spooler Transaction Instance (Job) Data'>\n");
  1603. RtlZeroMemory(pJob, sizeof(PRINT_JOB_RECORD));
  1604. RtlZeroMemory(line, MAXSTR * sizeof(char));
  1605. rewind( CurrentSystem.TempPrintFile );
  1606. while ( fgets(line, MAXSTR, CurrentSystem.TempPrintFile) != NULL ) {
  1607. s = strtok( line, (","));
  1608. CHECKTOK( s );
  1609. pJob->JobId = atol(s);
  1610. if (pJob == NULL){
  1611. continue;
  1612. }
  1613. s = strtok( NULL, (","));
  1614. CHECKTOK( s );
  1615. pJob->KCPUTime = atol(s);
  1616. s = strtok( NULL, (","));
  1617. CHECKTOK( s );
  1618. pJob->UCPUTime = atol(s);
  1619. s = strtok( NULL, (","));
  1620. CHECKTOK( s );
  1621. pJob->ReadIO = atol(s);
  1622. s = strtok( NULL, (","));
  1623. CHECKTOK( s );
  1624. pJob->StartTime = _atoi64(s);
  1625. s = strtok( NULL, (","));
  1626. CHECKTOK( s );
  1627. pJob->EndTime = _atoi64(s);
  1628. s = strtok( NULL, (","));
  1629. CHECKTOK( s );
  1630. pJob->ResponseTime = _atoi64(s);
  1631. s = strtok( NULL, (","));
  1632. CHECKTOK( s );
  1633. pJob->PrintJobTime = _atoi64(s);
  1634. s = strtok( NULL, (","));
  1635. CHECKTOK( s );
  1636. pJob->WriteIO = atol(s);
  1637. s = strtok( NULL, (","));
  1638. CHECKTOK( s );
  1639. pJob->DataType = atol(s);
  1640. s = strtok( NULL, (","));
  1641. CHECKTOK( s );
  1642. pJob->JobSize = atol(s);
  1643. s = strtok( NULL, (","));
  1644. CHECKTOK( s );
  1645. pJob->Pages = atol(s);
  1646. s = strtok( NULL, (","));
  1647. CHECKTOK( s );
  1648. pJob->PagesPerSide = atol(s);
  1649. s = strtok( NULL, (","));
  1650. CHECKTOK( s );
  1651. pJob->FilesOpened = (SHORT) atol(s);
  1652. s = strtok( NULL, (","));
  1653. CHECKTOK( s );
  1654. pJob->GdiJobSize = (SHORT) atol(s);
  1655. s = strtok( NULL, (","));
  1656. CHECKTOK( s );
  1657. pJob->Color = (SHORT) atol(s);
  1658. s = strtok( NULL, (","));
  1659. CHECKTOK( s );
  1660. pJob->XRes = (SHORT) atol(s);
  1661. s = strtok( NULL, (","));
  1662. CHECKTOK( s );
  1663. pJob->YRes = (SHORT) atol(s);
  1664. s = strtok( NULL, (","));
  1665. CHECKTOK( s );
  1666. pJob->Quality = (SHORT) atol(s);
  1667. s = strtok( NULL, (","));
  1668. CHECKTOK( s );
  1669. pJob->Copies = (SHORT) atol(s);
  1670. s = strtok( NULL, (","));
  1671. CHECKTOK( s );
  1672. pJob->TTOption = (SHORT) atol(s);
  1673. s = strtok( NULL, (","));
  1674. CHECKTOK( s );
  1675. pJob->NumberOfThreads = atol(s);
  1676. fprintf(procFile,
  1677. "<job id='%d'>"
  1678. "<type>%d</type>"
  1679. "<size>%d</size>"
  1680. "<pages>%d</pages>"
  1681. "<PPS>%d</PPS>"
  1682. "<files>%hd</files>"
  1683. "<gdisize>%d</gdisize>"
  1684. "<color>%hd</color>"
  1685. "<xres>%hd</xres>"
  1686. "<yres>%hd</yres>"
  1687. "<qlty>%hd</qlty>"
  1688. "<copies>%hd</copies>"
  1689. "<ttopt>%hd</ttopt>"
  1690. "<threads>%d</threads>"
  1691. "</job>\n",
  1692. pJob->JobId,
  1693. pJob->DataType,
  1694. ((pJob->JobSize) / 1024),
  1695. pJob->Pages,
  1696. pJob->PagesPerSide,
  1697. pJob->FilesOpened,
  1698. pJob->GdiJobSize,
  1699. pJob->Color,
  1700. pJob->XRes,
  1701. pJob->YRes,
  1702. pJob->Quality,
  1703. pJob->Copies,
  1704. pJob->TTOption,
  1705. pJob->NumberOfThreads
  1706. );
  1707. }
  1708. fprintf(procFile, "</table>\n" );
  1709. }
  1710. static void ReportPrintJobInfo(void)
  1711. {
  1712. PRINT_JOB_RECORD Job, *pJob;
  1713. char* s;
  1714. char line[MAXSTR];
  1715. FILETIME StTm, StlTm;
  1716. LARGE_INTEGER LargeTmp;
  1717. SYSTEMTIME stStart, stEnd, stDequeue;
  1718. ULONG TotalCount = 0;
  1719. ULONGLONG TotalRT = 0;
  1720. ULONG TotalCPUTime = 0;
  1721. if( NULL == CurrentSystem.TempPrintFile ){
  1722. return;
  1723. }
  1724. pJob = &Job;
  1725. rewind( CurrentSystem.TempPrintFile );
  1726. while ( fgets(line, MAXSTR, CurrentSystem.TempPrintFile) != NULL ) {
  1727. s = strtok( line, (","));
  1728. CHECKTOK( s );
  1729. pJob->JobId = atol(s);
  1730. if (pJob == NULL){
  1731. return;
  1732. }
  1733. }
  1734. fprintf(procFile, "<table title='Transaction Instance (Job) Statistics'>\n" );
  1735. RtlZeroMemory(pJob, sizeof(PRINT_JOB_RECORD));
  1736. RtlZeroMemory(line, MAXSTR * sizeof(char));
  1737. rewind( CurrentSystem.TempPrintFile );
  1738. while ( fgets(line, MAXSTR, CurrentSystem.TempPrintFile) != NULL ) {
  1739. s = strtok( line, (","));
  1740. CHECKTOK( s );
  1741. pJob->JobId = atol(s);
  1742. if (pJob == NULL){
  1743. continue;
  1744. }
  1745. s = strtok( NULL, (","));
  1746. CHECKTOK( s );
  1747. pJob->KCPUTime = atol(s);
  1748. s = strtok( NULL, (","));
  1749. CHECKTOK( s );
  1750. pJob->UCPUTime = atol(s);
  1751. s = strtok( NULL, (","));
  1752. CHECKTOK( s );
  1753. pJob->ReadIO = atol(s);
  1754. s = strtok( NULL, (","));
  1755. CHECKTOK( s );
  1756. pJob->StartTime = _atoi64(s);
  1757. s = strtok( NULL, (","));
  1758. CHECKTOK( s );
  1759. pJob->EndTime = _atoi64(s);
  1760. s = strtok( NULL, (","));
  1761. CHECKTOK( s );
  1762. pJob->ResponseTime = _atoi64(s);
  1763. s = strtok( NULL, (","));
  1764. CHECKTOK( s );
  1765. pJob->PrintJobTime = _atoi64(s);
  1766. s = strtok( NULL, (","));
  1767. CHECKTOK( s );
  1768. pJob->WriteIO = atol(s);
  1769. s = strtok( NULL, (","));
  1770. CHECKTOK( s );
  1771. pJob->DataType = atol(s);
  1772. s = strtok( NULL, (","));
  1773. CHECKTOK( s );
  1774. pJob->JobSize = atol(s);
  1775. s = strtok( NULL, (","));
  1776. CHECKTOK( s );
  1777. pJob->Pages = atol(s);
  1778. s = strtok( NULL, (","));
  1779. CHECKTOK( s );
  1780. pJob->PagesPerSide = atol(s);
  1781. s = strtok( NULL, (","));
  1782. CHECKTOK( s );
  1783. pJob->FilesOpened = (SHORT) atol(s);
  1784. s = strtok( NULL, (","));
  1785. CHECKTOK( s );
  1786. pJob->GdiJobSize = (SHORT) atol(s);
  1787. s = strtok( NULL, (","));
  1788. CHECKTOK( s );
  1789. pJob->Color = (SHORT) atol(s);
  1790. s = strtok( NULL, (","));
  1791. CHECKTOK( s );
  1792. pJob->XRes = (SHORT) atol(s);
  1793. s = strtok( NULL, (","));
  1794. CHECKTOK( s );
  1795. pJob->YRes = (SHORT) atol(s);
  1796. s = strtok( NULL, (","));
  1797. CHECKTOK( s );
  1798. pJob->Quality = (SHORT) atol(s);
  1799. s = strtok( NULL, (","));
  1800. CHECKTOK( s );
  1801. pJob->Copies = (SHORT) atol(s);
  1802. s = strtok( NULL, (","));
  1803. CHECKTOK( s );
  1804. pJob->TTOption = (SHORT) atol(s);
  1805. s = strtok( NULL, (","));
  1806. CHECKTOK( s );
  1807. pJob->NumberOfThreads = atol(s);
  1808. LargeTmp.QuadPart = pJob->StartTime;
  1809. StTm.dwHighDateTime = LargeTmp.HighPart;
  1810. StTm.dwLowDateTime = LargeTmp.LowPart;
  1811. FileTimeToLocalFileTime(&StTm, &StlTm);
  1812. FileTimeToSystemTime (
  1813. &StlTm,
  1814. &stStart
  1815. );
  1816. LargeTmp.QuadPart = pJob->EndTime;
  1817. StTm.dwHighDateTime = LargeTmp.HighPart;
  1818. StTm.dwLowDateTime = LargeTmp.LowPart;
  1819. FileTimeToLocalFileTime(&StTm, &StlTm);
  1820. FileTimeToSystemTime (
  1821. &StlTm,
  1822. &stEnd
  1823. );
  1824. LargeTmp.QuadPart = pJob->PrintJobTime;
  1825. StTm.dwHighDateTime = LargeTmp.HighPart;
  1826. StTm.dwLowDateTime = LargeTmp.LowPart;
  1827. FileTimeToLocalFileTime(&StTm, &StlTm);
  1828. FileTimeToSystemTime (
  1829. &StlTm,
  1830. &stDequeue
  1831. );
  1832. fprintf(procFile,
  1833. "<job id='%d'>"
  1834. "<start>%2d:%02d:%02d.%03d</start>"
  1835. "<dequeue>%2d:%02d:%02d.%03d</dequeue>"
  1836. "<end>%2d:%02d:%02d.%03d</end>"
  1837. "<response_time>%I64u</response_time>"
  1838. "<cpu>%d</cpu>"
  1839. "</job>\n",
  1840. pJob->JobId,
  1841. stStart.wHour, stStart.wMinute, stStart.wSecond, stStart.wMilliseconds,
  1842. stDequeue.wHour, stDequeue.wMinute, stDequeue.wSecond, stDequeue.wMilliseconds,
  1843. stEnd.wHour, stEnd.wMinute, stEnd.wSecond, stEnd.wMilliseconds,
  1844. pJob->ResponseTime,
  1845. pJob->KCPUTime + pJob->UCPUTime
  1846. );
  1847. TotalCount++;
  1848. TotalRT += pJob->ResponseTime;
  1849. TotalCPUTime += (pJob->KCPUTime + pJob->UCPUTime);
  1850. }
  1851. if (TotalCount > 0) {
  1852. TotalRT /= TotalCount;
  1853. TotalCPUTime /= TotalCount;
  1854. }
  1855. fprintf(procFile,
  1856. "<summary>"
  1857. "<count>%d</count>"
  1858. "<total_response_time>%I64u</total_response_time>"
  1859. "<total_cpu>%d</total_cpu>"
  1860. "</summary>\n",
  1861. TotalCount, TotalRT, TotalCPUTime );
  1862. fprintf(procFile, "</table>\n" );
  1863. ReportPrintJobInfo2();
  1864. }
  1865. PUCHAR CopyUrlStr(PUCHAR UrlStr) {
  1866. PUCHAR CopiedStr;
  1867. if (UrlStr == NULL) {
  1868. return NULL;
  1869. }
  1870. CopiedStr = (PUCHAR)malloc(strlen(UrlStr) + 1);
  1871. if (CopiedStr != NULL) {
  1872. RtlCopyMemory(CopiedStr, UrlStr, strlen(UrlStr) + 1);
  1873. return CopiedStr;
  1874. }
  1875. else {
  1876. return NULL;
  1877. }
  1878. }
  1879. void ProcessIisRequest(HTTP_REQUEST_RECORD *pReq)
  1880. {
  1881. // Global variable IIS must not be NULL here.
  1882. PURL_RECORD pUrl;
  1883. PCLIENT_RECORD pClient;
  1884. PSITE_RECORD pSite;
  1885. pUrl = FindOrAddUrlRecord(pReq->URL);
  1886. if (pUrl != NULL) {
  1887. pUrl->SiteId = pReq->SiteId;
  1888. pUrl->Requests++;
  1889. pUrl->TotalResponseTime += pReq->ULResponseTime;
  1890. pUrl->KCPUTime += pReq->KCPUTime;
  1891. pUrl->UCPUTime += pReq->UCPUTime;
  1892. pUrl->ReadIO += pReq->ReadIO;
  1893. pUrl->WriteIO += pReq->WriteIO;
  1894. pUrl->BytesSent += pReq->BytesSent;
  1895. // Cached responses don't have this field filled
  1896. // Thus need to check for Hits field as well
  1897. pUrl->UrlType = pReq->W3ProcessType;
  1898. }
  1899. pClient = FindOrAddClientRecord(pReq->IpAddrType, pReq->IpAddrV4, pReq->IpAddrV6);
  1900. if (pClient != NULL) {
  1901. pClient->Requests++;
  1902. pClient->TotalResponseTime += pReq->ULResponseTime;
  1903. pClient->BytesSent += pReq->BytesSent;
  1904. }
  1905. pSite = FindOrAddSiteRecord(pReq->SiteId);
  1906. if (pSite != NULL) {
  1907. pSite->Requests++;
  1908. pSite->TotalResponseTime += pReq->ULResponseTime;
  1909. pSite->KCPUTime += pReq->KCPUTime;
  1910. pSite->UCPUTime += pReq->UCPUTime;
  1911. pSite->ReadIO += pReq->ReadIO;
  1912. pSite->WriteIO += pReq->WriteIO;
  1913. pSite->BytesSent += pReq->BytesSent;
  1914. }
  1915. if (pReq->ULEndType == EVENT_TRACE_TYPE_UL_CACHEDEND) {
  1916. IIS->CachedResponses++;
  1917. IIS->TotalCachedResponseTime += pReq->ULResponseTime;
  1918. IIS->CachedCPUTime += pReq->KCPUTime + pReq->UCPUTime;
  1919. if (pUrl != NULL) {
  1920. pUrl->Hits++;
  1921. }
  1922. if (pClient != NULL) {
  1923. pClient->Hits++;
  1924. }
  1925. if (pSite != NULL) {
  1926. pSite->Hits++;
  1927. }
  1928. }
  1929. else {
  1930. ULONGLONG localCGIEndTime = pReq->CGIEndTime;
  1931. ULONGLONG localISAPIEndTime = pReq->ISAPIEndTime;
  1932. ULONGLONG localASPEndTime = pReq->ASPEndTime;
  1933. ULONGLONG W3ResponseTime;
  1934. #ifdef DBG
  1935. // we'll check the validity of HTTP Requests Here.
  1936. ULONGLONG ULSum = 0, W3Res = 0;
  1937. if (pReq->ULDeliverTime == 0 || pReq->ULReceiveTime == 0) {
  1938. TrctrDbgPrint(("TRACERPT Error Req: %I64u UL DeliverTime nad/or ReceiveTime not available, should throw this away.\n", pReq->RequestId));
  1939. }
  1940. else {
  1941. ULSum = (pReq->ULDeliverTime - pReq->ULStartTime) + (pReq->ULEndTime - pReq->ULReceiveTime);
  1942. }
  1943. if (pReq->W3StartTime == 0) {
  1944. TrctrDbgPrint(("TRACERPT Error Req: %I64u W3 StartTime not available, should throw this away.\n", pReq->RequestId));
  1945. }
  1946. if (pReq->W3EndTime == 0) {
  1947. TrctrDbgPrint(("TRACERPT Warning Req: %I64u W3 EndTime not available.\n", pReq->RequestId));
  1948. }
  1949. if (pReq->W3StartTime != 0 && pReq->W3EndTime != 0 && pReq->W3EndTime < pReq->W3StartTime) {
  1950. TrctrDbgPrint(("TRACERPT Warning Req: %I64u W3 EndTime smaller than pReq->W3StartTime.\n", pReq->RequestId));
  1951. }
  1952. if (ULSum != 0 && pReq->W3StartTime != 0 && pReq->W3EndTime != 0) {
  1953. double ULRatio = 0.0;
  1954. W3Res = pReq->W3EndTime - pReq->W3StartTime;
  1955. ULRatio = (double)ULSum / (double)(pReq->ULResponseTime - W3Res);
  1956. if (ULRatio < 0.5 || ULRatio > 2.0) {
  1957. TrctrDbgPrint(("TRACERPT Warning Req: %I64u UL Ratio is unreal.\n", pReq->RequestId));
  1958. }
  1959. }
  1960. if (pReq->W3ProcessType == EVENT_TRACE_TYPE_W3CORE_CGIREQ) {
  1961. if (pReq->CGIStartTime == 0) {
  1962. TrctrDbgPrint(("TRACERPT Error Req: %I64u CGI StartTime not available, should throw this away.\n", pReq->RequestId));
  1963. }
  1964. if (pReq->CGIEndTime == 0) {
  1965. TrctrDbgPrint(("TRACERPT Warning Req: %I64u CGI EndTime not available.\n", pReq->RequestId));
  1966. if (pReq->W3EndTime != 0 && (pReq->CGIStartTime > pReq->W3EndTime)) {
  1967. TrctrDbgPrint(("TRACERPT Warning Req: %I64u CGI StartTime > pReq->W3EndTime.\n", pReq->RequestId));
  1968. }
  1969. else if (pReq->W3EndTime == 0 && (pReq->CGIStartTime > pReq->ULReceiveTime)) {
  1970. TrctrDbgPrint(("TRACERPT Warning Req: %I64u CGI StartTime > pReq->ULReceiveTime.\n", pReq->RequestId));
  1971. }
  1972. }
  1973. }
  1974. else if (pReq->W3ProcessType == EVENT_TRACE_TYPE_W3CORE_ISAPIREQ) {
  1975. if (pReq->ISAPIStartTime == 0) {
  1976. TrctrDbgPrint(("TRACERPT Error Req: %I64u ISAPI StartTime not available, should throw this away.\n", pReq->RequestId));
  1977. }
  1978. if (pReq->ISAPIEndTime == 0) {
  1979. TrctrDbgPrint(("TRACERPT Warning Req: %I64u ISAPI EndTime not available.\n", pReq->RequestId));
  1980. if (pReq->W3EndTime != 0 && (pReq->ISAPIStartTime > pReq->W3EndTime)) {
  1981. TrctrDbgPrint(("TRACERPT Warning Req: %I64u ISAPI StartTime > pReq->W3EndTime.\n", pReq->RequestId));
  1982. }
  1983. else if (pReq->W3EndTime == 0 && (pReq->ISAPIStartTime > pReq->ULReceiveTime)) {
  1984. TrctrDbgPrint(("TRACERPT Warning Req: %I64u ISAPI StartTime > pReq->ULReceiveTime.\n", pReq->RequestId));
  1985. }
  1986. }
  1987. if (pReq->ASPStartTime == 0) {
  1988. TrctrDbgPrint(("TRACERPT Warning Req: %I64u ASP StartTime not available.\n", pReq->RequestId));
  1989. }
  1990. if (pReq->ASPEndTime == 0) {
  1991. TrctrDbgPrint(("TRACERPT Warning Req: %I64u ASP EndTime not available.\n", pReq->RequestId));
  1992. if (pReq->ISAPIEndTime != 0 && (pReq->ASPStartTime > pReq->ISAPIEndTime)) {
  1993. TrctrDbgPrint(("TRACERPT Warning Req: %I64u ASP StartTime > pReq->ISAPIEndTime.\n", pReq->RequestId));
  1994. }
  1995. else if (pReq->W3EndTime != 0 && (pReq->ASPStartTime > pReq->W3EndTime)) {
  1996. TrctrDbgPrint(("TRACERPT Warning Req: %I64u ASP StartTime > pReq->W3EndTime.\n", pReq->RequestId));
  1997. }
  1998. else if (pReq->W3EndTime == 0 && (pReq->ASPStartTime > pReq->ULReceiveTime)) {
  1999. TrctrDbgPrint(("TRACERPT Warning Req: %I64u ASP StartTime > pReq->ULReceiveTime.\n", pReq->RequestId));
  2000. }
  2001. }
  2002. }
  2003. #endif
  2004. // Fix the time inconsistency in transactions
  2005. if (pReq->W3StartTime == 0 || (pReq->W3EndTime != 0 && pReq->W3EndTime < pReq->W3StartTime)) {
  2006. RequestsDiscarded++;
  2007. if (pReq->URL != NULL) {
  2008. free(pReq->URL);
  2009. }
  2010. return;
  2011. }
  2012. if (pReq->W3EndTime == 0 || pReq->W3EndTime > pReq->ULReceiveTime) {
  2013. pReq->W3EndTime = pReq->ULReceiveTime;
  2014. if (pReq->W3EndTime == 0 || pReq->W3EndTime < pReq->W3StartTime) {
  2015. RequestsDiscarded++;
  2016. if (pReq->URL != NULL) {
  2017. free(pReq->URL);
  2018. }
  2019. return;
  2020. }
  2021. }
  2022. W3ResponseTime = pReq->W3EndTime - pReq->W3StartTime;
  2023. if (W3ResponseTime < pReq->W3FilterResponseTime) {
  2024. pReq->W3FilterResponseTime = W3ResponseTime;
  2025. }
  2026. if (pReq->W3ProcessType == EVENT_TRACE_TYPE_W3CORE_CGIREQ) {
  2027. if (pReq->CGIStartTime == 0) {
  2028. RequestsDiscarded++;
  2029. if (pReq->URL != NULL) {
  2030. free(pReq->URL);
  2031. }
  2032. return;
  2033. }
  2034. else if (pReq->CGIEndTime == 0 || pReq->CGIEndTime > pReq->W3EndTime) {
  2035. localCGIEndTime = pReq->W3EndTime;
  2036. if (pReq->CGIStartTime > localCGIEndTime) {
  2037. RequestsDiscarded++;
  2038. if (pReq->URL != NULL) {
  2039. free(pReq->URL);
  2040. }
  2041. return;
  2042. }
  2043. }
  2044. else {
  2045. localCGIEndTime = pReq->CGIEndTime;
  2046. }
  2047. if (pReq->CGIStartTime < pReq->W3StartTime) {
  2048. pReq->CGIStartTime = pReq->W3StartTime;
  2049. }
  2050. if (localCGIEndTime < pReq->CGIStartTime) {
  2051. localCGIEndTime = pReq->CGIStartTime;
  2052. }
  2053. if ((pReq->W3FilterResponseTime + (localCGIEndTime - pReq->CGIStartTime)) > W3ResponseTime) {
  2054. pReq->W3FilterResponseTime = W3ResponseTime - (localCGIEndTime - pReq->CGIStartTime);
  2055. }
  2056. }
  2057. else if (pReq->W3ProcessType == EVENT_TRACE_TYPE_W3CORE_ISAPIREQ) {
  2058. if (pReq->ISAPIStartTime == 0) {
  2059. RequestsDiscarded++;
  2060. if (pReq->URL != NULL) {
  2061. free(pReq->URL);
  2062. }
  2063. return;
  2064. }
  2065. if (pReq->ISAPIEndTime == 0 || pReq->ISAPIEndTime > pReq->W3EndTime) {
  2066. localISAPIEndTime = pReq->W3EndTime;
  2067. if (pReq->ISAPIStartTime > localISAPIEndTime) {
  2068. RequestsDiscarded++;
  2069. if (pReq->URL != NULL) {
  2070. free(pReq->URL);
  2071. }
  2072. return;
  2073. }
  2074. }
  2075. else {
  2076. localISAPIEndTime = pReq->ISAPIEndTime;
  2077. }
  2078. if (pReq->ISAPIStartTime < pReq->W3StartTime) {
  2079. pReq->ISAPIStartTime = pReq->W3StartTime;
  2080. }
  2081. if (localISAPIEndTime < pReq->ISAPIStartTime) {
  2082. localISAPIEndTime = pReq->ISAPIStartTime;
  2083. }
  2084. if ((pReq->W3FilterResponseTime + (localISAPIEndTime - pReq->ISAPIStartTime)) > W3ResponseTime) {
  2085. pReq->W3FilterResponseTime = W3ResponseTime - (localISAPIEndTime - pReq->ISAPIStartTime);
  2086. }
  2087. if (pReq->ASPStartTime != 0) {
  2088. if (pReq->ASPEndTime == 0) {
  2089. localASPEndTime = localISAPIEndTime;
  2090. if (pReq->ASPStartTime > localASPEndTime) {
  2091. RequestsDiscarded++;
  2092. if (pReq->URL != NULL) {
  2093. free(pReq->URL);
  2094. }
  2095. return;
  2096. }
  2097. }
  2098. else {
  2099. localASPEndTime = pReq->ASPEndTime;
  2100. }
  2101. if (pReq->ASPStartTime < pReq->ISAPIStartTime) {
  2102. pReq->ASPStartTime = pReq->ISAPIStartTime;
  2103. }
  2104. if (localASPEndTime < pReq->ASPStartTime) {
  2105. localASPEndTime = pReq->ASPStartTime;
  2106. }
  2107. if ((localISAPIEndTime - pReq->ISAPIStartTime) < (localASPEndTime - pReq->ASPStartTime)) {
  2108. localASPEndTime = localISAPIEndTime;
  2109. }
  2110. }
  2111. } // Fix done. All end times are fixed.
  2112. IIS->TotalNonCachedResponseTime += pReq->ULResponseTime;
  2113. IIS->NonCachedCPUTime += pReq->KCPUTime + pReq->UCPUTime;
  2114. if (pReq->W3FilterResponseTime != 0) {
  2115. IIS->W3FilterRequests += pReq->W3FilterVisits;
  2116. IIS->TotalW3FilterResponseTime += pReq->W3FilterResponseTime;
  2117. IIS->TotalW3FilterCPUTime += pReq->W3FltrCPUTime;
  2118. }
  2119. if (pReq->ULEndType == EVENT_TRACE_TYPE_UL_SENDERROR && pReq->ISAPIStartTime == 0) {
  2120. // This is a request ended with SENDERROR.
  2121. SendErrorRequests++;
  2122. }
  2123. if (pReq->HttpStatus != 0 && pReq->HttpStatus >= 400) {
  2124. // This is a request with http error.
  2125. IIS->W3Error++;
  2126. IIS->TotalErrorResponseTime += pReq->ULResponseTime;
  2127. IIS->ErrorCPUTime += pReq->KCPUTime + pReq->UCPUTime;
  2128. IIS->TotalErrorULOnlyCPUTime += pReq->ULCPUTime;
  2129. IIS->TotalErrorW3OnlyCPUTime += pReq->W3CPUTime;
  2130. IIS->TotalErrorW3FilterCPUTime += pReq->W3FltrCPUTime;
  2131. IIS->TotalErrorCGIOnlyCPUTime += pReq->CGICPUTime;
  2132. IIS->TotalErrorISAPIOnlyCPUTime += pReq->ISAPICPUTime;
  2133. IIS->TotalErrorASPOnlyCPUTime += pReq->ASPCPUTime;
  2134. IIS->TotalErrorW3OnlyResponseTime += (pReq->W3EndTime - pReq->W3StartTime)
  2135. - pReq->W3FilterResponseTime;
  2136. if (pReq->ULStartTime != 0 && pReq->ULEndTime != 0 && pReq->ULDeliverTime != 0 && pReq->ULReceiveTime != 0) {
  2137. // ????????????????????????????????????????????????????????????????????????
  2138. // TotalErrorULOnlyResponseTime += (pReq->ULDeliverTime - pReq->ULStartTime)
  2139. // + (pReq->ULEndTime - pReq->ULReceiveTime);
  2140. IIS->TotalErrorULOnlyResponseTime += pReq->ULResponseTime - (pReq->W3EndTime - pReq->W3StartTime);
  2141. }
  2142. else {
  2143. IIS->TotalErrorULOnlyResponseTime += pReq->ULResponseTime - (pReq->W3EndTime - pReq->W3StartTime);
  2144. }
  2145. IIS->TotalErrorW3FilterResponseTime += pReq->W3FilterResponseTime;
  2146. }
  2147. else if (pReq->W3ProcessType == EVENT_TRACE_TYPE_W3CORE_FILEREQ) {
  2148. IIS->W3FileRequests++;
  2149. IIS->TotalFileResponseTime += pReq->ULResponseTime;
  2150. IIS->FileCPUTime += pReq->KCPUTime + pReq->UCPUTime;
  2151. IIS->TotalFileULOnlyCPUTime += pReq->ULCPUTime;
  2152. IIS->TotalFileW3OnlyCPUTime += pReq->W3CPUTime;
  2153. IIS->TotalFileW3FilterCPUTime += pReq->W3FltrCPUTime;
  2154. if (pSite != NULL) {
  2155. pSite->FileRequests++;
  2156. }
  2157. IIS->TotalFileW3OnlyResponseTime += (pReq->W3EndTime - pReq->W3StartTime)
  2158. - pReq->W3FilterResponseTime;
  2159. if (pReq->ULStartTime != 0 && pReq->ULEndTime != 0 && pReq->ULDeliverTime != 0 && pReq->ULReceiveTime != 0) {
  2160. // ????????????????????????????????????????????????????????????????????????
  2161. // TotalFileULOnlyResponseTime += (pReq->ULDeliverTime - pReq->ULStartTime)
  2162. // + (pReq->ULEndTime - pReq->ULReceiveTime);
  2163. IIS->TotalFileULOnlyResponseTime += pReq->ULResponseTime - (pReq->W3EndTime - pReq->W3StartTime);
  2164. }
  2165. else {
  2166. IIS->TotalFileULOnlyResponseTime += pReq->ULResponseTime - (pReq->W3EndTime - pReq->W3StartTime);
  2167. }
  2168. IIS->TotalFileW3FilterResponseTime += pReq->W3FilterResponseTime;
  2169. }
  2170. else if (pReq->W3ProcessType == EVENT_TRACE_TYPE_W3CORE_CGIREQ) {
  2171. IIS->W3CGIRequests++;
  2172. IIS->TotalCGIResponseTime += pReq->ULResponseTime;
  2173. IIS->TotalCGIOnlyResponseTime += (localCGIEndTime - pReq->CGIStartTime);
  2174. IIS->CGICPUTime += pReq->KCPUTime + pReq->UCPUTime;
  2175. IIS->TotalCGIOnlyCPUTime += pReq->CGICPUTime;
  2176. IIS->TotalCGIULOnlyCPUTime += pReq->ULCPUTime;
  2177. IIS->TotalCGIW3OnlyCPUTime += pReq->W3CPUTime;
  2178. IIS->TotalCGIW3FilterCPUTime += pReq->W3FltrCPUTime;
  2179. if (pSite != NULL) {
  2180. pSite->CGIRequests++;
  2181. }
  2182. IIS->TotalCGIW3OnlyResponseTime += (pReq->W3EndTime - pReq->W3StartTime)
  2183. - (localCGIEndTime - pReq->CGIStartTime)
  2184. - pReq->W3FilterResponseTime;
  2185. if (pReq->ULStartTime != 0 && pReq->ULEndTime != 0 && pReq->ULDeliverTime != 0 && pReq->ULReceiveTime != 0) {
  2186. // ????????????????????????????????????????????????????????????????????????
  2187. // TotalCGIULOnlyResponseTime += (pReq->ULDeliverTime - pReq->ULStartTime)
  2188. // + (pReq->ULEndTime - pReq->ULReceiveTime);
  2189. IIS->TotalCGIULOnlyResponseTime += pReq->ULResponseTime - (pReq->W3EndTime - pReq->W3StartTime);
  2190. }
  2191. else {
  2192. IIS->TotalCGIULOnlyResponseTime += pReq->ULResponseTime - (pReq->W3EndTime - pReq->W3StartTime);
  2193. }
  2194. IIS->TotalCGIW3FilterResponseTime += pReq->W3FilterResponseTime;
  2195. }
  2196. else if (pReq->W3ProcessType == EVENT_TRACE_TYPE_W3CORE_ISAPIREQ) {
  2197. ULONGLONG TimeSpentInAsp = 0;
  2198. ULONGLONG TimeSpentInISAPI = 0;
  2199. if (pReq->ASPStartTime != 0 && localASPEndTime != 0) {
  2200. TimeSpentInAsp = localASPEndTime - pReq->ASPStartTime;
  2201. }
  2202. if (pReq->ISAPIStartTime != 0 && localISAPIEndTime != 0) {
  2203. TimeSpentInISAPI = localISAPIEndTime - pReq->ISAPIStartTime;
  2204. if (TimeSpentInAsp > TimeSpentInISAPI) {
  2205. TimeSpentInISAPI = 0;
  2206. }
  2207. else {
  2208. TimeSpentInISAPI -= TimeSpentInAsp;
  2209. }
  2210. }
  2211. IIS->W3ISAPIRequests++;
  2212. IIS->TotalISAPIResponseTime += pReq->ULResponseTime;
  2213. IIS->ISAPICPUTime += pReq->KCPUTime + pReq->UCPUTime;
  2214. if (pSite != NULL) {
  2215. pSite->ISAPIRequests++;
  2216. }
  2217. IIS->TotalASPW3OnlyResponseTime += (((pReq->W3EndTime - pReq->W3StartTime) - pReq->W3FilterResponseTime)
  2218. - (TimeSpentInISAPI + TimeSpentInAsp));
  2219. IIS->W3ASPRequests++;
  2220. IIS->TotalASPResponseTime += pReq->ULResponseTime;
  2221. IIS->TotalASPOnlyResponseTime += TimeSpentInAsp;
  2222. IIS->ASPCPUTime += pReq->KCPUTime + pReq->UCPUTime;
  2223. IIS->TotalASPOnlyCPUTime += pReq->ASPCPUTime;
  2224. IIS->TotalASPULOnlyCPUTime += pReq->ULCPUTime;
  2225. IIS->TotalASPW3OnlyCPUTime += pReq->W3CPUTime;
  2226. IIS->TotalASPW3FilterCPUTime += pReq->W3FltrCPUTime;
  2227. IIS->TotalASPISAPIOnlyCPUTime += pReq->ISAPICPUTime;
  2228. if (pSite != NULL) {
  2229. pSite->ASPRequests++;
  2230. }
  2231. IIS->TotalASPISAPIOnlyResponseTime += TimeSpentInISAPI;
  2232. if (pReq->ULStartTime != 0 && pReq->ULEndTime != 0 && pReq->ULDeliverTime != 0 && pReq->ULReceiveTime != 0) {
  2233. // ????????????????????????????????????????????????????????????????????????
  2234. // TotalASPULOnlyResponseTime += (pReq->ULDeliverTime - pReq->ULStartTime)
  2235. // + (pReq->ULEndTime - pReq->ULReceiveTime);
  2236. IIS->TotalASPULOnlyResponseTime += pReq->ULResponseTime - (pReq->W3EndTime - pReq->W3StartTime);
  2237. }
  2238. else {
  2239. IIS->TotalASPULOnlyResponseTime += pReq->ULResponseTime - (pReq->W3EndTime - pReq->W3StartTime);
  2240. }
  2241. IIS->TotalASPW3FilterResponseTime += pReq->W3FilterResponseTime;
  2242. }
  2243. else if (pReq->W3ProcessType == EVENT_TRACE_TYPE_W3CORE_OOPREQ) { // ???
  2244. IIS->W3OOPRequests++;
  2245. IIS->TotalOOPResponseTime += pReq->ULResponseTime;
  2246. IIS->OOPCPUTime += pReq->KCPUTime + pReq->UCPUTime;
  2247. if (pSite != NULL) {
  2248. pSite->OOPRequests++;
  2249. }
  2250. }
  2251. }
  2252. IIS->TotalRequests++;
  2253. IIS->TotalCPUTime += pReq->KCPUTime + pReq->UCPUTime;
  2254. if (pReq->URL != NULL) {
  2255. free(pReq->URL);
  2256. }
  2257. }
  2258. static void ReportIisEvents(void)
  2259. {
  2260. HTTP_REQUEST_RECORD Req, *pReq;
  2261. char* s;
  2262. char line[MAXSTR];
  2263. URL_RECORD TopHitURLs[DISPLAY_SIZE];
  2264. URL_RECORD TopHitStaticURLs[DISPLAY_SIZE];
  2265. URL_RECORD TopSlowURLs[DISPLAY_SIZE];
  2266. URL_RECORD TopConsumingURLs[DISPLAY_SIZE];
  2267. URL_RECORD TopBytesURLs[DISPLAY_SIZE];
  2268. PURL_RECORD pUrl;
  2269. CLIENT_RECORD TopHitClients[DISPLAY_SIZE];
  2270. CLIENT_RECORD TopSlowClients[DISPLAY_SIZE];
  2271. CLIENT_RECORD TopBytesClients[DISPLAY_SIZE];
  2272. PCLIENT_RECORD pClient;
  2273. SITE_RECORD TopHitSites[DISPLAY_SIZE];
  2274. SITE_RECORD TopSlowSites[DISPLAY_SIZE];
  2275. SITE_RECORD TopConsumingSites[DISPLAY_SIZE];
  2276. SITE_RECORD TopBytesSites[DISPLAY_SIZE];
  2277. PSITE_RECORD pSite;
  2278. ULONG i, k;
  2279. ULONG Duration = (ULONG)((CurrentSystem.IISEndTime - CurrentSystem.IISStartTime) / 10000000);
  2280. ULONG MilDuration = (ULONG)((CurrentSystem.IISEndTime - CurrentSystem.IISStartTime) * CurrentSystem.NumberOfProcessors / 10000);
  2281. double Rates = 0.0;
  2282. PLIST_ENTRY Next, Head;
  2283. ULONG PrintCPUUsage = TRUE;
  2284. if( NULL == CurrentSystem.TempIisFile ){
  2285. return;
  2286. }
  2287. IIS = (PIIS_REPORT_RECORD)malloc(sizeof(IIS_REPORT_RECORD));
  2288. if (IIS == NULL) {
  2289. return;
  2290. }
  2291. RtlZeroMemory(IIS, sizeof(IIS_REPORT_RECORD));
  2292. Head = &CurrentSystem.ProcessListHead;
  2293. Next = Head->Flink;
  2294. if( Head == Next ){
  2295. PrintCPUUsage = FALSE;
  2296. }
  2297. pReq = &Req;
  2298. RtlZeroMemory(pReq, sizeof(HTTP_REQUEST_RECORD));
  2299. RtlZeroMemory(line, MAXSTR * sizeof(char));
  2300. // Process requests written in the file
  2301. rewind( CurrentSystem.TempIisFile );
  2302. while ( fgets(line, MAXSTR, CurrentSystem.TempIisFile) != NULL ) {
  2303. s = strtok( line, (","));
  2304. CHECKTOK( s );
  2305. pReq->RequestId = _atoi64(s);
  2306. s = strtok( NULL, (","));
  2307. CHECKTOK( s );
  2308. pReq->SiteId = atol(s);
  2309. s = strtok( NULL, (","));
  2310. CHECKTOK( s );
  2311. pReq->KCPUTime = atol(s);
  2312. s = strtok( NULL, (","));
  2313. CHECKTOK( s );
  2314. pReq->UCPUTime = atol(s);
  2315. s = strtok( NULL, (","));
  2316. CHECKTOK( s );
  2317. pReq->ReadIO = atol(s);
  2318. s = strtok( NULL, (","));
  2319. CHECKTOK( s );
  2320. pReq->WriteIO = atol(s);
  2321. s = strtok( NULL, (","));
  2322. CHECKTOK( s );
  2323. pReq->ULStartTime = _atoi64(s);
  2324. s = strtok( NULL, (","));
  2325. CHECKTOK( s );
  2326. pReq->ULEndTime = _atoi64(s);
  2327. s = strtok( NULL, (","));
  2328. CHECKTOK( s );
  2329. pReq->ULResponseTime = _atoi64(s);
  2330. s = strtok( NULL, (","));
  2331. CHECKTOK( s );
  2332. pReq->ULParseTime = _atoi64(s);
  2333. s = strtok( NULL, (","));
  2334. CHECKTOK( s );
  2335. pReq->ULDeliverTime = _atoi64(s);
  2336. s = strtok( NULL, (","));
  2337. CHECKTOK( s );
  2338. pReq->ULReceiveTime = _atoi64(s);
  2339. s = strtok( NULL, (","));
  2340. CHECKTOK( s );
  2341. pReq->ULReceiveType = (SHORT) atol(s);
  2342. s = strtok( NULL, (","));
  2343. CHECKTOK( s );
  2344. pReq->ULEndType = (SHORT) atol(s);
  2345. s = strtok( NULL, (","));
  2346. CHECKTOK( s );
  2347. pReq->W3StartTime = _atoi64(s);
  2348. s = strtok( NULL, (","));
  2349. CHECKTOK( s );
  2350. pReq->W3EndTime = _atoi64(s);
  2351. s = strtok( NULL, (","));
  2352. CHECKTOK( s );
  2353. pReq->W3FilterResponseTime = _atoi64(s);
  2354. s = strtok( NULL, (","));
  2355. CHECKTOK( s );
  2356. pReq->W3ProcessType = (SHORT) atol(s);
  2357. s = strtok( NULL, (","));
  2358. CHECKTOK( s );
  2359. pReq->W3EndType = (SHORT) atol(s);
  2360. s = strtok( NULL, (","));
  2361. CHECKTOK( s );
  2362. pReq->FileReqTime = _atoi64(s);
  2363. s = strtok( NULL, (","));
  2364. CHECKTOK( s );
  2365. pReq->CGIStartTime = _atoi64(s);
  2366. s = strtok( NULL, (","));
  2367. CHECKTOK( s );
  2368. pReq->CGIEndTime = _atoi64(s);
  2369. s = strtok( NULL, (","));
  2370. CHECKTOK( s );
  2371. pReq->ISAPIStartTime = _atoi64(s);
  2372. s = strtok( NULL, (","));
  2373. CHECKTOK( s );
  2374. pReq->ISAPIEndTime = _atoi64(s);
  2375. s = strtok( NULL, (","));
  2376. CHECKTOK( s );
  2377. pReq->ASPStartTime = _atoi64(s);
  2378. s = strtok( NULL, (","));
  2379. CHECKTOK( s );
  2380. pReq->ASPEndTime = _atoi64(s);
  2381. s = strtok( NULL, (","));
  2382. CHECKTOK( s );
  2383. pReq->SSLResponseTime = _atoi64(s);
  2384. s = strtok( NULL, (","));
  2385. CHECKTOK( s );
  2386. pReq->StrmFltrResponseTime = _atoi64(s);
  2387. s = strtok( NULL, (","));
  2388. CHECKTOK( s );
  2389. pReq->HttpStatus = (USHORT) atol(s);;
  2390. s = strtok( NULL, (","));
  2391. CHECKTOK( s );
  2392. pReq->IsapiExt = (USHORT) atol(s);;
  2393. s = strtok( NULL, (","));
  2394. CHECKTOK( s );
  2395. pReq->IpAddrType = (USHORT) atol(s);;
  2396. s = strtok( NULL, (","));
  2397. CHECKTOK( s );
  2398. pReq->IpAddrV4 = atol(s);
  2399. s = strtok( NULL, (","));
  2400. CHECKTOK( s );
  2401. pReq->IpAddrV6[0] = (USHORT) atol(s);;
  2402. s = strtok( NULL, (","));
  2403. CHECKTOK( s );
  2404. pReq->IpAddrV6[1] = (USHORT) atol(s);;
  2405. s = strtok( NULL, (","));
  2406. CHECKTOK( s );
  2407. pReq->IpAddrV6[2] = (USHORT) atol(s);;
  2408. s = strtok( NULL, (","));
  2409. CHECKTOK( s );
  2410. pReq->IpAddrV6[3] = (USHORT) atol(s);;
  2411. s = strtok( NULL, (","));
  2412. CHECKTOK( s );
  2413. pReq->IpAddrV6[4] = (USHORT) atol(s);;
  2414. s = strtok( NULL, (","));
  2415. CHECKTOK( s );
  2416. pReq->IpAddrV6[5] = (USHORT) atol(s);;
  2417. s = strtok( NULL, (","));
  2418. CHECKTOK( s );
  2419. pReq->IpAddrV6[6] = (USHORT) atol(s);;
  2420. s = strtok( NULL, (","));
  2421. CHECKTOK( s );
  2422. pReq->IpAddrV6[7] = (USHORT) atol(s);;
  2423. s = strtok( NULL, (","));
  2424. CHECKTOK( s );
  2425. pReq->NumberOfThreads = atol(s);
  2426. s = strtok( NULL, (","));
  2427. CHECKTOK( s );
  2428. pReq->BytesSent = atol(s);
  2429. s = strtok( NULL, (","));
  2430. CHECKTOK( s );
  2431. pReq->ULCPUTime = atol(s);
  2432. s = strtok( NULL, (","));
  2433. CHECKTOK( s );
  2434. pReq->W3CPUTime = atol(s);
  2435. s = strtok( NULL, (","));
  2436. CHECKTOK( s );
  2437. pReq->W3FltrCPUTime = atol(s);
  2438. s = strtok( NULL, (","));
  2439. CHECKTOK( s );
  2440. pReq->ISAPICPUTime = atol(s);
  2441. s = strtok( NULL, (","));
  2442. CHECKTOK( s );
  2443. pReq->ASPCPUTime = atol(s);
  2444. s = strtok( NULL, (","));
  2445. CHECKTOK( s );
  2446. pReq->CGICPUTime = atol(s);
  2447. s = strtok( NULL, (","));
  2448. CHECKTOK( s );
  2449. if (strlen(s) > 0) {
  2450. LPSTR strptr = (LPSTR)malloc(strlen(s) + 1);
  2451. if (strptr != NULL) {
  2452. RtlCopyMemory((PUCHAR)strptr, (PUCHAR)s, strlen(s));
  2453. if (*(strptr + strlen(s) - 1) == '\n') {
  2454. *(strptr + strlen(s) - 1) = '\0';
  2455. }
  2456. else {
  2457. *(strptr + strlen(s)) = '\0';
  2458. }
  2459. pReq->URL = (PCHAR)strptr;
  2460. }
  2461. else {
  2462. continue;
  2463. }
  2464. }
  2465. else {
  2466. continue;
  2467. }
  2468. ProcessIisRequest(pReq);
  2469. }
  2470. if (IIS->TotalRequests != 0) {
  2471. if (Duration != 0) {
  2472. Rates = (double)(IIS->TotalRequests) / (double)Duration;
  2473. }
  2474. else {
  2475. Rates = 0.0;
  2476. }
  2477. }
  2478. else {
  2479. free(IIS);
  2480. return;
  2481. }
  2482. fprintf(procFile, "<table title='Http Requests Response Time Statistics'>\n");
  2483. fprintf(procFile,
  2484. "<requests cached='true' type='Static HTTP'>"
  2485. "<rate>%1.3f</rate>"
  2486. "<response_time>%1.3f</response_time>"
  2487. "<component name='UL'>%3d.0</component>"
  2488. "<component name='W3'>0.0</component>"
  2489. "<component name='W3Fltr'>0.0</component>"
  2490. "<component name='ISAPI'>0.0</component>"
  2491. "<component name='ASP'>0.0</component>"
  2492. "<component name='CGI'>0.0</component>"
  2493. "</requests>\n",
  2494. Duration ? (double)(IIS->CachedResponses) / (double)Duration : 0.0,
  2495. IIS->CachedResponses ? (double)(IIS->TotalCachedResponseTime / IIS->CachedResponses) / 10000.0 : 0.0,
  2496. IIS->CachedResponses ? 100 : 0);
  2497. fprintf(procFile,
  2498. "<requests cached='false' type='ASP'>"
  2499. "<rate>%1.3f</rate>"
  2500. "<response_time>%1.3f</response_time>"
  2501. "<component name='UL'>%1.1f</component>"
  2502. "<component name='W3'>%1.1f</component>"
  2503. "<component name='W3Fltr'>%1.1f</component>"
  2504. "<component name='ISAPI'>%1.1f</component>"
  2505. "<component name='ASP'>%1.1f</component>"
  2506. "<component name='CGI'>%1.1f</component>"
  2507. "</requests>\n",
  2508. Duration ? (double)(IIS->W3ISAPIRequests) / (double)Duration : 0.0,
  2509. (IIS->W3ISAPIRequests) ? ((double)IIS->TotalISAPIResponseTime / (double)IIS->W3ISAPIRequests) / 10000.0 : 0.0,
  2510. ((IIS->TotalASPResponseTime) ? ((double)(IIS->TotalASPULOnlyResponseTime) / (double)(IIS->TotalASPResponseTime)) * 100.0 : 0.0),
  2511. ((IIS->TotalASPResponseTime) ? ((double)(IIS->TotalASPW3OnlyResponseTime) / (double)(IIS->TotalASPResponseTime)) * 100.0 : 0.0),
  2512. ((IIS->TotalASPResponseTime) ? ((double)(IIS->TotalASPW3FilterResponseTime) / (double)(IIS->TotalASPResponseTime)) * 100.0 : 0.0),
  2513. ((IIS->TotalASPResponseTime) ? ((double)(IIS->TotalASPISAPIOnlyResponseTime) / (double)(IIS->TotalASPResponseTime)) * 100.0 : 0.0),
  2514. ((IIS->TotalASPResponseTime) ? ((double)(IIS->TotalASPOnlyResponseTime) / (double)(IIS->TotalASPResponseTime)) * 100.0 : 0.0),
  2515. 0.0);
  2516. fprintf(procFile,
  2517. "<requests cached='false' type='Static HTTP'>"
  2518. "<rate>%1.3f</rate>"
  2519. "<response_time>%1.3f</response_time>"
  2520. "<component name='UL'>%1.1f</component>"
  2521. "<component name='W3'>%1.1f</component>"
  2522. "<component name='W3Fltr'>%1.1f</component>"
  2523. "<component name='ISAPI'>%1.1f</component>"
  2524. "<component name='ASP'>%1.1f</component>"
  2525. "<component name='CGI'>%1.1f</component>"
  2526. "</requests>\n",
  2527. Duration ? (double)(IIS->W3FileRequests) / (double)Duration : 0.0,
  2528. (IIS->W3FileRequests) ? ((double)IIS->TotalFileResponseTime / (double)IIS->W3FileRequests) / 10000.0 : 0.0,
  2529. (IIS->TotalFileResponseTime ? ((double)(IIS->TotalFileULOnlyResponseTime) / (double)(IIS->TotalFileResponseTime)) * 100.0 : 0.0),
  2530. (IIS->TotalFileResponseTime ? ((double)(IIS->TotalFileW3OnlyResponseTime) / (double)(IIS->TotalFileResponseTime)) * 100.0 : 0.0),
  2531. (IIS->TotalFileResponseTime ? ((double)(IIS->TotalFileW3FilterResponseTime) / (double)(IIS->TotalFileResponseTime)) * 100.0 : 0.0),
  2532. 0.0,
  2533. 0.0,
  2534. 0.0);
  2535. fprintf(procFile,
  2536. "<requests cached='false' type='CGI'>"
  2537. "<rate>%1.3f</rate>"
  2538. "<response_time>%1.3f</response_time>"
  2539. "<component name='UL'>%1.1f</component>"
  2540. "<component name='W3'>%1.1f</component>"
  2541. "<component name='W3Fltr'>%1.1f</component>"
  2542. "<component name='ISAPI'>%1.1f</component>"
  2543. "<component name='ASP'>%1.1f</component>"
  2544. "<component name='CGI'>%1.1f</component>"
  2545. "</requests>\n",
  2546. Duration ? (double)(IIS->W3CGIRequests) / (double)Duration : 0.0,
  2547. (IIS->W3CGIRequests) ? ((double)IIS->TotalCGIResponseTime / (double)IIS->W3CGIRequests) / 10000.0 : 0.0,
  2548. ((IIS->TotalCGIResponseTime) ? ((double)(IIS->TotalCGIULOnlyResponseTime) / (double)(IIS->TotalCGIResponseTime)) * 100.0 : 0.0),
  2549. ((IIS->TotalCGIResponseTime) ? ((double)(IIS->TotalCGIW3OnlyResponseTime) / (double)(IIS->TotalCGIResponseTime)) * 100.0 : 0.0),
  2550. ((IIS->TotalCGIResponseTime) ? ((double)(IIS->TotalCGIW3FilterResponseTime) / (double)(IIS->TotalCGIResponseTime)) * 100.0 : 0.0),
  2551. 0.0,
  2552. 0.0,
  2553. ((IIS->TotalCGIResponseTime) ? ((double)(IIS->TotalCGIOnlyResponseTime) / (double)(IIS->TotalCGIResponseTime)) * 100.0 : 0.0));
  2554. if (IIS->W3Error != 0) {
  2555. fprintf(procFile,
  2556. "<requests cached='false' type='Error'>"
  2557. "<rate>%1.3f</rate>"
  2558. "<response_time>%1.3f</response_time>"
  2559. "<component name='UL'>%1.1f</component>"
  2560. "<component name='W3'>%1.1f</component>"
  2561. "<component name='W3Fltr'>%1.1f</component>"
  2562. "<component name='ISAPI'>%1.1f</component>"
  2563. "<component name='ASP'>%1.1f</component>"
  2564. "<component name='CGI'>%1.1f</component>"
  2565. "</requests>\n",
  2566. Duration ? (double)(IIS->W3Error) / (double)Duration : 0.0,
  2567. (IIS->W3Error) ? ((double)IIS->TotalErrorResponseTime / (double)IIS->W3Error) / 10000.0 : 0.0,
  2568. ((IIS->TotalErrorResponseTime) ? ((double)(IIS->TotalErrorULOnlyResponseTime) / (double)(IIS->TotalErrorResponseTime)) * 100.0 : 0.0),
  2569. ((IIS->TotalErrorResponseTime) ? ((double)(IIS->TotalErrorW3OnlyResponseTime) / (double)(IIS->TotalErrorResponseTime)) * 100.0 : 0.0),
  2570. ((IIS->TotalErrorResponseTime) ? ((double)(IIS->TotalErrorW3FilterResponseTime) / (double)(IIS->TotalErrorResponseTime)) * 100.0 : 0.0),
  2571. 0.0,
  2572. 0.0,
  2573. 0.0);
  2574. }
  2575. fprintf(procFile,
  2576. "<summary cached='true'>"
  2577. "<rate>%1.3f</rate>"
  2578. "<response_time>%1.3f</response_time>"
  2579. "<component name='UL'>%3d.0</component>"
  2580. "<component name='W3'>0.0</component>"
  2581. "<component name='W3Fltr'>0.0</component>"
  2582. "<component name='ISAPI'>0.0</component>"
  2583. "<component name='ASP'>0.0</component>"
  2584. "<component name='CGI'>0.0</component>"
  2585. "</summary>\n",
  2586. Duration ? (double)(IIS->CachedResponses) / (double)Duration : 0.0,
  2587. IIS->CachedResponses ? (double)(IIS->TotalCachedResponseTime / IIS->CachedResponses) / 10000.0 : 0.0,
  2588. IIS->CachedResponses ? 100 : 0);
  2589. fprintf(procFile,
  2590. "<summary cached='false'>"
  2591. "<rate percent='%1.3f'>%1.3f</rate>"
  2592. "<response_time>%1.3f</response_time>"
  2593. "<component name='UL'>%1.1f</component>"
  2594. "<component name='W3'>%1.1f</component>"
  2595. "<component name='W3Fltr'>%1.1f</component>"
  2596. "<component name='ISAPI'>%1.1f</component>"
  2597. "<component name='ASP'>%1.1f</component>"
  2598. "<component name='CGI'>%1.1f</component>"
  2599. "</summary>\n",
  2600. ((double)(IIS->TotalRequests - IIS->CachedResponses) / ((double)IIS->TotalRequests)) * 100.0,
  2601. Duration ? (double)(IIS->TotalRequests - IIS->CachedResponses) / (double)Duration : 0.0,
  2602. (IIS->TotalRequests - IIS->CachedResponses) ? ((double)IIS->TotalNonCachedResponseTime / (double)(IIS->TotalRequests - IIS->CachedResponses)) / 10000.0 : 0.0,
  2603. ((IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalFileULOnlyResponseTime + IIS->TotalCGIULOnlyResponseTime + IIS->TotalASPULOnlyResponseTime + IIS->TotalErrorULOnlyResponseTime) / (double)(IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
  2604. ((IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalFileW3OnlyResponseTime + IIS->TotalCGIW3OnlyResponseTime + IIS->TotalASPW3OnlyResponseTime + IIS->TotalErrorW3OnlyResponseTime) / (double)(IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
  2605. ((IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalW3FilterResponseTime) / (double)(IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
  2606. ((IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalASPISAPIOnlyResponseTime) / (double)(IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
  2607. ((IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalASPOnlyResponseTime) / (double)(IIS->TotalNonCachedResponseTime)) * 100.0: 0.0),
  2608. ((IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalCGIOnlyResponseTime) / (double)(IIS->TotalNonCachedResponseTime)) * 100.0: 0.0));
  2609. fprintf(procFile,
  2610. "<summary type='totals'>"
  2611. "<rate>%1.3f</rate>"
  2612. "<response_time>%1.3f</response_time>"
  2613. "<component name='UL'>%1.1f</component>"
  2614. "<component name='W3'>%1.1f</component>"
  2615. "<component name='W3Fltr'>%1.1f</component>"
  2616. "<component name='ISAPI'>%1.1f</component>"
  2617. "<component name='ASP'>%1.1f</component>"
  2618. "<component name='CGI'>%1.1f</component>"
  2619. "</summary>\n",
  2620. Duration ? (double)(IIS->TotalRequests) / (double)Duration : 0.0,
  2621. ((double)(IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime) / (double)IIS->TotalRequests) / 10000.0,
  2622. ((IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalCachedResponseTime + IIS->TotalFileULOnlyResponseTime + IIS->TotalCGIULOnlyResponseTime + IIS->TotalASPULOnlyResponseTime + IIS->TotalErrorULOnlyResponseTime) / (double)(IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
  2623. ((IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalFileW3OnlyResponseTime + IIS->TotalCGIW3OnlyResponseTime + IIS->TotalASPW3OnlyResponseTime + IIS->TotalErrorW3OnlyResponseTime) / (double)(IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
  2624. ((IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalW3FilterResponseTime) / (double)(IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
  2625. ((IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalASPISAPIOnlyResponseTime) / (double)(IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
  2626. ((IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalASPOnlyResponseTime) / (double)(IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0),
  2627. ((IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime) ? ((double)(IIS->TotalCGIOnlyResponseTime) / (double)(IIS->TotalCachedResponseTime + IIS->TotalNonCachedResponseTime)) * 100.0 : 0.0));
  2628. fprintf(procFile, "</table>\n");
  2629. if (PrintCPUUsage) {
  2630. fprintf(procFile, "<table title='Http Requests CPU Time Usage Statistics'>\n");
  2631. fprintf(procFile,
  2632. "<requests cached='true' type='Static HTTP'>"
  2633. "<rate>%1.3f</rate>"
  2634. "<cpu>%1.1f</cpu>"
  2635. "<component name='UL'>%3d.0</component>"
  2636. "<component name='W3'>0.0</component>"
  2637. "<component name='W3Fltr'>0.0</component>"
  2638. "<component name='ISAPI'>0.0</component>"
  2639. "<component name='ASP'>0.0</component>"
  2640. "<component name='CGI'>0.0</component>"
  2641. "</requests>\n",
  2642. Duration ? (double)(IIS->CachedResponses) / (double)Duration : 0.0,
  2643. MilDuration ? (((double)(IIS->CachedCPUTime) / (double)MilDuration) * 100.0) : 0.0,
  2644. IIS->CachedResponses ? 100 : 0);
  2645. fprintf(procFile,
  2646. "<requests cached='false' type='ASP'>"
  2647. "<rate>%1.3f</rate>"
  2648. "<cpu>%1.1f</cpu>"
  2649. "<component name='UL'>%1.1f</component>"
  2650. "<component name='W3'>%1.1f</component>"
  2651. "<component name='W3Fltr'>%1.1f</component>"
  2652. "<component name='ISAPI'>%1.1f</component>"
  2653. "<component name='ASP'>%1.1f</component>"
  2654. "<component name='CGI'>%1.1f</component>"
  2655. "</requests>\n",
  2656. Duration ? (double)(IIS->W3ISAPIRequests) / (double)Duration : 0.0,
  2657. MilDuration ? (((double)(IIS->ISAPICPUTime) / (double)MilDuration) * 100.0) : 0.0,
  2658. ((IIS->ASPCPUTime) ? ((double)(IIS->TotalASPULOnlyCPUTime) / (double)(IIS->ASPCPUTime)) * 100.0 : 0.0),
  2659. ((IIS->ASPCPUTime) ? ((double)(IIS->TotalASPW3OnlyCPUTime) / (double)(IIS->ASPCPUTime)) * 100.0 : 0.0),
  2660. ((IIS->ASPCPUTime) ? ((double)(IIS->TotalASPW3FilterCPUTime) / (double)(IIS->ASPCPUTime)) * 100.0 : 0.0),
  2661. ((IIS->ASPCPUTime) ? ((double)(IIS->TotalASPISAPIOnlyCPUTime) / (double)(IIS->ASPCPUTime)) * 100.0 : 0.0),
  2662. ((IIS->ASPCPUTime) ? ((double)(IIS->TotalASPOnlyCPUTime) / (double)(IIS->ASPCPUTime)) * 100.0: 0.0),
  2663. 0.0);
  2664. fprintf(procFile,
  2665. "<requests cached='false' type='Static HTTP'>"
  2666. "<rate>%1.3f</rate>"
  2667. "<cpu>%1.1f</cpu>"
  2668. "<component name='UL'>%1.1f</component>"
  2669. "<component name='W3'>%1.1f</component>"
  2670. "<component name='W3Fltr'>%1.1f</component>"
  2671. "<component name='ISAPI'>%1.1f</component>"
  2672. "<component name='ASP'>%1.1f</component>"
  2673. "<component name='CGI'>%1.1f</component>"
  2674. "</requests>\n",
  2675. Duration ? (double)(IIS->W3FileRequests) / (double)Duration : 0.0,
  2676. MilDuration ? (((double)(IIS->FileCPUTime) / (double)MilDuration) * 100.0) : 0.0,
  2677. ((IIS->FileCPUTime) ? ((double)(IIS->TotalFileULOnlyCPUTime) / (double)(IIS->FileCPUTime)) * 100.0 : 0.0),
  2678. ((IIS->FileCPUTime) ? ((double)(IIS->TotalFileW3OnlyCPUTime) / (double)(IIS->FileCPUTime)) * 100.0 : 0.0),
  2679. ((IIS->FileCPUTime) ? ((double)(IIS->TotalFileW3FilterCPUTime) / (double)(IIS->FileCPUTime)) * 100.0 : 0.0),
  2680. 0.0,
  2681. 0.0,
  2682. 0.0);
  2683. fprintf(procFile,
  2684. "<requests cached='false' type='CGI'>"
  2685. "<rate>%1.3f</rate>"
  2686. "<cpu>%1.1f</cpu>"
  2687. "<component name='UL'>%1.1f</component>"
  2688. "<component name='W3'>%1.1f</component>"
  2689. "<component name='W3Fltr'>%1.1f</component>"
  2690. "<component name='ISAPI'>%1.1f</component>"
  2691. "<component name='ASP'>%1.1f</component>"
  2692. "<component name='CGI'>%1.1f</component>"
  2693. "</requests>\n",
  2694. Duration ? (double)(IIS->W3CGIRequests) / (double)Duration : 0.0,
  2695. MilDuration ? (((double)(IIS->CGICPUTime) / (double)MilDuration) * 100.0) : 0.0,
  2696. ((IIS->CGICPUTime) ? ((double)(IIS->TotalCGIULOnlyCPUTime) / (double)(IIS->CGICPUTime)) * 100.0 : 0.0),
  2697. ((IIS->CGICPUTime) ? ((double)(IIS->TotalCGIW3OnlyCPUTime) / (double)(IIS->CGICPUTime)) * 100.0 : 0.0),
  2698. ((IIS->CGICPUTime) ? ((double)(IIS->TotalCGIW3FilterCPUTime) / (double)(IIS->CGICPUTime)) * 100.0 : 0.0),
  2699. 0.0,
  2700. 0.0,
  2701. ((IIS->CGICPUTime) ? ((double)(IIS->TotalCGIOnlyCPUTime) / (double)(IIS->CGICPUTime)) * 100.0 : 0.0));
  2702. if (IIS->W3Error != 0) {
  2703. fprintf(procFile,
  2704. "<requests cached='false' type='Error'>"
  2705. "<rate>%1.3f</rate>"
  2706. "<cpu>%1.1f</cpu>"
  2707. "<component name='UL'>%1.1f</component>"
  2708. "<component name='W3'>%1.1f</component>"
  2709. "<component name='W3Fltr'>%1.1f</component>"
  2710. "<component name='ISAPI'>%1.1f</component>"
  2711. "<component name='ASP'>%1.1f</component>"
  2712. "<component name='CGI'>%1.1f</component>"
  2713. "</requests>\n",
  2714. Duration ? (double)(IIS->W3Error) / (double)Duration : 0.0,
  2715. MilDuration ? (((double)(IIS->ErrorCPUTime) / (double)MilDuration) * 100.0) : 0.0,
  2716. ((IIS->ErrorCPUTime) ? ((double)(IIS->TotalErrorULOnlyCPUTime) / (double)(IIS->ErrorCPUTime)) * 100.0 : 0.0),
  2717. ((IIS->ErrorCPUTime) ? ((double)(IIS->TotalErrorW3OnlyCPUTime) / (double)(IIS->ErrorCPUTime)) * 100.0 : 0.0),
  2718. ((IIS->ErrorCPUTime) ? ((double)(IIS->TotalErrorW3FilterCPUTime) / (double)(IIS->ErrorCPUTime)) * 100.0 : 0.0),
  2719. 0.0,
  2720. 0.0,
  2721. 0.0);
  2722. }
  2723. fprintf(procFile,
  2724. "<summary cached='true'>"
  2725. "<rate>%1.3f</rate>"
  2726. "<cpu>%1.1f</cpu>"
  2727. "<component name='UL'>%3d.0</component>"
  2728. "<component name='W3'>0.0</component>"
  2729. "<component name='W3Fltr'>0.0</component>"
  2730. "<component name='ISAPI'>0.0</component>"
  2731. "<component name='ASP'>0.0</component>"
  2732. "<component name='CGI'>0.0</component>"
  2733. "</summary>\n",
  2734. Duration ? (double)(IIS->CachedResponses) / (double)Duration : 0.0,
  2735. MilDuration ? (((double)(IIS->CachedCPUTime) / (double)MilDuration) * 100.0) : 0.0,
  2736. IIS->CachedResponses ? 100 : 0);
  2737. fprintf(procFile,
  2738. "<summary cached='false'>"
  2739. "<rate percent='%1.1f'>%1.3f</rate>"
  2740. "<cpu>%1.1f</cpu>"
  2741. "<component name='UL'>%1.1f</component>"
  2742. "<component name='W3'>%1.1f</component>"
  2743. "<component name='W3Fltr'>%1.1f</component>"
  2744. "<component name='ISAPI'>%1.1f</component>"
  2745. "<component name='ASP'>%1.1f</component>"
  2746. "<component name='CGI'>%1.1f</component>"
  2747. "</summary>\n",
  2748. ((double)(IIS->TotalRequests - IIS->CachedResponses) / ((double)IIS->TotalRequests)) * 100.0,
  2749. Duration ? (double)(IIS->TotalRequests - IIS->CachedResponses) / (double)Duration : 0.0,
  2750. MilDuration ? (((double)(IIS->NonCachedCPUTime) / (double)MilDuration) * 100.0) : 0.0,
  2751. ((IIS->NonCachedCPUTime) ? ((double)(IIS->TotalFileULOnlyCPUTime + IIS->TotalCGIULOnlyCPUTime + IIS->TotalASPULOnlyCPUTime + IIS->TotalErrorULOnlyCPUTime) / (double)(IIS->NonCachedCPUTime)) * 100.0 : 0.0),
  2752. ((IIS->NonCachedCPUTime) ? ((double)(IIS->TotalFileW3OnlyCPUTime + IIS->TotalCGIW3OnlyCPUTime + IIS->TotalASPW3OnlyCPUTime + IIS->TotalErrorW3OnlyCPUTime) / (double)(IIS->NonCachedCPUTime)) * 100.0 : 0.0),
  2753. ((IIS->NonCachedCPUTime) ? ((double)(IIS->TotalW3FilterCPUTime) / (double)(IIS->NonCachedCPUTime)) * 100.0 : 0.0),
  2754. ((IIS->NonCachedCPUTime) ? ((double)(IIS->TotalASPISAPIOnlyCPUTime) / (double)(IIS->NonCachedCPUTime)) * 100.0 : 0.0),
  2755. ((IIS->NonCachedCPUTime) ? ((double)(IIS->TotalASPOnlyCPUTime) / (double)(IIS->NonCachedCPUTime)) * 100.0: 0.0),
  2756. ((IIS->NonCachedCPUTime) ? ((double)(IIS->TotalCGIOnlyCPUTime) / (double)(IIS->NonCachedCPUTime)) * 100.0: 0.0));
  2757. fprintf(procFile,
  2758. "<summary type='totals'>"
  2759. "<rate>%1.3f</rate>"
  2760. "<cpu>%1.1f</cpu>"
  2761. "<component name='UL'>%1.1f</component>"
  2762. "<component name='W3'>%1.1f</component>"
  2763. "<component name='W3Fltr'>%1.1f</component>"
  2764. "<component name='ISAPI'>%1.1f</component>"
  2765. "<component name='ASP'>%1.1f</component>"
  2766. "<component name='CGI'>%1.1f</component>"
  2767. "</summary>\n",
  2768. Duration ? (double)IIS->TotalRequests / (double)Duration : 0.0,
  2769. MilDuration ? (((double)(IIS->TotalCPUTime) / (double)MilDuration) * 100.0) : 0.0,
  2770. ((IIS->TotalCPUTime) ? ((double)(IIS->CachedCPUTime + IIS->TotalFileULOnlyCPUTime + IIS->TotalCGIULOnlyCPUTime + IIS->TotalASPULOnlyCPUTime + IIS->TotalErrorULOnlyCPUTime) / (double)(IIS->TotalCPUTime)) * 100.0 : 0.0),
  2771. ((IIS->TotalCPUTime) ? ((double)(IIS->TotalFileW3OnlyCPUTime + IIS->TotalCGIW3OnlyCPUTime + IIS->TotalASPW3OnlyCPUTime + IIS->TotalErrorW3OnlyCPUTime) / (double)(IIS->TotalCPUTime)) * 100.0 : 0.0),
  2772. ((IIS->TotalCPUTime) ? ((double)(IIS->TotalW3FilterCPUTime) / (double)(IIS->TotalCPUTime)) * 100.0 : 0.0),
  2773. ((IIS->TotalCPUTime) ? ((double)(IIS->TotalASPISAPIOnlyCPUTime) / (double)(IIS->TotalCPUTime)) * 100.0 : 0.0),
  2774. ((IIS->TotalCPUTime) ? ((double)(IIS->TotalASPOnlyCPUTime) / (double)(IIS->TotalCPUTime)) * 100.0: 0.0),
  2775. ((IIS->TotalCPUTime) ? ((double)(IIS->TotalCGIOnlyCPUTime) / (double)(IIS->TotalCPUTime)) * 100.0: 0.0));
  2776. fprintf(procFile, "</table>\n");
  2777. }
  2778. RtlZeroMemory(TopHitURLs, sizeof(URL_RECORD) * DISPLAY_SIZE);
  2779. RtlZeroMemory(TopHitStaticURLs, sizeof(URL_RECORD) * DISPLAY_SIZE);
  2780. RtlZeroMemory(TopSlowURLs, sizeof(URL_RECORD) * DISPLAY_SIZE);
  2781. RtlZeroMemory(TopConsumingURLs, sizeof(URL_RECORD) * DISPLAY_SIZE);
  2782. RtlZeroMemory(TopBytesURLs, sizeof(URL_RECORD) * DISPLAY_SIZE);
  2783. for (k = 0; k < URL_HASH_TABLESIZE; k++) {
  2784. pUrl = GetHeadUrlRecord(k);
  2785. while (pUrl != NULL) {
  2786. ULONGLONG AverageURLResponseTime = 0;
  2787. ULONG Found;
  2788. URL_RECORD tmpUrl1, tmpUrl2;
  2789. if (pUrl->Requests != 0) {
  2790. RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
  2791. RtlZeroMemory(&tmpUrl2, sizeof(URL_RECORD));
  2792. Found = FALSE;
  2793. for (i = 0; i < DISPLAY_SIZE; i++) {
  2794. if (Found && tmpUrl1.Requests != 0) {
  2795. RtlCopyMemory(&tmpUrl2, &TopHitURLs[i], sizeof(URL_RECORD));
  2796. RtlCopyMemory(&TopHitURLs[i], &tmpUrl1, sizeof(URL_RECORD));
  2797. RtlCopyMemory(&tmpUrl1, &tmpUrl2, sizeof(URL_RECORD));
  2798. }
  2799. else if (!Found) {
  2800. if (TopHitURLs[i].Requests == 0) {
  2801. RtlCopyMemory(&TopHitURLs[i], pUrl, sizeof(URL_RECORD));
  2802. TopHitURLs[i].URL = CopyUrlStr(pUrl->URL);
  2803. if (TopHitURLs[i].URL != NULL) {
  2804. Found = TRUE;
  2805. }
  2806. else {
  2807. RtlZeroMemory(&TopHitURLs[i], sizeof(URL_RECORD));
  2808. }
  2809. }
  2810. else if (pUrl->Requests > TopHitURLs[i].Requests) {
  2811. RtlCopyMemory(&tmpUrl1, &TopHitURLs[i], sizeof(URL_RECORD));
  2812. RtlCopyMemory(&TopHitURLs[i], pUrl, sizeof(URL_RECORD));
  2813. TopHitURLs[i].URL = CopyUrlStr(pUrl->URL);
  2814. if (TopHitURLs[i].URL != NULL) {
  2815. Found = TRUE;
  2816. }
  2817. else {
  2818. RtlCopyMemory(&TopHitURLs[i], &tmpUrl1, sizeof(URL_RECORD));
  2819. RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
  2820. }
  2821. }
  2822. }
  2823. }
  2824. if (tmpUrl1.Requests != 0) {
  2825. free(tmpUrl1.URL);
  2826. }
  2827. RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
  2828. RtlZeroMemory(&tmpUrl2, sizeof(URL_RECORD));
  2829. Found = FALSE;
  2830. for (i = 0; i < DISPLAY_SIZE; i++) {
  2831. if (Found && tmpUrl1.Requests != 0) {
  2832. RtlCopyMemory(&tmpUrl2, &TopHitStaticURLs[i], sizeof(URL_RECORD));
  2833. RtlCopyMemory(&TopHitStaticURLs[i], &tmpUrl1, sizeof(URL_RECORD));
  2834. RtlCopyMemory(&tmpUrl1, &tmpUrl2, sizeof(URL_RECORD));
  2835. }
  2836. else if (!Found) {
  2837. if ((pUrl->UrlType == EVENT_TRACE_TYPE_W3CORE_FILEREQ || pUrl->Hits > 0) &&
  2838. TopHitStaticURLs[i].Requests == 0) {
  2839. RtlCopyMemory(&TopHitStaticURLs[i], pUrl, sizeof(URL_RECORD));
  2840. TopHitStaticURLs[i].URL = CopyUrlStr(pUrl->URL);
  2841. if (TopHitStaticURLs[i].URL != NULL) {
  2842. Found = TRUE;
  2843. }
  2844. else {
  2845. RtlZeroMemory(&TopHitStaticURLs[i], sizeof(URL_RECORD));
  2846. }
  2847. }
  2848. else if ((pUrl->UrlType == EVENT_TRACE_TYPE_W3CORE_FILEREQ || pUrl->Hits > 0) &&
  2849. pUrl->Requests > TopHitStaticURLs[i].Requests) {
  2850. RtlCopyMemory(&tmpUrl1, &TopHitStaticURLs[i], sizeof(URL_RECORD));
  2851. RtlCopyMemory(&TopHitStaticURLs[i], pUrl, sizeof(URL_RECORD));
  2852. TopHitStaticURLs[i].URL = CopyUrlStr(pUrl->URL);
  2853. if (TopHitStaticURLs[i].URL != NULL) {
  2854. Found = TRUE;
  2855. }
  2856. else {
  2857. RtlCopyMemory(&TopHitStaticURLs[i], &tmpUrl1, sizeof(URL_RECORD));
  2858. RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
  2859. }
  2860. }
  2861. }
  2862. }
  2863. if (tmpUrl1.Requests != 0) {
  2864. free(tmpUrl1.URL);
  2865. }
  2866. AverageURLResponseTime = pUrl->TotalResponseTime / pUrl->Requests;
  2867. RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
  2868. RtlZeroMemory(&tmpUrl2, sizeof(URL_RECORD));
  2869. Found = FALSE;
  2870. for (i = 0; i < DISPLAY_SIZE; i++) {
  2871. if (Found && tmpUrl1.Requests != 0) {
  2872. RtlCopyMemory(&tmpUrl2, &TopSlowURLs[i], sizeof(URL_RECORD));
  2873. RtlCopyMemory(&TopSlowURLs[i], &tmpUrl1, sizeof(URL_RECORD));
  2874. RtlCopyMemory(&tmpUrl1, &tmpUrl2, sizeof(URL_RECORD));
  2875. }
  2876. else if (!Found) {
  2877. if (TopSlowURLs[i].Requests == 0) {
  2878. RtlCopyMemory(&TopSlowURLs[i], pUrl, sizeof(URL_RECORD));
  2879. TopSlowURLs[i].URL = CopyUrlStr(pUrl->URL);
  2880. if (TopSlowURLs[i].URL != NULL) {
  2881. Found = TRUE;
  2882. }
  2883. else {
  2884. RtlZeroMemory(&TopSlowURLs[i], sizeof(URL_RECORD));
  2885. }
  2886. }
  2887. else if (AverageURLResponseTime > (TopSlowURLs[i].TotalResponseTime / TopSlowURLs[i].Requests)) {
  2888. RtlCopyMemory(&tmpUrl1, &TopSlowURLs[i], sizeof(URL_RECORD));
  2889. RtlCopyMemory(&TopSlowURLs[i], pUrl, sizeof(URL_RECORD));
  2890. TopSlowURLs[i].URL = CopyUrlStr(pUrl->URL);
  2891. if (TopSlowURLs[i].URL != NULL) {
  2892. Found = TRUE;
  2893. }
  2894. else {
  2895. RtlCopyMemory(&TopSlowURLs[i], &tmpUrl1, sizeof(URL_RECORD));
  2896. RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
  2897. }
  2898. }
  2899. }
  2900. }
  2901. if (tmpUrl1.Requests != 0) {
  2902. free(tmpUrl1.URL);
  2903. }
  2904. RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
  2905. RtlZeroMemory(&tmpUrl2, sizeof(URL_RECORD));
  2906. Found = FALSE;
  2907. for (i = 0; i < DISPLAY_SIZE; i++) {
  2908. if (Found && tmpUrl1.Requests != 0) {
  2909. RtlCopyMemory(&tmpUrl2, &TopConsumingURLs[i], sizeof(URL_RECORD));
  2910. RtlCopyMemory(&TopConsumingURLs[i], &tmpUrl1, sizeof(URL_RECORD));
  2911. RtlCopyMemory(&tmpUrl1, &tmpUrl2, sizeof(URL_RECORD));
  2912. }
  2913. else if (!Found) {
  2914. if (TopConsumingURLs[i].Requests == 0) {
  2915. RtlCopyMemory(&TopConsumingURLs[i], pUrl, sizeof(URL_RECORD));
  2916. TopConsumingURLs[i].URL = CopyUrlStr(pUrl->URL);
  2917. if (TopConsumingURLs[i].URL != NULL) {
  2918. Found = TRUE;
  2919. }
  2920. else {
  2921. RtlZeroMemory(&TopConsumingURLs[i], sizeof(URL_RECORD));
  2922. }
  2923. }
  2924. else if ((pUrl->KCPUTime + pUrl->UCPUTime) > (TopConsumingURLs[i].KCPUTime + TopConsumingURLs[i].UCPUTime)) {
  2925. RtlCopyMemory(&tmpUrl1, &TopConsumingURLs[i], sizeof(URL_RECORD));
  2926. RtlCopyMemory(&TopConsumingURLs[i], pUrl, sizeof(URL_RECORD));
  2927. TopConsumingURLs[i].URL = CopyUrlStr(pUrl->URL);
  2928. if (TopConsumingURLs[i].URL != NULL) {
  2929. Found = TRUE;
  2930. }
  2931. else {
  2932. RtlCopyMemory(&TopConsumingURLs[i], &tmpUrl1, sizeof(URL_RECORD));
  2933. RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
  2934. }
  2935. }
  2936. }
  2937. }
  2938. if (tmpUrl1.Requests != 0) {
  2939. free(tmpUrl1.URL);
  2940. }
  2941. RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
  2942. RtlZeroMemory(&tmpUrl2, sizeof(URL_RECORD));
  2943. Found = FALSE;
  2944. for (i = 0; i < DISPLAY_SIZE; i++) {
  2945. if (Found && tmpUrl1.Requests != 0) {
  2946. RtlCopyMemory(&tmpUrl2, &TopBytesURLs[i], sizeof(URL_RECORD));
  2947. RtlCopyMemory(&TopBytesURLs[i], &tmpUrl1, sizeof(URL_RECORD));
  2948. RtlCopyMemory(&tmpUrl1, &tmpUrl2, sizeof(URL_RECORD));
  2949. }
  2950. else if (!Found) {
  2951. if (TopBytesURLs[i].Requests == 0) {
  2952. RtlCopyMemory(&TopBytesURLs[i], pUrl, sizeof(URL_RECORD));
  2953. TopBytesURLs[i].URL = CopyUrlStr(pUrl->URL);
  2954. if (TopBytesURLs[i].URL != NULL) {
  2955. Found = TRUE;
  2956. }
  2957. else {
  2958. RtlZeroMemory(&TopBytesURLs[i], sizeof(URL_RECORD));
  2959. }
  2960. }
  2961. else if (pUrl->BytesSent > TopBytesURLs[i].BytesSent) {
  2962. RtlCopyMemory(&tmpUrl1, &TopBytesURLs[i], sizeof(URL_RECORD));
  2963. RtlCopyMemory(&TopBytesURLs[i], pUrl, sizeof(URL_RECORD));
  2964. TopBytesURLs[i].URL = CopyUrlStr(pUrl->URL);
  2965. if (TopBytesURLs[i].URL != NULL) {
  2966. Found = TRUE;
  2967. }
  2968. else {
  2969. RtlCopyMemory(&TopBytesURLs[i], &tmpUrl1, sizeof(URL_RECORD));
  2970. RtlZeroMemory(&tmpUrl1, sizeof(URL_RECORD));
  2971. }
  2972. }
  2973. }
  2974. }
  2975. if (tmpUrl1.Requests != 0) {
  2976. free(tmpUrl1.URL);
  2977. }
  2978. }
  2979. if (pUrl->URL) {
  2980. free(pUrl->URL);
  2981. }
  2982. free(pUrl);
  2983. pUrl = GetHeadUrlRecord(k);
  2984. }
  2985. }
  2986. fprintf( procFile, "<table title='Most Requested URLs' top='%d'>", DISPLAY_SIZE);
  2987. for (i = 0; i < DISPLAY_SIZE && TopHitURLs[i].Requests != 0; i++) {
  2988. ULONGLONG AverageURLResponseTime = 0;
  2989. CHAR ReducedUrl[URL_NAME_COLUMN_SIZE + 1];
  2990. char* strPrint;
  2991. if (TopHitURLs[i].Requests != 0) {
  2992. AverageURLResponseTime = TopHitURLs[i].TotalResponseTime / TopHitURLs[i].Requests;
  2993. }
  2994. RemoveCtrlCharA(TopHitURLs[i].URL, strlen(TopHitURLs[i].URL));
  2995. if (strlen(TopHitURLs[i].URL) > URL_NAME_COLUMN_SIZE) {
  2996. ReduceStringA(ReducedUrl, URL_NAME_COLUMN_SIZE + 1, TopHitURLs[i].URL);
  2997. strPrint = ReducedUrl;
  2998. }else{
  2999. strPrint = TopHitURLs[i].URL;
  3000. }
  3001. fprintf(procFile,
  3002. "<url name='%s'>"
  3003. "<site_id>%d</site_id>"
  3004. "<rate>%1.3f</rate>"
  3005. "<cache_hit>%1.1f</cache_hit>"
  3006. "<response_time>%1.1f</response_time>"
  3007. "</url>\n",
  3008. strPrint,
  3009. TopHitURLs[i].SiteId,
  3010. (Duration ? ((double)TopHitURLs[i].Requests / (double)Duration) : 0.0),
  3011. TopHitURLs[i].Requests ? ((double)TopHitURLs[i].Hits / (double)TopHitURLs[i].Requests * 100.0) : 0.0,
  3012. ((double)AverageURLResponseTime) / 10000.0);
  3013. }
  3014. fprintf( procFile, "</table>\n" );
  3015. fprintf(procFile, "<table title='Most Requested Static URLs' top='%d'>\n", DISPLAY_SIZE);
  3016. for (i = 0; i < DISPLAY_SIZE && TopHitStaticURLs[i].Requests != 0; i++) {
  3017. char* strPrint;
  3018. ULONGLONG AverageURLResponseTime = 0;
  3019. CHAR ReducedUrl[URL_NAME_COLUMN_SIZE + 1];
  3020. if (TopHitStaticURLs[i].Requests != 0) {
  3021. AverageURLResponseTime = TopHitStaticURLs[i].TotalResponseTime / TopHitStaticURLs[i].Requests;
  3022. }
  3023. RemoveCtrlCharA(TopHitStaticURLs[i].URL, strlen(TopHitStaticURLs[i].URL));
  3024. if (strlen(TopHitStaticURLs[i].URL) > URL_NAME_COLUMN_SIZE) {
  3025. ReduceStringA(ReducedUrl, URL_NAME_COLUMN_SIZE + 1, TopHitStaticURLs[i].URL);
  3026. strPrint = ReducedUrl;
  3027. }else{
  3028. strPrint = TopHitStaticURLs[i].URL;
  3029. }
  3030. fprintf(procFile,
  3031. "<url name='%s'>"
  3032. "<site_id>%d</site_id>"
  3033. "<rate>%1.3f</rate>"
  3034. "<cache_hit>%1.1f</cache_hit>"
  3035. "<response_time>%1.1f</response_time>"
  3036. "</url>\n",
  3037. strPrint,
  3038. TopHitStaticURLs[i].SiteId,
  3039. (Duration ? ((double)TopHitStaticURLs[i].Requests / (double)Duration) : 0.0),
  3040. TopHitStaticURLs[i].Requests ? ((double)TopHitStaticURLs[i].Hits / (double)TopHitStaticURLs[i].Requests * 100.0) : 0.0,
  3041. ((double)AverageURLResponseTime) / 10000.0);
  3042. }
  3043. fprintf(procFile, "</table>\n");
  3044. fprintf(procFile, "<table title='Slowest URLs' top='%d'>\n", DISPLAY_SIZE );
  3045. for (i = 0; i < DISPLAY_SIZE && TopSlowURLs[i].Requests != 0; i++) {
  3046. char* strPrint;
  3047. ULONGLONG AverageURLResponseTime = 0;
  3048. CHAR ReducedUrl[URL_NAME_COLUMN_SIZE + 1];
  3049. if (TopSlowURLs[i].Requests != 0) {
  3050. AverageURLResponseTime = TopSlowURLs[i].TotalResponseTime / TopSlowURLs[i].Requests;
  3051. }
  3052. RemoveCtrlCharA(TopSlowURLs[i].URL, strlen(TopSlowURLs[i].URL));
  3053. if (strlen(TopSlowURLs[i].URL) > URL_NAME_COLUMN_SIZE) {
  3054. ReduceStringA(ReducedUrl, URL_NAME_COLUMN_SIZE + 1, TopSlowURLs[i].URL);
  3055. strPrint = ReducedUrl;
  3056. }else{
  3057. strPrint = TopSlowURLs[i].URL;
  3058. }
  3059. fprintf(procFile,
  3060. "<url name='%s'>"
  3061. "<site_id>%d</site_id>"
  3062. "<rate>%1.3f</rate>"
  3063. "<cache_hit>%1.1f</cache_hit>"
  3064. "<response_time>%1.1f</response_time>"
  3065. "</url>\n",
  3066. strPrint,
  3067. TopSlowURLs[i].SiteId,
  3068. (Duration ? ((double)TopSlowURLs[i].Requests / (double)Duration) : 0.0),
  3069. TopSlowURLs[i].Requests ? ((double)TopSlowURLs[i].Hits / (double)TopSlowURLs[i].Requests * 100.0) : 0.0,
  3070. ((double)AverageURLResponseTime) / 10000.0);
  3071. }
  3072. fprintf(procFile, "</table>\n" );
  3073. if (PrintCPUUsage) {
  3074. fprintf(procFile, "<table title='URLs with the Most CPU Usage' top='%d'>\n", DISPLAY_SIZE);
  3075. for (i = 0; i < DISPLAY_SIZE && TopConsumingURLs[i].Requests != 0; i++) {
  3076. char* strPrint;
  3077. CHAR ReducedUrl[URL_NAME_COLUMN_SIZE + 1];
  3078. RemoveCtrlCharA(TopConsumingURLs[i].URL, strlen(TopConsumingURLs[i].URL));
  3079. if (strlen(TopConsumingURLs[i].URL) > URL_NAME_COLUMN_SIZE) {
  3080. ReduceStringA(ReducedUrl, URL_NAME_COLUMN_SIZE + 1, TopConsumingURLs[i].URL);
  3081. strPrint = ReducedUrl;
  3082. }else{
  3083. strPrint = TopConsumingURLs[i].URL;
  3084. }
  3085. fprintf(procFile,
  3086. "<url name='%s'>"
  3087. "<site_id>%d</site_id>"
  3088. "<rate>%1.3f</rate>"
  3089. "<cpu>%1.2f</cpu>"
  3090. "</url>\n",
  3091. strPrint,
  3092. TopConsumingURLs[i].SiteId,
  3093. (Duration ? ((double)TopConsumingURLs[i].Requests / (double)Duration) : 0.0),
  3094. MilDuration ? ((((double)TopConsumingURLs[i].KCPUTime + (double)TopConsumingURLs[i].UCPUTime) / (double)MilDuration) * 100.0) : 0.0);
  3095. }
  3096. fprintf(procFile, "</table>\n" );
  3097. }
  3098. fprintf(procFile, "<table title='URLs with the Most Bytes Sent' top='%d'>\n", DISPLAY_SIZE);
  3099. for (i = 0; i < DISPLAY_SIZE && TopBytesURLs[i].Requests != 0; i++) {
  3100. char* strPrint;
  3101. CHAR ReducedUrl[URL_NAME_COLUMN_SIZE + 1];
  3102. RemoveCtrlCharA(TopBytesURLs[i].URL, strlen(TopBytesURLs[i].URL));
  3103. if (strlen(TopBytesURLs[i].URL) > URL_NAME_COLUMN_SIZE) {
  3104. ReduceStringA(ReducedUrl, URL_NAME_COLUMN_SIZE + 1, TopBytesURLs[i].URL);
  3105. strPrint = ReducedUrl;
  3106. }else{
  3107. strPrint = TopBytesURLs[i].URL;
  3108. }
  3109. fprintf(procFile,
  3110. "<url name='%s'>"
  3111. "<site_id>%d</site_id>"
  3112. "<rate>%1.3f</rate>"
  3113. "<cache_hit>%1.1f</cache_hit>"
  3114. "<bytes_sent_per_sec>%d</bytes_sent_per_sec>"
  3115. "</url>\n",
  3116. strPrint,
  3117. TopBytesURLs[i].SiteId,
  3118. (Duration ? ((double)TopBytesURLs[i].Requests / (double)Duration) : 0.0),
  3119. TopBytesURLs[i].Requests ? ((double)TopBytesURLs[i].Hits / (double)TopBytesURLs[i].Requests * 100.0) : 0.0,
  3120. Duration ? TopBytesURLs[i].BytesSent/ Duration : 0);
  3121. }
  3122. fprintf(procFile, "</table>\n" );
  3123. for (i = 0; i < DISPLAY_SIZE; i++) {
  3124. if (TopHitURLs[i].Requests != 0 && TopHitURLs[i].URL != NULL) {
  3125. free(TopHitURLs[i].URL);
  3126. }
  3127. if (TopHitStaticURLs[i].Requests != 0 && TopHitStaticURLs[i].URL != NULL) {
  3128. free(TopHitStaticURLs[i].URL);
  3129. }
  3130. if (TopSlowURLs[i].Requests != 0 && TopSlowURLs[i].URL != NULL) {
  3131. free(TopSlowURLs[i].URL);
  3132. }
  3133. if (TopConsumingURLs[i].Requests != 0 && TopConsumingURLs[i].URL != NULL) {
  3134. free(TopConsumingURLs[i].URL);
  3135. }
  3136. if (TopBytesURLs[i].Requests != 0 && TopBytesURLs[i].URL != NULL) {
  3137. free(TopBytesURLs[i].URL);
  3138. }
  3139. }
  3140. RtlZeroMemory(TopHitClients, sizeof(CLIENT_RECORD) * DISPLAY_SIZE);
  3141. RtlZeroMemory(TopSlowClients, sizeof(CLIENT_RECORD) * DISPLAY_SIZE);
  3142. pClient = GetHeadClientRecord();
  3143. while (pClient != NULL) {
  3144. ULONGLONG AverageClientResponseTime = 0;
  3145. ULONG Found;
  3146. CLIENT_RECORD tmpClient1, tmpClient2;
  3147. if (pClient->Requests != 0) {
  3148. RtlZeroMemory(&tmpClient1, sizeof(CLIENT_RECORD));
  3149. RtlZeroMemory(&tmpClient2, sizeof(CLIENT_RECORD));
  3150. Found = FALSE;
  3151. for (i = 0; i < DISPLAY_SIZE; i++) {
  3152. if (Found && tmpClient1.Requests != 0) {
  3153. RtlCopyMemory(&tmpClient2, &TopHitClients[i], sizeof(CLIENT_RECORD));
  3154. RtlCopyMemory(&TopHitClients[i], &tmpClient1, sizeof(CLIENT_RECORD));
  3155. RtlCopyMemory(&tmpClient1, &tmpClient2, sizeof(CLIENT_RECORD));
  3156. }
  3157. else if (!Found) {
  3158. if (TopHitClients[i].Requests == 0) {
  3159. RtlCopyMemory(&TopHitClients[i], pClient, sizeof(CLIENT_RECORD));
  3160. Found = TRUE;
  3161. }
  3162. else if (pClient->Requests > TopHitClients[i].Requests) {
  3163. RtlCopyMemory(&tmpClient1, &TopHitClients[i], sizeof(CLIENT_RECORD));
  3164. RtlCopyMemory(&TopHitClients[i], pClient, sizeof(CLIENT_RECORD));
  3165. Found = TRUE;
  3166. }
  3167. }
  3168. }
  3169. AverageClientResponseTime = pClient->TotalResponseTime / pClient->Requests;
  3170. RtlZeroMemory(&tmpClient1, sizeof(CLIENT_RECORD));
  3171. RtlZeroMemory(&tmpClient2, sizeof(CLIENT_RECORD));
  3172. Found = FALSE;
  3173. for (i = 0; i < DISPLAY_SIZE; i++) {
  3174. if (Found && tmpClient1.Requests != 0) {
  3175. RtlCopyMemory(&tmpClient2, &TopSlowClients[i], sizeof(CLIENT_RECORD));
  3176. RtlCopyMemory(&TopSlowClients[i], &tmpClient1, sizeof(CLIENT_RECORD));
  3177. RtlCopyMemory(&tmpClient1, &tmpClient2, sizeof(CLIENT_RECORD));
  3178. }
  3179. else if (!Found) {
  3180. if (TopSlowClients[i].Requests == 0) {
  3181. RtlCopyMemory(&TopSlowClients[i], pClient, sizeof(CLIENT_RECORD));
  3182. Found = TRUE;
  3183. }
  3184. else if (AverageClientResponseTime > (TopSlowClients[i].TotalResponseTime / TopSlowClients[i].Requests)) {
  3185. RtlCopyMemory(&tmpClient1, &TopSlowClients[i], sizeof(CLIENT_RECORD));
  3186. RtlCopyMemory(&TopSlowClients[i], pClient, sizeof(CLIENT_RECORD));
  3187. Found = TRUE;
  3188. }
  3189. }
  3190. }
  3191. }
  3192. free(pClient);
  3193. pClient = GetHeadClientRecord();
  3194. }
  3195. fprintf(procFile, "<table title='Clients with the Most Requests' top='%d'>\n", DISPLAY_SIZE);
  3196. for (i = 0; i < DISPLAY_SIZE && TopHitClients[i].Requests != 0; i++) {
  3197. ULONGLONG AverageClientResponseTime = 0;
  3198. CHAR ipAddrBuffer[MAX_ADDRESS_LENGTH];
  3199. PCHAR pszA = &ipAddrBuffer[0];
  3200. if (TopHitClients[i].Requests != 0) {
  3201. AverageClientResponseTime = TopHitClients[i].TotalResponseTime / TopHitClients[i].Requests;
  3202. }
  3203. DecodeIpAddressA(TopHitClients[i].IpAddrType,
  3204. &TopHitClients[i].IpAddrV4,
  3205. &TopHitClients[i].IpAddrV6[0],
  3206. pszA);
  3207. fprintf(procFile,
  3208. "<client ip='%s'>"
  3209. "<rate>%1.3f</rate>"
  3210. "<cache_hit>%1.1f</cache_hit>"
  3211. "<response_time>%I64u</response_time>"
  3212. "</client>\n",
  3213. ipAddrBuffer,
  3214. (Duration ? ((double)TopHitClients[i].Requests / (double)Duration) : 0.0),
  3215. TopHitClients[i].Requests ? ((double)TopHitClients[i].Hits / (double)TopHitClients[i].Requests * 100.0) : 0.0,
  3216. AverageClientResponseTime / 10000);
  3217. }
  3218. fprintf(procFile, "</table>\n" );
  3219. fprintf(procFile, "<table title='Clients with the Slowest Responses' top='%d'>", DISPLAY_SIZE);
  3220. for (i = 0; i < DISPLAY_SIZE && TopSlowClients[i].Requests != 0; i++) {
  3221. ULONGLONG AverageClientResponseTime = 0;
  3222. CHAR ipAddrBuffer[MAX_ADDRESS_LENGTH];
  3223. PCHAR pszA = &ipAddrBuffer[0];
  3224. if (TopSlowClients[i].Requests != 0) {
  3225. AverageClientResponseTime = TopSlowClients[i].TotalResponseTime / TopSlowClients[i].Requests;
  3226. }
  3227. DecodeIpAddressA(TopHitClients[i].IpAddrType,
  3228. &TopHitClients[i].IpAddrV4,
  3229. &TopHitClients[i].IpAddrV6[0],
  3230. pszA);
  3231. fprintf(procFile,
  3232. "<client ip='%s'>"
  3233. "<rate>%1.3f</rate>"
  3234. "<cache_hit>%1.1f</cache_hit>"
  3235. "<response_time>%I64u</response_time>"
  3236. "</client>\n",
  3237. ipAddrBuffer,
  3238. (Duration ? ((double)TopSlowClients[i].Requests / (double)Duration) : 0.0),
  3239. TopSlowClients[i].Requests ? ((double)TopSlowClients[i].Hits / (double)TopSlowClients[i].Requests * 100.0) : 0.0,
  3240. AverageClientResponseTime / 10000);
  3241. }
  3242. fprintf(procFile, "</table>" );
  3243. RtlZeroMemory(TopHitSites, sizeof(SITE_RECORD) * DISPLAY_SIZE);
  3244. RtlZeroMemory(TopSlowSites, sizeof(SITE_RECORD) * DISPLAY_SIZE);
  3245. RtlZeroMemory(TopConsumingSites, sizeof(SITE_RECORD) * DISPLAY_SIZE);
  3246. RtlZeroMemory(TopBytesSites, sizeof(SITE_RECORD) * DISPLAY_SIZE);
  3247. pSite = GetHeadSiteRecord();
  3248. while (pSite != NULL) {
  3249. ULONGLONG AverageSiteResponseTime = 0;
  3250. ULONG Found;
  3251. SITE_RECORD tmpSite1, tmpSite2;
  3252. if (pSite->Requests != 0) {
  3253. RtlZeroMemory(&tmpSite1, sizeof(SITE_RECORD));
  3254. RtlZeroMemory(&tmpSite2, sizeof(SITE_RECORD));
  3255. Found = FALSE;
  3256. for (i = 0; i < DISPLAY_SIZE; i++) {
  3257. if (Found && tmpSite1.Requests != 0) {
  3258. RtlCopyMemory(&tmpSite2, &TopHitSites[i], sizeof(SITE_RECORD));
  3259. RtlCopyMemory(&TopHitSites[i], &tmpSite1, sizeof(SITE_RECORD));
  3260. RtlCopyMemory(&tmpSite1, &tmpSite2, sizeof(SITE_RECORD));
  3261. }
  3262. else if (!Found) {
  3263. if (TopHitSites[i].Requests == 0) {
  3264. RtlCopyMemory(&TopHitSites[i], pSite, sizeof(SITE_RECORD));
  3265. Found = TRUE;
  3266. }
  3267. else if (pSite->Requests > TopHitSites[i].Requests) {
  3268. RtlCopyMemory(&tmpSite1, &TopHitSites[i], sizeof(SITE_RECORD));
  3269. RtlCopyMemory(&TopHitSites[i], pSite, sizeof(SITE_RECORD));
  3270. Found = TRUE;
  3271. }
  3272. }
  3273. }
  3274. AverageSiteResponseTime = pSite->TotalResponseTime / pSite->Requests;
  3275. RtlZeroMemory(&tmpSite1, sizeof(SITE_RECORD));
  3276. RtlZeroMemory(&tmpSite2, sizeof(SITE_RECORD));
  3277. Found = FALSE;
  3278. for (i = 0; i < DISPLAY_SIZE; i++) {
  3279. if (Found && tmpSite1.Requests != 0) {
  3280. RtlCopyMemory(&tmpSite2, &TopSlowSites[i], sizeof(SITE_RECORD));
  3281. RtlCopyMemory(&TopSlowSites[i], &tmpSite1, sizeof(SITE_RECORD));
  3282. RtlCopyMemory(&tmpSite1, &tmpSite2, sizeof(SITE_RECORD));
  3283. }
  3284. else if (!Found) {
  3285. if (TopSlowSites[i].Requests == 0) {
  3286. RtlCopyMemory(&TopSlowSites[i], pSite, sizeof(SITE_RECORD));
  3287. Found = TRUE;
  3288. }
  3289. else if (AverageSiteResponseTime > (TopSlowSites[i].TotalResponseTime / TopSlowSites[i].Requests)) {
  3290. RtlCopyMemory(&tmpSite1, &TopSlowSites[i], sizeof(SITE_RECORD));
  3291. RtlCopyMemory(&TopSlowSites[i], pSite, sizeof(SITE_RECORD));
  3292. Found = TRUE;
  3293. }
  3294. }
  3295. }
  3296. RtlZeroMemory(&tmpSite1, sizeof(SITE_RECORD));
  3297. RtlZeroMemory(&tmpSite2, sizeof(SITE_RECORD));
  3298. Found = FALSE;
  3299. for (i = 0; i < DISPLAY_SIZE; i++) {
  3300. if (Found && tmpSite1.Requests != 0) {
  3301. RtlCopyMemory(&tmpSite2, &TopConsumingSites[i], sizeof(SITE_RECORD));
  3302. RtlCopyMemory(&TopConsumingSites[i], &tmpSite1, sizeof(SITE_RECORD));
  3303. RtlCopyMemory(&tmpSite1, &tmpSite2, sizeof(SITE_RECORD));
  3304. }
  3305. else if (!Found) {
  3306. if (TopConsumingSites[i].Requests == 0) {
  3307. RtlCopyMemory(&TopConsumingSites[i], pSite, sizeof(SITE_RECORD));
  3308. Found = TRUE;
  3309. }
  3310. else if ((pSite->KCPUTime + pSite->UCPUTime) > (TopConsumingSites[i].KCPUTime + TopConsumingSites[i].UCPUTime)) {
  3311. RtlCopyMemory(&tmpSite1, &TopConsumingSites[i], sizeof(SITE_RECORD));
  3312. RtlCopyMemory(&TopConsumingSites[i], pSite, sizeof(SITE_RECORD));
  3313. Found = TRUE;
  3314. }
  3315. }
  3316. }
  3317. RtlZeroMemory(&tmpSite1, sizeof(SITE_RECORD));
  3318. RtlZeroMemory(&tmpSite2, sizeof(SITE_RECORD));
  3319. Found = FALSE;
  3320. for (i = 0; i < DISPLAY_SIZE; i++) {
  3321. if (Found && tmpSite1.Requests != 0) {
  3322. RtlCopyMemory(&tmpSite2, &TopBytesSites[i], sizeof(SITE_RECORD));
  3323. RtlCopyMemory(&TopBytesSites[i], &tmpSite1, sizeof(SITE_RECORD));
  3324. RtlCopyMemory(&tmpSite1, &tmpSite2, sizeof(SITE_RECORD));
  3325. }
  3326. else if (!Found) {
  3327. if (TopBytesSites[i].Requests == 0) {
  3328. RtlCopyMemory(&TopBytesSites[i], pSite, sizeof(SITE_RECORD));
  3329. Found = TRUE;
  3330. }
  3331. else if (pSite->BytesSent > TopBytesSites[i].BytesSent) {
  3332. RtlCopyMemory(&tmpSite1, &TopBytesSites[i], sizeof(SITE_RECORD));
  3333. RtlCopyMemory(&TopBytesSites[i], pSite, sizeof(SITE_RECORD));
  3334. Found = TRUE;
  3335. }
  3336. }
  3337. }
  3338. }
  3339. free(pSite);
  3340. pSite = GetHeadSiteRecord();
  3341. }
  3342. fprintf(procFile, "<table title='Sites with the Most Requests' top='%d'>\n", DISPLAY_SIZE);
  3343. for (i = 0; i < DISPLAY_SIZE && TopHitSites[i].Requests != 0; i++) {
  3344. ULONGLONG AverageSiteResponseTime = 0;
  3345. if (TopHitSites[i].Requests != 0) {
  3346. AverageSiteResponseTime = TopHitSites[i].TotalResponseTime / TopHitSites[i].Requests;
  3347. }
  3348. fprintf(procFile,
  3349. "<site id='%d'>"
  3350. "<rate>%1.3f</rate>"
  3351. "<response_time>%I64u</response_time>"
  3352. "<cache_hits>%1.1f</cache_hits>"
  3353. "<static>%1.1f</static>"
  3354. "<cgi>%1.1f</cgi>"
  3355. "<asp>%1.1f</asp>"
  3356. "</site>\n",
  3357. TopHitSites[i].SiteId,
  3358. (Duration ? ((double)TopHitSites[i].Requests / (double)Duration) : 0.0),
  3359. AverageSiteResponseTime / 10000,
  3360. TopHitSites[i].Requests ? ((double)TopHitSites[i].Hits / (double)TopHitSites[i].Requests * 100.0) : 0.0,
  3361. TopHitSites[i].Requests ? ((double)TopHitSites[i].FileRequests / (double)TopHitSites[i].Requests * 100.0) : 0.0,
  3362. TopHitSites[i].Requests ? ((double)TopHitSites[i].CGIRequests / (double)TopHitSites[i].Requests * 100.0) : 0.0,
  3363. TopHitSites[i].Requests ? ((double)TopHitSites[i].ISAPIRequests / (double)TopHitSites[i].Requests * 100.0) : 0.0);
  3364. }
  3365. fprintf(procFile, "</table>\n" );
  3366. fprintf(procFile, "<table title='Sites with the Slowest Responses' top='%d'>\n", DISPLAY_SIZE);
  3367. for (i = 0; i < DISPLAY_SIZE && TopSlowSites[i].Requests != 0; i++) {
  3368. ULONGLONG AverageSiteResponseTime = 0;
  3369. if (TopSlowSites[i].Requests != 0) {
  3370. AverageSiteResponseTime = TopSlowSites[i].TotalResponseTime / TopSlowSites[i].Requests;
  3371. }
  3372. fprintf(procFile,
  3373. "<site id='%d'>"
  3374. "<rate>%1.3f</rate>"
  3375. "<response_time>%I64u</response_time>"
  3376. "<cache_hits>%1.1f</cache_hits>"
  3377. "<static>%1.1f</static>"
  3378. "<cgi>%1.1f</cgi>"
  3379. "<asp>%1.1f</asp>"
  3380. "</site>\n",
  3381. TopSlowSites[i].SiteId,
  3382. (Duration ? ((double)TopSlowSites[i].Requests / (double)Duration) : 0.0),
  3383. AverageSiteResponseTime / 10000,
  3384. TopSlowSites[i].Requests ? ((double)TopSlowSites[i].Hits / (double)TopSlowSites[i].Requests * 100.0) : 0.0,
  3385. TopSlowSites[i].Requests ? ((double)TopSlowSites[i].FileRequests / (double)TopSlowSites[i].Requests * 100.0) : 0.0,
  3386. TopSlowSites[i].Requests ? ((double)TopSlowSites[i].CGIRequests / (double)TopSlowSites[i].Requests * 100.0) : 0.0,
  3387. TopSlowSites[i].Requests ? ((double)TopSlowSites[i].ISAPIRequests / (double)TopSlowSites[i].Requests * 100.0) : 0.0);
  3388. }
  3389. fprintf(procFile, "</table>\n" );
  3390. if (PrintCPUUsage) {
  3391. fprintf(procFile, "<table title='Sites with the Most CPU Time Usage' top='%d'>\n", DISPLAY_SIZE );
  3392. for (i = 0; i < DISPLAY_SIZE && TopConsumingSites[i].Requests != 0; i++) {
  3393. ULONGLONG AverageSiteResponseTime = 0;
  3394. if (TopConsumingSites[i].Requests != 0) {
  3395. AverageSiteResponseTime = TopConsumingSites[i].TotalResponseTime / TopConsumingSites[i].Requests;
  3396. }
  3397. fprintf(procFile,
  3398. "<site id='%d'>"
  3399. "<rate>%1.3f</rate>"
  3400. "<cache_hits>%1.1f</cache_hits>"
  3401. "<response_time>%I64u</response_time>"
  3402. "<cpu_time units='ms'>%d</cpu_time>"
  3403. "<cpu>%1.1f</cpu>"
  3404. "</site>\n",
  3405. TopConsumingSites[i].SiteId,
  3406. (Duration ? ((double)TopConsumingSites[i].Requests / (double)Duration) : 0.0),
  3407. TopConsumingSites[i].Requests ? ((double)TopConsumingSites[i].Hits / (double)TopConsumingSites[i].Requests * 100.0) : 0.0,
  3408. AverageSiteResponseTime / 10000,
  3409. TopConsumingSites[i].Requests ? (TopConsumingSites[i].KCPUTime + TopConsumingSites[i].UCPUTime) / TopConsumingSites[i].Requests : 0,
  3410. MilDuration ? ((((double)TopConsumingSites[i].KCPUTime + (double)TopConsumingSites[i].UCPUTime) / (double)MilDuration) * 100.0) : 0.0);
  3411. }
  3412. fprintf(procFile, "</table>\n" );
  3413. }
  3414. fprintf(procFile, "<table title='Sites with the Most Bytes Sent' top='%d'>\n", DISPLAY_SIZE );
  3415. for (i = 0; i < DISPLAY_SIZE && TopBytesSites[i].Requests != 0; i++) {
  3416. fprintf(procFile,
  3417. "<site id='%d'>"
  3418. "<rate>%1.3f</rate>"
  3419. "<bytes>%d</bytes>"
  3420. "<cache_hits>%1.1f</cache_hits>"
  3421. "<static>%1.1f</static>"
  3422. "<cgi>%1.1f</cgi>"
  3423. "<asp>%1.1f</asp>"
  3424. "</site>\n",
  3425. TopBytesSites[i].SiteId,
  3426. (Duration ? ((double)TopBytesSites[i].Requests / (double)Duration) : 0.0),
  3427. Duration ? TopBytesSites[i].BytesSent / Duration : 0,
  3428. TopBytesSites[i].Requests ? ((double)TopBytesSites[i].Hits / (double)TopBytesSites[i].Requests * 100.0) : 0.0,
  3429. TopBytesSites[i].Requests ? ((double)TopBytesSites[i].FileRequests / (double)TopBytesSites[i].Requests * 100.0) : 0.0,
  3430. TopBytesSites[i].Requests ? ((double)TopBytesSites[i].CGIRequests / (double)TopBytesSites[i].Requests * 100.0) : 0.0,
  3431. TopBytesSites[i].Requests ? ((double)TopBytesSites[i].ISAPIRequests / (double)TopBytesSites[i].Requests * 100.0) : 0.0);
  3432. }
  3433. fprintf(procFile, "</table>\n" );
  3434. free(IIS);
  3435. }
  3436. void
  3437. WriteSummary()
  3438. {
  3439. FILE* SummaryFile;
  3440. PLIST_ENTRY Head, Next;
  3441. PMOF_INFO pMofInfo;
  3442. ULONG i;
  3443. WCHAR buffer[MAXSTR];
  3444. FILETIME StTm, StlTm;
  3445. LARGE_INTEGER LargeTmp;
  3446. SYSTEMTIME tmf, emf;
  3447. BOOL bResult;
  3448. if( NULL == TraceContext->SummaryFileName ){
  3449. return;
  3450. }
  3451. if( 0 == TotalEventCount ){
  3452. return;
  3453. }
  3454. SummaryFile = _wfopen( TraceContext->SummaryFileName, L"w" );
  3455. if (SummaryFile == NULL){
  3456. return;
  3457. }
  3458. fwprintf(SummaryFile,L"Files Processed:\n");
  3459. for (i=0; i<TraceContext->LogFileCount; i++) {
  3460. fwprintf(SummaryFile,L"\t%s\n",TraceContext->LogFileName[i]);
  3461. }
  3462. LargeTmp.QuadPart = CurrentSystem.StartTime;
  3463. StTm.dwHighDateTime = LargeTmp.HighPart;
  3464. StTm.dwLowDateTime = LargeTmp.LowPart;
  3465. FileTimeToLocalFileTime(&StTm, &StlTm);
  3466. bResult = FileTimeToSystemTime (
  3467. &StlTm,
  3468. &tmf
  3469. );
  3470. if( ! bResult || tmf.wMonth > 12 ){
  3471. ZeroMemory( &tmf, sizeof(SYSTEMTIME) );
  3472. buffer[0] = '\0';
  3473. }else{
  3474. GetDateFormatW( LOCALE_USER_DEFAULT, DATE_LONGDATE, &tmf, NULL, buffer, MAXSTR );
  3475. }
  3476. fwprintf(SummaryFile,
  3477. L"Total Buffers Processed %d\n"
  3478. L"Total Events Processed %d\n"
  3479. L"Total Events Lost %d\n"
  3480. L"Start Time %ws\n",
  3481. TotalBuffersRead,
  3482. TotalEventCount,
  3483. TotalEventsLost,
  3484. buffer );
  3485. LargeTmp.QuadPart = CurrentSystem.EndTime;
  3486. StTm.dwHighDateTime = LargeTmp.HighPart;
  3487. StTm.dwLowDateTime = LargeTmp.LowPart;
  3488. FileTimeToLocalFileTime(&StTm, &StlTm);
  3489. bResult = FileTimeToSystemTime (
  3490. &StlTm,
  3491. &emf
  3492. );
  3493. if( ! bResult || tmf.wMonth > 12 ){
  3494. ZeroMemory( &tmf, sizeof(SYSTEMTIME) );
  3495. buffer[0] = '\0';
  3496. }else{
  3497. GetDateFormatW( LOCALE_USER_DEFAULT, DATE_LONGDATE, &emf, NULL, buffer, MAXSTR );
  3498. }
  3499. ElapseTime = CurrentSystem.EndTime - CurrentSystem.StartTime;
  3500. fwprintf(SummaryFile,
  3501. L"End Time %ws\n"
  3502. L"Elapsed Time %I64d sec\n",
  3503. buffer,
  3504. (ElapseTime / 10000000) );
  3505. fwprintf(SummaryFile,
  3506. L"+-------------------------------------------------------------------------------------+\n"
  3507. L"|%10s %-20s %-10s %-38s|\n"
  3508. L"+-------------------------------------------------------------------------------------+\n",
  3509. L"Event Count",
  3510. L"Event Name",
  3511. L"Event Type",
  3512. L"Guid"
  3513. );
  3514. Head = &CurrentSystem.EventListHead;
  3515. Next = Head->Flink;
  3516. while (Head != Next) {
  3517. WCHAR wstr[MAXSTR];
  3518. PWCHAR str;
  3519. WCHAR s[MAX_GUID_STRING_SIZE];
  3520. PLIST_ENTRY vHead, vNext;
  3521. PMOF_VERSION pMofVersion;
  3522. RtlZeroMemory(&wstr[0], MAXSTR*sizeof(WCHAR));
  3523. pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
  3524. Next = Next->Flink;
  3525. if (pMofInfo->EventCount > 0) {
  3526. str = CpdiGuidToString(&s[0], MAX_GUID_STRING_SIZE, (LPGUID)&pMofInfo->Guid);
  3527. if( pMofInfo->strDescription != NULL ){
  3528. StringCchCopyW( wstr, MAXSTR, pMofInfo->strDescription );
  3529. }
  3530. //
  3531. // Get event count by type from MOF_VERSION structure
  3532. //
  3533. vHead = &pMofInfo->VersionHeader;
  3534. vNext = vHead->Flink;
  3535. while (vHead != vNext) {
  3536. pMofVersion = CONTAINING_RECORD(vNext, MOF_VERSION, Entry);
  3537. vNext = vNext->Flink;
  3538. if (pMofVersion->EventCountByType != 0) {
  3539. fwprintf(SummaryFile,L"| %10d %-20s %-10s %38s|\n",
  3540. pMofVersion->EventCountByType,
  3541. wstr,
  3542. pMofVersion->strType ? pMofVersion->strType : GUID_TYPE_DEFAULT,
  3543. str);
  3544. }
  3545. }
  3546. }
  3547. }
  3548. fwprintf(SummaryFile,
  3549. L"+-------------------------------------------------------------------------------------+\n"
  3550. );
  3551. fclose( SummaryFile );
  3552. }