class GCPHandler(logging.Handler): def __init__(self, child_log_name='application', trace_header_name=None, labels=None, resource=None): logging.Handler.__init__(self) self.labels = labels self.trace_header_name = trace_header_name if resource is None: resource = _GLOBAL_RESOURCE else: resource = Resource(type=resource['type'], labels=resource['labels']) self.resource = resource self.transport_child = BackgroundThreadTransport( client, child_log_name) self.mLogLevels = [] def emit(self, record): if not has_request_context(): return msg = self.format(record) self.mLogLevels.append(record.levelno) trace_path = None span_id = None if self.trace_header_name in request.headers.keys(): # trace can be formatted as "X-Cloud-Trace-Context: TRACE_ID/SPAN_ID;o=TRACE_TRUE" raw_trace = request.headers.get(self.trace_header_name).split('/') trace_id = raw_trace[0] trace_path = f"projects/{os.getenv('GOOGLE_CLOUD_PROJECT')}/traces/{trace_id}" if len(raw_trace) > 1: span_id = raw_trace[1].split(';')[0] self.transport_child.send(msg, timestamp=datetime.datetime.utcnow(), severity=record.levelname, resource=self.resource, labels=self.labels, trace=trace_path, span_id=span_id)
class GCPHandler(logging.Handler): def __init__(self, app, parentLogName='request', childLogName='application', traceHeaderName=None, labels=None, resource=None): logging.Handler.__init__(self) self.app = app self.labels = labels self.traceHeaderName = traceHeaderName if (resource is None): resource = _GLOBAL_RESOURCE else: resource = Resource(type=resource['type'], labels=resource['labels']) print(resource) self.resource = resource self.transport_parent = BackgroundThreadTransport( client, parentLogName) self.transport_child = BackgroundThreadTransport(client, childLogName) self.mLogLevels = [] if app is not None: self.init_app(app) def emit(self, record): msg = self.format(record) SEVERITY = record.levelname # if the current log is at a lower level than is setup, skip it if (record.levelno <= logger.level): return self.mLogLevels.append(SEVERITY) TRACE = None SPAN = None if (self.traceHeaderName in request.headers.keys()): # trace can be formatted as "X-Cloud-Trace-Context: TRACE_ID/SPAN_ID;o=TRACE_TRUE" rawTrace = request.headers.get(self.traceHeaderName).split('/') TRACE = rawTrace[0] if (len(rawTrace) > 1): SPAN = rawTrace[1].split(';')[0] self.transport_child.send(msg, timestamp=datetime.datetime.utcnow(), severity=SEVERITY, resource=self.resource, labels=self.labels, trace=TRACE, span_id=SPAN) def init_app(self, app): # capture the http_request time @app.before_request def before_request(): g.request_start_time = time.time() g.request_time = lambda: "%.5fs" % (time.time() - g. request_start_time) # always log the http_request@ default INFO @app.after_request def add_logger(response): TRACE = None SPAN = None if (self.traceHeaderName in request.headers.keys()): # trace can be formatted as "X-Cloud-Trace-Context: TRACE_ID/SPAN_ID;o=TRACE_TRUE" rawTrace = request.headers.get(self.traceHeaderName).split('/') TRACE = rawTrace[0] if (len(rawTrace) > 1): SPAN = rawTrace[1].split(';')[0] # https://github.com/googleapis/googleapis/blob/master/google/logging/type/http_request.proto REQUEST = { 'requestMethod': request.method, 'requestUrl': request.url, 'status': response.status_code, 'responseSize': response.content_length, 'latency': g.request_time(), 'remoteIp': request.remote_addr, 'requestSize': request.content_length } if 'user-agent' in request.headers: REQUEST['userAgent'] = request.headers.get('user-agent') if request.referrer: REQUEST['referer'] = request.referrer # find the log level priority sub-messages; apply the max level to the root log message if len(self.mLogLevels) == 0: severity = logging.getLevelName(logging.INFO) if (response.status_code >= 400): severity = logging.getLevelName(logging.ERROR) else: severity = min(self.mLogLevels) self.mLogLevels = [] self.transport_parent.send(None, timestamp=datetime.datetime.utcnow(), severity=severity, resource=self.resource, labels=self.labels, trace=TRACE, span_id=SPAN, http_request=REQUEST) #response.headers['x-upstream-service-time'] = g.request_time() return response