1/* 2 Copyright (C) 2000-2005 SKYRIX Software AG 3 4 This file is part of SOPE. 5 6 SOPE is free software; you can redistribute it and/or modify it under 7 the terms of the GNU Lesser General Public License as published by the 8 Free Software Foundation; either version 2, or (at your option) any 9 later version. 10 11 SOPE is distributed in the hope that it will be useful, but WITHOUT ANY 12 WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 14 License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with SOPE; see the file COPYING. If not, write to the 18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 19 02111-1307, USA. 20*/ 21 22#include <NGObjWeb/WODirectAction.h> 23#include <NGObjWeb/WOApplication.h> 24#include <NGObjWeb/WOResourceManager.h> 25#include <NGObjWeb/WOContext.h> 26#include <NGObjWeb/WORequest.h> 27#include <NGObjWeb/WOResponse.h> 28#include <NGObjWeb/WOSession.h> 29#include <NGObjWeb/WOStatisticsStore.h> 30#include "common.h" 31 32@interface WOApplication(MemoryStatistics) 33 34- (NSDictionary *)memoryStatistics; 35 36@end 37 38@implementation WOApplication(MemoryStatistics) 39 40- (NSDictionary *)memoryStatistics { 41#ifdef __linux__ 42 FILE *f; 43 char buf[4096]; 44 char fname[256]; 45 unsigned len; 46 47 sprintf(fname, "/proc/%d/status", getpid()); 48 if ((f = fopen(fname, "r"))) { 49 id d = nil; 50 NSString *s; 51 NSEnumerator *lines; 52 53 len = fread(buf, 1, sizeof(buf) - 1, f); 54 fclose(f); 55 buf[len] = '\0'; 56 57 s = [NSString stringWithCString:buf]; 58 lines = [[s componentsSeparatedByString:@"\n"] objectEnumerator]; 59 while ((s = [lines nextObject])) { 60 NSString *key; 61 NSRange rng; 62 63 rng = [s rangeOfString:@":"]; 64 if (rng.length <= 0) 65 continue; 66 67 key = [s substringToIndex:rng.location]; 68 69 if ([key hasPrefix:@"Vm"]) { 70 const char *cstr; 71 id value; 72 73 cstr = [s cString]; 74 while (*cstr != '\0' && *cstr != ':') cstr++; 75 if (*cstr == '\0') continue; 76 cstr++; 77 while (*cstr != '\0' && isspace(*cstr)) cstr++; 78 value = [NSString stringWithCString:cstr]; 79 80 if ([value hasSuffix:@" kB"]) { 81 value = [value substringToIndex:[value length] - 3]; 82 value = [NSNumber numberWithInt:[value intValue] * 1024]; 83 } 84 85 if (d == nil) 86 d = [NSMutableDictionary dictionaryWithCapacity:16]; 87 [(NSMutableDictionary *)d setObject:value forKey:key]; 88 } 89 } 90 return d; 91 } 92#endif 93 return nil; 94} 95 96@end /* WOApplication(MemoryStatistics) */ 97 98@implementation WODirectAction(WOStats) 99 100- (id<WOActionResults>)WOStatsAction { 101 WOApplication *app; 102 WOResponse *response; 103 NSDictionary *stats; 104 NSString *xslPath; 105 NSArray *languages; 106 static NSDictionary *keyToDataType = nil; 107 108 if (keyToDataType == nil) { 109 keyToDataType = 110 [[NSDictionary alloc] initWithObjectsAndKeys: 111 @"number", @"averageDuration", 112 @"number", @"maximumDuration", 113 @"number", @"minimumDuration", 114 @"number", @"totalDuration", 115 @"number", @"instanceUptime", 116 @"number", @"instanceUptimeInHours", 117 @"number", @"instanceLoad", 118 @"number", @"pageResponseCount", 119 @"number", @"numberOfZippedResponses", 120 @"number", @"totalResponseCount", 121 @"number", @"pageFrequency", 122 @"number", @"pageDeliveryVolumne", 123 @"number", @"responseFrequency", 124 @"number", @"relativeTimeConsumption", 125 @"number", @"averageResponseSize", 126 @"number", @"totalResponseSize", 127 @"number", @"totalZippedSize", 128 @"number", @"smallestResponseSize", 129 @"number", @"largestResponseSize", 130 @"number", @"VmData", 131 @"number", @"VmExe", 132 @"number", @"VmRSS", 133 @"number", @"VmLib", 134 @"number", @"VmStk", 135 @"number", @"VmSize", 136 @"number", @"VmLck", 137 nil]; 138 } 139 140 app = [WOApplication application]; 141 142 xslPath = [[NSUserDefaults standardUserDefaults] 143 stringForKey:@"WOStatsStylesheetName"]; 144 languages = [[self context] resourceLookupLanguages]; 145 xslPath = [[app resourceManager] urlForResourceNamed:xslPath 146 inFramework:nil 147 languages:languages 148 request:[self request]]; 149 if ([xslPath hasPrefix:@"/missingresource"]) 150 xslPath = nil; 151 152 response = [WOResponse responseWithRequest:[self request]]; 153 [response setContentEncoding:NSUTF8StringEncoding]; 154 [response setHeader:@"text/xml; charset=utf-8" forKey:@"content-type"]; 155 156 stats = [[app statisticsStore] statistics]; 157 158 [response appendContentString:@"<?xml version='1.0'?>\n"]; 159 if ([xslPath length] > 0) { 160 [response appendContentString:@"<?xml-stylesheet type='text/xsl' href='"]; 161 [response appendContentString:xslPath]; 162 [response appendContentString:@"'?>"]; 163 } 164 165 [response appendContentString:@"<application name='"]; 166 [response appendContentString:[app name]]; 167 [response appendContentString:@"'"]; 168 [response appendContentString: 169 [NSString stringWithFormat:@" pid='%d'", getpid()]]; 170 [response appendContentString: 171 @" xmlns:dt='urn:schemas-microsoft-com:datatypes'>\n"]; 172 173 { 174 NSEnumerator *e; 175 NSString *key; 176 NSDictionary *pageStatistics; 177 178 /* application statistics */ 179 180 e = [stats keyEnumerator]; 181 while ((key = [e nextObject])) { 182 id value; 183 NSString *dt; 184 185 if ([key isEqualToString:@"pageStatistics"]) 186 continue; 187 188 value = [stats objectForKey:key]; 189 190 [response appendContentString:@" <"]; 191 [response appendContentString:key]; 192 193 if ((dt = [keyToDataType objectForKey:key])) { 194 [response appendContentString:@" dt:dt='"]; 195 [response appendContentString:dt]; 196 [response appendContentString:@"'"]; 197 } 198 199 [response appendContentString:@">"]; 200 201 [response appendContentHTMLString:[value stringValue]]; 202 203 [response appendContentString:@"</"]; 204 [response appendContentString:key]; 205 [response appendContentString:@">\n"]; 206 } 207 208 /* memory statistics */ 209 210 { 211 NSDictionary *mem; 212 213 mem = [app memoryStatistics]; 214 215 if ([mem count] > 0) { 216 [response appendContentString:@" <memory>\n"]; 217 218 e = [mem keyEnumerator]; 219 while ((key = [e nextObject])) { 220 id value; 221 NSString *dt; 222 223 value = [mem objectForKey:key]; 224 225 [response appendContentString:@" <"]; 226 [response appendContentString:key]; 227 228 if ((dt = [keyToDataType objectForKey:key])) { 229 [response appendContentString:@" dt:dt='"]; 230 [response appendContentString:dt]; 231 [response appendContentString:@"'"]; 232 } 233 234 [response appendContentString:@">"]; 235 236 [response appendContentHTMLString:[value stringValue]]; 237 238 [response appendContentString:@"</"]; 239 [response appendContentString:key]; 240 [response appendContentString:@">\n"]; 241 } 242 243 [response appendContentString:@" </memory>\n"]; 244 } 245 } 246 247 /* page statistics */ 248 249 pageStatistics = [stats objectForKey:@"pageStatistics"]; 250 251 [response appendContentString:@" <pages>\n"]; 252 253 e = [pageStatistics keyEnumerator]; 254 while ((key = [e nextObject])) { 255 NSDictionary *stats; 256 NSEnumerator *e2; 257 NSString *key2; 258 259 stats = [pageStatistics objectForKey:key]; 260 e2 = [stats keyEnumerator]; 261 262 [response appendContentString:@" <page name='"]; 263 [response appendContentString:key]; 264 [response appendContentString:@"'>\n"]; 265 266 while ((key2 = [e2 nextObject])) { 267 id value; 268 NSString *dt; 269 270 value = [stats objectForKey:key2]; 271 272 [response appendContentString:@" <"]; 273 [response appendContentString:key2]; 274 275 if ((dt = [keyToDataType objectForKey:key2])) { 276 [response appendContentString:@" dt:dt='"]; 277 [response appendContentString:dt]; 278 [response appendContentString:@"'"]; 279 } 280 281 [response appendContentString:@">"]; 282 283 [response appendContentHTMLString:[value stringValue]]; 284 285 [response appendContentString:@"</"]; 286 [response appendContentString:key2]; 287 [response appendContentString:@">\n"]; 288 } 289 [response appendContentString:@" </page>\n"]; 290 } 291 292 [response appendContentString:@" </pages>\n"]; 293 } 294 295 [response appendContentString:@"</application>\n"]; 296 297 return response; 298} 299 300@end /* WODirectAction(WOStats) */ 301