1 # Copyright 2017 Cisco Systems, Inc. All rights reserved.
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
15 from datetime import datetime
16 from fluent import sender
20 class FluentLogHandler(logging.Handler):
21 '''This is a minimalist log handler for use with Fluentd
23 Needs to be attached to a logger using the addHandler method.
24 It only picks up from every record:
25 - the formatted message (no timestamp and no level)
27 - the runlogdate (to tie multiple run-related logs together)
28 The timestamp is retrieved by the fluentd library.
31 def __init__(self, tag, fluentd_ip='127.0.0.1', fluentd_port=24224):
32 logging.Handler.__init__(self)
34 self.formatter = logging.Formatter('%(message)s')
35 self.sender = sender.FluentSender(self.tag, host=fluentd_ip, port=fluentd_port)
37 self.__warning_counter = 0
38 self.__error_counter = 0
40 def start_new_run(self):
41 '''Delimitate a new run in the stream of records with a new timestamp
43 self.runlogdate = str(datetime.now())
45 self.__warning_counter = 0
46 self.__error_counter = 0
48 self.__send_start_record()
50 def emit(self, record):
52 "runlogdate": self.runlogdate,
53 "loglevel": record.levelname,
54 "message": self.formatter.format(record)
56 self.__update_stats(record.levelno)
57 self.sender.emit(None, data)
59 # send START record for each run
60 def __send_start_record(self):
62 "runlogdate": self.runlogdate,
64 "message": "NFVBENCH run is started",
69 self.sender.emit(None, data)
71 # send stats related to the current run and reset state for a new run
72 def send_run_summary(self, run_summary_required):
73 if run_summary_required or self.__get_highest_level() == logging.ERROR:
75 "runlogdate": self.runlogdate,
76 "loglevel": "RUN_SUMMARY",
77 "message": self.__get_highest_level_desc(),
78 "numloglevel": self.__get_highest_level(),
79 "numerrors": self.__error_counter,
80 "numwarnings": self.__warning_counter
82 self.sender.emit(None, data)
84 def __get_highest_level(self):
85 if self.__error_counter > 0:
87 elif self.__warning_counter > 0:
88 return logging.WARNING
91 def __get_highest_level_desc(self):
92 highest_level = self.__get_highest_level()
93 if highest_level == logging.INFO:
95 elif highest_level == logging.WARNING:
96 return "RUN WITH WARNINGS"
98 return "RUN WITH ERRORS"
100 def __update_stats(self, levelno):
101 if levelno == logging.WARNING:
102 self.__warning_counter += 1
103 elif levelno == logging.ERROR:
104 self.__error_counter += 1