]> git.proxmox.com Git - mirror_ovs.git/blob - python/ovs/vlog.py
Global replace of Nicira Networks.
[mirror_ovs.git] / python / ovs / vlog.py
1
2 # Copyright (c) 2011 Nicira, Inc.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 import datetime
17 import logging
18 import logging.handlers
19 import socket
20 import sys
21
22 import ovs.dirs
23 import ovs.util
24
25 FACILITIES = {"console": "info", "file": "info", "syslog": "info"}
26 LEVELS = {
27 "dbg": logging.DEBUG,
28 "info": logging.INFO,
29 "warn": logging.WARNING,
30 "err": logging.ERROR,
31 "emer": logging.CRITICAL,
32 "off": logging.CRITICAL
33 }
34
35
36 def get_level(level_str):
37 return LEVELS.get(level_str.lower())
38
39
40 class Vlog:
41 __inited = False
42 __msg_num = 0
43 __mfl = {} # Module -> facility -> level
44
45 def __init__(self, name):
46 """Creates a new Vlog object representing a module called 'name'. The
47 created Vlog object will do nothing until the Vlog.init() static method
48 is called. Once called, no more Vlog objects may be created."""
49
50 assert not Vlog.__inited
51 self.name = name.lower()
52 if name not in Vlog.__mfl:
53 Vlog.__mfl[self.name] = FACILITIES.copy()
54
55 def __log(self, level, message, **kwargs):
56 if not Vlog.__inited:
57 return
58
59 now = datetime.datetime.now().strftime("%b %d %H:%M:%S")
60 message = ("%s|%s|%s|%s|%s"
61 % (now, Vlog.__msg_num, self.name, level, message))
62
63 level = LEVELS.get(level.lower(), logging.DEBUG)
64 Vlog.__msg_num += 1
65
66 for f, f_level in Vlog.__mfl[self.name].iteritems():
67 f_level = LEVELS.get(f_level, logging.CRITICAL)
68 if level >= f_level:
69 logging.getLogger(f).log(level, message, **kwargs)
70
71 def emer(self, message, **kwargs):
72 self.__log("EMER", message, **kwargs)
73
74 def err(self, message, **kwargs):
75 self.__log("ERR", message, **kwargs)
76
77 def warn(self, message, **kwargs):
78 self.__log("WARN", message, **kwargs)
79
80 def info(self, message, **kwargs):
81 self.__log("INFO", message, **kwargs)
82
83 def dbg(self, message, **kwargs):
84 self.__log("DBG", message, **kwargs)
85
86 def exception(self, message):
87 """Logs 'message' at ERR log level. Includes a backtrace when in
88 exception context."""
89 self.err(message, exc_info=True)
90
91 @staticmethod
92 def init(log_file=None):
93 """Intializes the Vlog module. Causes Vlog to write to 'log_file' if
94 not None. Should be called after all Vlog objects have been created.
95 No logging will occur until this function is called."""
96
97 if Vlog.__inited:
98 return
99
100 Vlog.__inited = True
101 logging.raiseExceptions = False
102 for f in FACILITIES:
103 logger = logging.getLogger(f)
104 logger.setLevel(logging.DEBUG)
105
106 try:
107 if f == "console":
108 logger.addHandler(logging.StreamHandler(sys.stderr))
109 elif f == "syslog":
110 logger.addHandler(logging.handlers.SysLogHandler(
111 address="/dev/log",
112 facility=logging.handlers.SysLogHandler.LOG_DAEMON))
113 elif f == "file" and log_file:
114 logger.addHandler(logging.FileHandler(log_file))
115 except (IOError, socket.error):
116 logger.setLevel(logging.CRITICAL)
117
118 @staticmethod
119 def set_level(module, facility, level):
120 """ Sets the log level of the 'module'-'facility' tuple to 'level'.
121 All three arguments are strings which are interpreted the same as
122 arguments to the --verbose flag. Should be called after all Vlog
123 objects have already been created."""
124
125 module = module.lower()
126 facility = facility.lower()
127 level = level.lower()
128
129 if facility != "any" and facility not in FACILITIES:
130 return
131
132 if module != "any" and module not in Vlog.__mfl:
133 return
134
135 if level not in LEVELS:
136 return
137
138 if module == "any":
139 modules = Vlog.__mfl.keys()
140 else:
141 modules = [module]
142
143 if facility == "any":
144 facilities = FACILITIES.keys()
145 else:
146 facilities = [facility]
147
148 for m in modules:
149 for f in facilities:
150 Vlog.__mfl[m][f] = level
151
152
153 def add_args(parser):
154 """Adds vlog related options to 'parser', an ArgumentParser object. The
155 resulting arguments parsed by 'parser' should be passed to handle_args."""
156
157 group = parser.add_argument_group(title="Logging Options")
158 group.add_argument("--log-file", nargs="?", const="default",
159 help="Enables logging to a file. Default log file"
160 " is used if LOG_FILE is omitted.")
161 group.add_argument("-v", "--verbose", nargs="*",
162 help="Sets logging levels, see ovs-vswitchd(8)."
163 " Defaults to ANY:ANY:dbg.")
164
165
166 def handle_args(args):
167 """ Handles command line arguments ('args') parsed by an ArgumentParser.
168 The ArgumentParser should have been primed by add_args(). Also takes care
169 of initializing the Vlog module."""
170
171 log_file = args.log_file
172 if log_file == "default":
173 log_file = "%s/%s.log" % (ovs.dirs.LOGDIR, ovs.util.PROGRAM_NAME)
174
175 if args.verbose is None:
176 args.verbose = []
177 elif args.verbose == []:
178 args.verbose = ["any:any:dbg"]
179
180 for verbose in args.verbose:
181 args = verbose.split(':')
182
183 if len(args) >= 3:
184 level = args[2]
185 else:
186 level = "dbg"
187
188 if len(args) >= 2:
189 facility = args[1]
190 else:
191 facility = "any"
192
193 if len(args) >= 1:
194 module = args[0]
195 else:
196 module = "any"
197
198 Vlog.set_level(module, facility, level)
199
200 Vlog.init(log_file)