From 46ef692d3c1c9d57ad61bcc34bdac48eabf240b7 Mon Sep 17 00:00:00 2001 From: Tommy Carpenter Date: Mon, 9 Jul 2018 15:11:14 -0400 Subject: Finish EELF compliance. Issue-ID: DCAEGEN2-581 Change-Id: I22651dbe775b0165612c507df99b5a0e8e2ee22c Signed-off-by: Tommy Carpenter --- app/app/config_binding_service/logging.py | 80 +++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 5 deletions(-) (limited to 'app/app/config_binding_service/logging.py') diff --git a/app/app/config_binding_service/logging.py b/app/app/config_binding_service/logging.py index 7966e2f..b6275a7 100644 --- a/app/app/config_binding_service/logging.py +++ b/app/app/config_binding_service/logging.py @@ -22,9 +22,9 @@ from os import makedirs import datetime -LOGGER = getLogger("defaultlogger") _AUDIT_LOGGER = getLogger("defaultlogger") _ERROR_LOGGER = getLogger("defaultlogger") +_METRICS_LOGGER = getLogger("defaultlogger") def _create_logger(name, logfile): @@ -46,6 +46,7 @@ def _create_logger(name, logfile): def create_loggers(): """ Public method to set the global logger, launched from Run + This is *not* launched during unit testing, so unit tests do not create/write log files """ makedirs("/opt/logs", exist_ok=True) @@ -61,6 +62,12 @@ def create_loggers(): global _ERROR_LOGGER _ERROR_LOGGER = _create_logger("config_binding_service_error", err_file) + # create the metrics log + met_file = "/opt/logs/metrics.log" + open(met_file, 'a').close() # this is like "touch" + global _METRICS_LOGGER + _METRICS_LOGGER = _create_logger("config_binding_service_metrics", met_file) + def utc(): """gets current time in utc""" @@ -75,25 +82,36 @@ def audit(raw_request, bts, xer, rcode, calling_mod, msg="n/a"): 1 BeginTimestamp Implemented (bts) 2 EndTimestamp Auto Injected when this is called 3 RequestID Implemented (xer) + 5 threadId n/a 7 serviceName Implemented (from Req) 9 StatusCode Auto injected based on rcode 10 ResponseCode Implemented (rcode) + 13 Category log level - all audit records are INFO. 15 Server IP address Implemented (from Req) 16 ElapsedTime Auto Injected (milliseconds) + 17 Server This is running in a Docker container so this is not applicable, my HOSTNAME is always "config_binding_service" 18 ClientIPaddress Implemented (from Req) 19 class name Implemented (mod), though docs say OOP, I am using the python module here 20 Unused ...implemented.... 21-25 Custom n/a 26 detailMessage Implemented (msg) + + Not implemented + 4 serviceInstanceID - ? + 6 physical/virtual server name (Optional) + 8 PartnerName - nothing in the request tells me this + 11 Response Description - the CBS follows standard HTTP error codes so look them up + 12 instanceUUID - Optional + 14 Severity (Optional) """ ets = utc() - _AUDIT_LOGGER.info("{bts}|{ets}|{xer}||||{path}||{status}|{rcode}|||||{servip}|{et}||{clientip}|{calling_mod}|||||||{msg}".format( + _AUDIT_LOGGER.info("{bts}|{ets}|{xer}||n/a||{path}||{status}|{rcode}|||INFO||{servip}|{et}|config_binding_service|{clientip}|{calling_mod}|||||||{msg}".format( bts=bts.isoformat(), ets=ets.isoformat(), xer=xer, rcode=rcode, path=raw_request.path.split("/")[1], - status="COMPLETE" if rcode == 200 else "ERROR", + status="COMPLETE" if rcode < 400 else "ERROR", servip=raw_request.host.split(":")[0], et=int((ets - bts).microseconds / 1000), # supposed to be in milleseconds clientip=raw_request.remote_addr, @@ -108,6 +126,7 @@ def error(raw_request, xer, severity, ecode, tgt_entity="n/a", tgt_path="n/a", m 1 Timestamp Auto Injected when this is called 2 RequestID Implemented (xer) + 3 ThreadID n/a 4 ServiceName Implemented (from Req) 6 TargetEntity Implemented (tgt_entity) 7 TargetServiceName Implemented (tgt_path)/ @@ -117,12 +136,11 @@ def error(raw_request, xer, severity, ecode, tgt_entity="n/a", tgt_path="n/a", m 11. detailMessage Implemented (adv_msg) Not implemented: - 3 ThreadID - n/a 5 PartnerName - nothing in the request tells me this """ ets = utc() - _ERROR_LOGGER.error("{ets}|{xer}||{path}||{tge}|{tgp}|{sev}|{ecode}|{msg}|{amsg}".format( + _ERROR_LOGGER.error("{ets}|{xer}|n/a|{path}||{tge}|{tgp}|{sev}|{ecode}|{msg}|{amsg}".format( ets=ets, xer=xer, path=raw_request.path.split("/")[1], @@ -132,3 +150,55 @@ def error(raw_request, xer, severity, ecode, tgt_entity="n/a", tgt_path="n/a", m ecode=ecode, msg=msg, amsg=adv_msg)) + + +def metrics(raw_request, bts, xer, target, target_path, rcode, calling_mod, msg="n/a"): + """ + write an EELF metrics record per https://wiki.onap.org/download/attachments/1015849/ONAP%20application%20logging%20guidelines.pdf?api=v2 + %The metrics fields implemented: + + 1 BeginTimestamp Implemented (bts) + 2 EndTimestamp Auto Injected when this is called + 3 RequestID Implemented (xer) + 5 threadId n/a + 7 serviceName Implemented (from Req) + 9 TargetEntity Implemented (target) + 10 TargetServiceName Implemented (target_path) + 11 StatusCode Implemented (based on rcode) + 12 Response Code Implemented (rcode) + 15 Category log level all metrics records are INFO. + 17 Server IP address Implemented (from Req) + 18 ElapsedTime Auto Injected (milliseconds) + 19 Server This is running in a Docker container so this is not applicable, my HOSTNAME is always "config_binding_service" + 20 ClientIPaddress Implemented (from Req) + 21 class name Implemented (mod), though docs say OOP, I am using the python module here + 22 Unused ...implemented.... + 24 TargetVirtualEntity n/a + 25-28 Custom n/a + 29 detailMessage Implemented (msg) + + Not implemented + 4 serviceInstanceID - ? + 6 physical/virtual server name (Optional) + 8 PartnerName - nothing in the request tells me this + 13 Response Description - the CBS follows standard HTTP error codes so look them up + 14 instanceUUID - Optional + 16 Severity (Optional) + 23 ProcessKey - optional + """ + ets = utc() + + _METRICS_LOGGER.info("{bts}|{ets}|{xer}||n/a||{path}||{tge}|{tgp}|{status}|{rcode}|||INFO||{servip}|{et}|config_binding_service|{clientip}|{calling_mod}|||n/a|||||{msg}".format( + bts=bts.isoformat(), + ets=ets.isoformat(), + xer=xer, + path=raw_request.path.split("/")[1], + tge=target, + tgp=target_path, + status="COMPLETE" if rcode < 400 else "ERROR", + rcode=rcode, + servip=raw_request.host.split(":")[0], + et=int((ets - bts).microseconds / 1000), # supposed to be in milleseconds + clientip=raw_request.remote_addr, + calling_mod=calling_mod, msg=msg + )) -- cgit 1.2.3-korg