__init__.py (16009B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\logmodule\__init__.py 2 from __future__ import print_function 3 import sys 4 import datetime 5 import traceback2 6 import __builtin__ 7 from cStringIO import StringIO 8 import os 9 import blue 10 import localstorage 11 from stdlogutils import GetStack, NextTraceID 12 from stdlogutils.logserver import LGINFO, LGNOTICE, LGWARN, LGERR 13 from stdlogutils.logserver import ChannelWrapper, LogChannelStream 14 from eveexceptions import UserError 15 DATETIME_FORMAT_STR = '%m/%d/%Y %H:%M:%S' 16 Suppress = ChannelWrapper.Suppress 17 Unsuppress = ChannelWrapper.Unsuppress 18 SuppressAllChannels = ChannelWrapper.SuppressAllChannels 19 UnsuppressAllChannels = ChannelWrapper.UnsuppressAllChannels 20 channelDict = ChannelWrapper.channelDict 21 uiMessageFunc = None 22 sentry_client = None 23 _WIN_EBADF = 9 24 Channel = ChannelWrapper 25 for f in Channel.flags: 26 globals()[f] = Channel.flags[f] 27 globals()[f.lower()] = Channel.flags[f] 28 29 baseName = '' 30 channels = {} 31 logExceptionLevel = 0 32 postStackTraceAll = None 33 34 def MsgWindowStreamToMsgWindow(): 35 from eveprefs import prefs 36 if hasattr(session, 'userid') and session.userid and settings.generic: 37 return settings.generic.Get('exceptionPopups', 0) 38 if prefs: 39 return prefs.GetValue('exceptionPopups', 0) 40 return 0 41 42 43 def SetUiMessageFunc(func): 44 global uiMessageFunc 45 uiMessageFunc = func 46 47 48 def SetStackFileNameSubPaths(filePaths): 49 pass 50 51 52 def DefaultUIMessage(*args): 53 print(args) 54 55 56 def init(base_name = '', prefs = None): 57 global baseName 58 baseName = base_name 59 if prefs is not None: 60 ChannelWrapper.Initialize(prefs) 61 SetUiMessageFunc(DefaultUIMessage) 62 63 64 def AddGlobalChannels(channels): 65 g = globals() 66 for channel in channels: 67 if channel.lower() not in g: 68 g[channel.lower()] = GetChannel(channel) 69 70 71 def GetChannel(name): 72 if '.' not in name: 73 name = baseName + '.' + name 74 if name not in channels: 75 s = name.split('.') 76 facility = '.'.join(s[:-1]) 77 obj = s[-1] 78 channels[name] = Channel(facility.encode('utf-8'), obj.encode('utf-8')) 79 return channels[name] 80 81 82 ui = GetChannel('UI') 83 general = GetChannel('General') 84 methodcalls = GetChannel('MethodCalls') 85 unittest = GetChannel('Unittest') 86 87 def LogException(extraText = '', channel = 'general', toConsole = 1, toLogServer = 1, toAlertSvc = None, toMsgWindow = 1, exctype = None, exc = None, tb = None, severity = None, show_locals = 1): 88 global logExceptionLevel 89 if logExceptionLevel > 0: 90 return 91 _tmpctx = blue.pyos.taskletTimer.EnterTasklet('logmodule::LogException') 92 logExceptionLevel += 1 93 if not exctype: 94 exctype, exc, tb = sys.exc_info() 95 try: 96 try: 97 _LogException((exctype, exc, tb), extraText, channel, toConsole, toLogServer, toAlertSvc, toMsgWindow, severity, show_locals) 98 return 99 except Exception: 100 try: 101 traceback2.print_exc(show_locals=3) 102 stream = LogChannelStream(GetChannel('general'), ERR) 103 traceback2.print_exc(show_locals=3, file=stream) 104 stream.close() 105 except Exception: 106 pass 107 108 try: 109 traceback2.print_exception(exctype, exc, tb, file=sys.stdout, show_locals=show_locals) 110 stream = LogChannelStream(GetChannel(channel), ERR) 111 print('retrying traceback log, got an error in _LogException', file=stream) 112 traceback2.print_exception(exctype, exc, tb, file=stream, show_locals=show_locals) 113 stream.close() 114 except Exception: 115 try: 116 traceback2.print_exc(show_locals=3) 117 except: 118 pass 119 120 finally: 121 del tb 122 logExceptionLevel -= 1 123 blue.pyos.taskletTimer.ReturnFromTasklet(_tmpctx) 124 125 126 def _LogException(exc_info, extraText, channel, toConsole, toLogServer, toAlertSvc, toMsgWindow, severity, show_locals): 127 from eveprefs import boot 128 if sentry_client: 129 sentry_client(message=extraText, exc_info=exc_info) 130 exctype, exc, tb = exc_info 131 exception_list = traceback2.extract_tb(tb, extract_locals=show_locals) 132 if tb: 133 caught_list = traceback2.extract_stack(tb.tb_frame) 134 else: 135 caught_list = traceback2.extract_stack(up=2) 136 stack, stackID = GetStack(exception_list, caught_list, show_locals=show_locals) 137 if severity is None: 138 severity = (ERR, WARN)[isinstance(exc, UserError)] 139 if toAlertSvc is None: 140 toAlertSvc = severity in (ERR,) 141 if toMsgWindow and isinstance(exc, UserError) and boot.role == 'client': 142 toMsgWindow = 0 143 uiMessageFunc(*exc.args) 144 out = GetMultiplex(channel, severity, toConsole, toLogServer, toMsgWindow, toAlertSvc, stackID) 145 formatted_exception = traceback2.format_exception_only(exctype, exc) 146 if not extraText: 147 try: 148 extraText = 'Info: %s' % formatted_exception[-1].strip() 149 except: 150 extraText = 'Info: <none>' 151 152 prefix = 'REMOTE ' if channel == 'remote.exc' else '' 153 traceID = NextTraceID() 154 print('%sEXCEPTION #%d logged at %s : %s ' % (prefix, 155 traceID, 156 datetime.datetime.utcnow().strftime(DATETIME_FORMAT_STR), 157 extraText), file=out) 158 print(' ', file=out) 159 print('Formatted exception info:', end=' ', file=out) 160 for line in formatted_exception: 161 print(line, end=' ', file=out) 162 163 print(' ', file=out) 164 for line in stack: 165 print(line, end=' ', file=out) 166 167 print(' ', file=out) 168 if exctype is MemoryError: 169 try: 170 DumpMemoryStatus(out) 171 DumpMemHistory(out) 172 except: 173 pass 174 175 try: 176 _LogThreadLocals(out) 177 except MemoryError: 178 pass 179 180 if boot.role != 'client': 181 try: 182 ram = blue.sysinfo.GetMemory().pageFile / 1024 / 1024 183 cpuLoad = sm.GetService('machoNet').GetCPULoad() 184 memLeft = blue.sysinfo.GetMemory().availablePhysical / 1024 / 1024 185 txt = 'System Information: ' 186 txt += ' Node ID: %s' % sm.GetService('machoNet').GetNodeID() 187 if boot.role == 'server': 188 txt += ' | Node Name: %s' % sm.GetService('machoNet').GetLocalHostName() 189 txt += ' | Total CPU load: %s%%' % int(cpuLoad) 190 txt += ' | Process memory in use: %s MB' % ram 191 txt += ' | Physical memory left: %s MB' % memLeft 192 print(txt, file=out) 193 except Exception as e: 194 sys.exc_clear() 195 196 try: 197 print('Stackhash: %s' % stackID[0], file=out) 198 except Exception: 199 pass 200 201 print('Reported from: ', __name__, file=out) 202 print('%sEXCEPTION END' % (prefix,), file=out) 203 out.flush() 204 if toConsole: 205 if toLogServer: 206 print('#nolog: An exception has occurred. It has been logged in the log server as exception #%d' % traceID, file=sys.stderr) 207 else: 208 print('There is no useful information accompanying this exception in the log server', file=sys.stderr) 209 210 211 def DumpMemHistory(out): 212 from eveprefs import boot 213 try: 214 if boot.role != 'client': 215 import blue, cPickle 216 fname = blue.paths.ResolvePath(u'root:/') + 'logs/memhist.b%d.%s.pikl' % (boot.build, blue.os.pid) 217 print('dumping cpu and memory history in ' + fname, file=out) 218 f = file(fname, 'w') 219 cPickle.dump(blue.pyos.cpuUsage, f) 220 f.close() 221 print('dump done.', file=out) 222 except Exception: 223 pass 224 225 226 def LogTraceback(extraText = '', channel = 'general', toConsole = 1, toAlertSvc = None, toLogServer = 1, nthParent = 0, daStack = None, severity = LGERR, show_locals = 1, limit = None): 227 if logExceptionLevel > 0: 228 return 229 _tmpctx = blue.pyos.taskletTimer.EnterTasklet('logmodule::LogTraceback') 230 try: 231 if daStack is None: 232 daStack = traceback2.extract_stack(limit=limit, up=nthParent + 1, extract_locals=show_locals) 233 stack, stackID = GetStack(daStack, None, show_locals, True) 234 if toAlertSvc is None: 235 toAlertSvc = severity in (ERR,) 236 toMsgWindow = False 237 multiplexToConsole = False if toLogServer else toConsole 238 out = GetMultiplex(channel, severity, multiplexToConsole, toLogServer, toMsgWindow, toAlertSvc, stackID) 239 traceID = NextTraceID() 240 logMessage = StringIO() 241 logMessage.write('STACKTRACE #%d logged at %s : %s\n' % (traceID, datetime.datetime.utcnow().strftime(DATETIME_FORMAT_STR), extraText)) 242 logMessage.write(' \n') 243 for line in stack: 244 logMessage.write(line) 245 246 logMessage.write(' \n') 247 _LogThreadLocals(logMessage) 248 logMessage.write('Stackhash: %s\n' % stackID[0]) 249 logMessage.write('Reported from: ' + __name__ + '\n') 250 logMessage.write('STACKTRACE END') 251 print(logMessage.getvalue(), file=out) 252 out.flush() 253 if toConsole: 254 if toLogServer: 255 if '/jessica' in blue.pyos.GetArg(): 256 print('#nolog: ' + logMessage.getvalue(), file=sys.stderr) 257 else: 258 print('#nolog: A traceback has been generated. It has been logged in the log server as stacktrace #%d' % traceID, file=sys.stderr) 259 else: 260 print('There is no useful information accompanying this traceback in the log server', file=sys.stderr) 261 finally: 262 blue.pyos.taskletTimer.ReturnFromTasklet(_tmpctx) 263 264 265 def LogMemoryStatus(extraText = '', channel = 'general'): 266 out = GetMultiplex(channel, WARN, 0, 1, 0, 0, 0) 267 print('Logging memory status : ', extraText, file=out) 268 DumpMemoryStatus(out) 269 270 271 def WhoCalledMe(up = 3): 272 try: 273 trc = traceback2.extract_stack(limit=1, up=up)[0] 274 fileName = os.path.basename(trc[0]) 275 lineNum = trc[1] 276 funcName = trc[2] 277 ret = '%s(%s) in %s' % (fileName, lineNum, funcName) 278 except: 279 ret = 'unknown' 280 281 return ret 282 283 284 def DumpMemoryStatus(out): 285 if blue.sysinfo.os.platform == blue.OsPlatform.WINDOWS: 286 m = blue.win32.GlobalMemoryStatus() 287 print('GlobalMemoryStatus:', file=out) 288 for k, v in m.items(): 289 print('%s : %r' % (k, v), file=out) 290 291 print('ProcessMemoryInfo:', file=out) 292 m = blue.win32.GetProcessMemoryInfo() 293 for k, v in m.items(): 294 print('%s : %r' % (k, v), file=out) 295 296 print('Python memory usage: %r' % sys.getpymalloced(), file=out) 297 try: 298 print('blue WriteStreams: %s, mem use: %s' % (blue.marshal.GetNWriteStreams(), blue.marshal.GetWriteStreamMem()), file=out) 299 except: 300 pass 301 302 print('end of memory status', file=out) 303 out.flush() 304 305 306 def _LogThreadLocals(out): 307 out.write('Thread Locals:') 308 if hasattr(__builtin__, 'session'): 309 out.write(' session was ') 310 out.write(str(session)) 311 else: 312 out.write('sorry, no session for ya.') 313 try: 314 ctk = localstorage.GetLocalStorage().get('calltimer.key', None) 315 except NameError: 316 return 317 318 if ctk: 319 out.write(' calltimer.key was ') 320 out.write(ctk) 321 currentcall = localstorage.GetLocalStorage().get('base.currentcall', None) 322 if currentcall: 323 try: 324 currentcall = currentcall() 325 out.write(' currentcall was: ') 326 out.write(str(currentcall)) 327 except ReferenceError: 328 pass 329 330 out.write('\n') 331 332 333 def GetMultiplex(channel, mode, toConsole, toLogServer, toMsgWindow, toAlertSvc, stackID): 334 to = [] 335 if toConsole: 336 if mode == INFO: 337 to.append(sys.__stdout__) 338 else: 339 to.append(sys.__stderr__) 340 if toLogServer: 341 to.append(LogChannelStream(GetChannel(channel), mode)) 342 if toMsgWindow and hasattr(__builtin__, 'session'): 343 to.append(MsgWindowStream()) 344 if toAlertSvc and hasattr(__builtin__, 'sm') and 'machoNet' in sm.services: 345 to.append(LogAlertServiceStream(GetChannel(channel), mode, stackID)) 346 return Multiplex(to) 347 348 349 class LogAlertServiceStream(object): 350 351 def __init__(self, channel, mode, stackID): 352 self.channel, self.mode, self.buff, self.stackID = (channel, 353 mode, 354 StringIO(), 355 stackID) 356 357 def write(self, what): 358 self.buff.write(what.encode('utf-8')) 359 360 def flush(self): 361 if not self.buff.tell(): 362 return 363 try: 364 self.buff.seek(0) 365 buff = self.buff.read() 366 sm.GetService('alert').SendStackTraceAlert(self.stackID, buff, {ERR: 'Error', 367 WARN: 'Warning', 368 INFO: 'Info'}.get(self.mode, 'Unknown')) 369 except: 370 print('Exception in LogAlertServiceStream') 371 372 self.buff = StringIO() 373 374 375 class MsgWindowStream(object): 376 __bad_to_good__ = [('<', '<'), 377 ('>', '>'), 378 ('\r', ''), 379 ('\n', '<br>')] 380 381 def __init__(self): 382 self.buff = [] 383 384 def write(self, what): 385 for bad, good in self.__bad_to_good__: 386 what = what.replace(bad, good) 387 388 self.buff.append(what) 389 390 def flush(self): 391 if not self.buff: 392 return 393 try: 394 if not MsgWindowStreamToMsgWindow(): 395 return 396 buff = ''.join(self.buff) 397 if len(buff) > 10000: 398 buff = buff[:10000] + '... [long traceback clipped; more info in the logger]' 399 import uthread 400 uthread.new(uiMessageFunc, 'ErrSystemError', {'text': buff}) 401 except: 402 pass 403 404 self.buff = [] 405 406 407 class Multiplex(object): 408 409 def __init__(self, streams): 410 self.streams = streams 411 412 def __del__(self): 413 self.flush() 414 415 def write(self, what): 416 for each in self.streams: 417 each.write(what) 418 419 def flush(self): 420 for each in self.streams: 421 try: 422 getattr(each, 'flush', lambda : None)() 423 except IOError as ioe: 424 if each in (sys.__stderr__, sys.__stdout__) and ioe[0] == _WIN_EBADF and blue.os.HasStartupArg('noconsole'): 425 pass 426 else: 427 raise 428 429 def close(self): 430 for each in self.streams: 431 getattr(each, 'close', lambda : None)() 432 433 434 def RegisterPostStackTraceAll(func): 435 global postStackTraceAll 436 postStackTraceAll = func 437 438 439 def StackTraceAll(reason = '(no reason stated)'): 440 import stackless, traceback2, os, time 441 from eveprefs import boot 442 logsFolder = blue.paths.ResolvePath(u'root:') + 'logs' 443 if not os.path.exists(logsFolder): 444 os.mkdir(logsFolder) 445 y, m, wd, d, h, m, s, ms = blue.os.GetTimeParts(blue.os.GetWallclockTime()) 446 args = (boot.build, 447 y, 448 m, 449 d, 450 h, 451 m, 452 s) 453 filename = logsFolder + '/#stacktrace b%d %.4d.%.2d.%.2d %.2d.%.2d.%.2d.txt' % args 454 GetChannel('General').Log('Writing out stacktrace at ' + filename, LGERR) 455 out = open(filename, 'w') 456 out.write('Stack trace of all tasklets as requested: %s\n' % reason) 457 out.write('Node ID: %s\n' % getattr(sm.services['machoNet'], 'nodeID', 'unknown')) 458 out.write(time.ctime() + '\n\n') 459 t = stackless.getcurrent() 460 first = t 461 no = 1 462 while t: 463 out.write('Tasklet #%s -------------------------------------------------' % no + '\n') 464 no += 1 465 if str(t.frame).find('cframe') == -1: 466 traceback2.print_stack(t.frame, file=out) 467 else: 468 out.write('%s\n' % t.frame) 469 out.write('\n') 470 t = t.next 471 if t is None or t == first: 472 break 473 474 if postStackTraceAll: 475 postStackTraceAll(out) 476 477 478 def Quit(reason = '(no reason stated)'): 479 try: 480 StackTraceAll(reason) 481 except: 482 try: 483 LogTraceback('Exception in stack-trace-all, shutdown bombing') 484 except: 485 pass 486 487 try: 488 import bluepy 489 bluepy.Terminate(1, reason) 490 except ImportError: 491 sys.exit(1)