counterService.py (12199B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\script\sys\counterService.py 2 import types 3 from collections import defaultdict 4 import blue 5 import uthread 6 import log 7 from carbon.common.script.sys import service 8 from carbon.common.script.sys.serviceConst import ROLE_ADMIN, ROLE_PROGRAMMER, ROLE_SERVICE 9 from carbon.common.script.util.format import GetTimeParts 10 from stringutil import strx 11 12 def CurrentTimeString(): 13 year, month, weekday, day, hour, minute, second, ms = GetTimeParts(blue.os.GetWallclockTime()) 14 line = '%d/%d/%d %d:%d:%d.%d' % (month, 15 day, 16 year, 17 hour, 18 minute, 19 second, 20 ms) 21 return line 22 23 24 class Counter: 25 26 def __init__(self, name, parent): 27 self.counter = 0 28 self.parent = parent 29 self.name = name 30 self.filename = '' 31 import log 32 self.logChannel = log.GetChannel('Counters.' + self.name) 33 34 def Reset(self): 35 self.counter = 0 36 37 def Add(self, value = 1): 38 self.counter += value 39 40 def Dec(self, value = 1): 41 self.counter -= value 42 43 def Set(self, value): 44 self.counter = value 45 46 def Value(self): 47 return self.counter 48 49 def Flush(self): 50 self.logChannel.Log(strx(self.Value()), log.LGINFO) 51 52 53 class TrafficCounter(Counter): 54 55 def __init__(self, name, parent): 56 Counter.__init__(self, name, parent) 57 self.Reset() 58 59 def Reset(self): 60 self.currval = 0 61 self.total = 0 62 self.minval = 0 63 self.maxval = 0 64 self.lastcur = 0 65 self.lasttot = 0 66 self.perfrom = {} 67 self.perfrom = defaultdict(lambda : 0) 68 self.lastperfrom = {} 69 self.lastperfrom = defaultdict(lambda : 0) 70 71 def Add(self, value = 1): 72 self.currval += value 73 self.total += 1 74 if value > self.maxval: 75 self.maxval = value 76 if (not self.minval or value < self.minval) and value: 77 self.minval = value 78 79 def AddFrom(self, nodeID, value = 1): 80 self.perfrom[nodeID] += value 81 self.Add(value) 82 83 def Dec(self, value = 1): 84 raise AttributeError('Dec is cwap on TrafficCounter') 85 86 def Set(self, value): 87 raise AttributeError('Set is cwap on TrafficCounter') 88 89 def Current(self): 90 return self.currval 91 92 def Count(self): 93 return self.total 94 95 def LastFlow(self): 96 return self.lastcur 97 98 def LastCount(self): 99 return self.lasttot 100 101 def PerSource(self): 102 return self.lastperfrom.items() 103 104 def Min(self): 105 return self.minval 106 107 def Max(self): 108 return self.maxval 109 110 def Value(self): 111 if type(self.currval) == types.FloatType: 112 avg = 0.0 113 if self.total != 0.0: 114 avg = float(self.currval / self.total) 115 return 'curr=%f, min=%f, max=%f, count=%d, avg=%f' % (self.currval, 116 self.minval, 117 self.maxval, 118 self.total, 119 avg) 120 else: 121 avg = 0 122 if self.total != 0: 123 avg = long(self.currval / self.total) 124 out = 'curr=%d, min=%d, max=%d, count=%d, avg=%d' % (self.currval, 125 self.minval, 126 self.maxval, 127 self.total, 128 avg) 129 for n in self.perfrom: 130 out += ', %s from %s' % (self.perfrom[n], n) 131 132 return out 133 134 def Flush(self): 135 self.logChannel.Log(strx(self.Value()), log.LGINFO) 136 if self.name == 'dataSent' or self.name == 'dataReceived': 137 self.lastcur = self.currval 138 self.lasttot = self.total 139 self.currval = 0 140 self.total = 0 141 self.lastperfrom.clear() 142 self.lastperfrom = self.perfrom.copy() 143 self.perfrom.clear() 144 145 146 class StatCounter(Counter): 147 148 def __init__(self, name, parent): 149 Counter.__init__(self, name, parent) 150 self.Reset() 151 152 def Reset(self): 153 self.lastval = 0 154 self.total = 0 155 self.minval = 0 156 self.maxval = 0 157 self.count = 0 158 159 def Add(self, value = 1): 160 self.lastval = value 161 self.total += value 162 self.count += 1 163 if value > self.maxval: 164 self.maxval = value 165 if (not self.minval or value < self.minval) and value: 166 self.minval = value 167 168 def Dec(self, value = 1): 169 raise NotImplementedError 170 171 def Set(self, value): 172 raise NotImplementedError 173 174 def Total(self): 175 return self.total 176 177 def Count(self): 178 return self.count 179 180 def Min(self): 181 return self.minval 182 183 def Max(self): 184 return self.maxval 185 186 def Avg(self): 187 avg = 0.0 188 if self.count > 0: 189 avg = self.total / float(self.count) 190 return avg 191 192 def Value(self): 193 return 'total=%f, last=%f, min=%f, max=%f, count=%f, avg=%f' % (self.total, 194 self.lastval, 195 self.minval, 196 self.maxval, 197 self.count, 198 self.Avg()) 199 200 def Flush(self): 201 pass 202 203 204 class ListCounter(Counter): 205 206 def __init__(self, name, parent): 207 Counter.__init__(self, name, parent) 208 self.counter = [] 209 210 def Reset(self): 211 self.counter = [] 212 213 def Add(self, value = 1): 214 if len(self.counter) == 0: 215 self.counter.append(value) 216 else: 217 self.counter.append(self.counter[-1] + value) 218 219 def Dec(self, value = 1): 220 if len(self.counter) == 0: 221 self.counter.append(value) 222 else: 223 self.counter.append(self.counter[-1] - value) 224 225 def Flush(self): 226 Counter.Flush(self) 227 self.counter = [] 228 229 def Set(self, value): 230 self.counter.append(value) 231 232 def Value(self): 233 raise RuntimeError('virtual method, must override') 234 235 236 class AvgCounter(ListCounter): 237 238 def __init__(self, name, parent): 239 ListCounter.__init__(self, name, parent) 240 241 def Value(self): 242 result = 0 243 if len(self.counter) == 0: 244 result = 0 245 else: 246 for s in self.counter: 247 result += s 248 249 result /= len(self.counter) 250 return result 251 252 253 class MaxCounter(ListCounter): 254 255 def __init__(self, name, parent): 256 ListCounter.__init__(self, name, parent) 257 258 def Value(self): 259 if len(self.counter) == 0: 260 return 0 261 max = self.counter[0] 262 for s in self.counter: 263 if s > max: 264 max = s 265 266 return max 267 268 269 class MinCounter(ListCounter): 270 271 def __init__(self, name, parent): 272 ListCounter.__init__(self, name, parent) 273 274 def Value(self): 275 if len(self.counter) == 0: 276 return 0 277 min = self.counter[0] 278 for s in self.counter: 279 if s < min: 280 min = s 281 282 return min 283 284 285 class CoreCounterService(service.Service): 286 __exportedcalls__ = {'CreateCounter': [ROLE_SERVICE | ROLE_ADMIN | ROLE_PROGRAMMER], 287 'DestroyCounter': [ROLE_SERVICE | ROLE_ADMIN | ROLE_PROGRAMMER], 288 'GetCounter': [ROLE_SERVICE | ROLE_ADMIN | ROLE_PROGRAMMER], 289 'SetFlushInterval': [ROLE_SERVICE | ROLE_ADMIN | ROLE_PROGRAMMER], 290 'GetFlushInterval': [ROLE_SERVICE | ROLE_ADMIN | ROLE_PROGRAMMER], 291 'StartLogging': [ROLE_SERVICE | ROLE_ADMIN | ROLE_PROGRAMMER], 292 'StopLogging': [ROLE_SERVICE | ROLE_ADMIN | ROLE_PROGRAMMER], 293 'GetCountersList': [ROLE_SERVICE | ROLE_ADMIN | ROLE_PROGRAMMER], 294 'IsLogging': [ROLE_SERVICE | ROLE_ADMIN | ROLE_PROGRAMMER]} 295 __guid__ = 'svc.counter' 296 __configvalues__ = {'countersInterval': 15, 297 'logStart': 0} 298 299 def Run(self, memStream = None): 300 self.counters = [] 301 self.timer = None 302 if self.logStart: 303 self.StartLogging() 304 305 def GetHtmlStateDetails(self, k, v, detailed): 306 from carbon.common.script.util import htmlwriter 307 if k == 'socket': 308 if detailed: 309 hd = [] 310 li = [] 311 li.append(['Listen Port', 80]) 312 return (k, htmlwriter.GetTable(hd, li, useFilter=True)) 313 elif k == 'counters': 314 if detailed: 315 hd = ['Name', 316 'Value', 317 'Parent', 318 'Filename', 319 'Log Channel'] 320 li = [] 321 for each in self.counters: 322 li.append([each.name, 323 each.counter, 324 each.parent, 325 each.filename, 326 each.logChannel]) 327 328 return (k, htmlwriter.GetTable(hd, li, useFilter=True)) 329 else: 330 v = '' 331 comma = '' 332 for each in self.counters: 333 v = v + comma + each.name + '=' + strx(each.counter) 334 comma = ', ' 335 336 return (k, v) 337 else: 338 if k == 'countersInterval': 339 desc = 'The time in secounds between logging counter values, assuming that counter logging is started in the first place.' 340 if self.logStart: 341 desc = 'Thus as the service is currently configured, %d seconds will pass between each log operation' % v 342 else: 343 desc = 'Thus if you would enable counter logging, %d seconds would pass between each log operation as the service is currently configured.' % v 344 return ('Counter Interval', desc) 345 if k == 'logStart': 346 desc = 'Whether or not counter logging should be started up when the service is started. If 0, then logging will not be started, otherwise it will be. ' 347 if v: 348 desc = desc + 'The counter service is currently configured in such a manner that logging will be started' 349 else: 350 desc = desc + 'The counter service is currently configured in such a manner that logging will <b>not</b> be started' 351 return ('Start Logging?', desc) 352 353 def Stop(self, memStream): 354 pass 355 356 def Flush(self): 357 for s in self.counters: 358 s.Flush() 359 360 def FindCounter(self, name): 361 for s in self.counters: 362 if s.name == name: 363 return s 364 365 def CreateCounter(self, name, type = 'normal'): 366 counter = self.FindCounter(name) 367 if counter: 368 return counter 369 if type == 'normal': 370 counter = Counter(name, self) 371 elif type == 'traffic': 372 counter = TrafficCounter(name, self) 373 elif type == 'statistic': 374 counter = StatCounter(name, self) 375 elif type == 'avg': 376 counter = AvgCounter(name, self) 377 elif type == 'max': 378 counter = MaxCounter(name, self) 379 else: 380 raise RuntimeError('Countertype %s not supported' % type) 381 self.counters.append(counter) 382 return counter 383 384 def AddCounter(self, counter): 385 self.counters.append(counter) 386 387 def GetCounter(self, name): 388 for s in self.counters: 389 if s.name == name: 390 return s 391 392 def DestroyCounter(self, name): 393 found = None 394 for s in self.counters: 395 if s.name == name: 396 found = s 397 break 398 399 if found != None: 400 self.counters.remove(found) 401 402 def StartLogging(self): 403 uthread.new(self.StartLogging_thread).context = 'counterService::FlushDaemon' 404 405 def StartLogging_thread(self): 406 self.logStart = 1 407 while 1: 408 blue.pyos.synchro.SleepWallclock(self.countersInterval * 1000) 409 if not self.logStart: 410 return 411 self.Flush() 412 413 def StopLogging(self): 414 self.logStart = 0 415 416 def IsLogging(self): 417 return self.logStart 418 419 def GetFlushInterval(self): 420 return self.countersInterval 421 422 def SetFlushInterval(self, interval): 423 self.countersInterval = interval 424 425 def GetCountersList(self): 426 titleList = [] 427 valueList = [] 428 for s in self.counters: 429 titleList.append(s.name) 430 valueList.append(s.Value()) 431 432 return (titleList, valueList)