blob: dd74457f9581e616a5af474997ba8f6ee58b9008 [file] [log] [blame]
MK Ryu3e1de8b2015-05-27 16:47:10 -07001#!/usr/bin/python
2#
3# Copyright (c) 2015 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7
8import argparse
9import ctypes
10import logging
11import logging.handlers
12import multiprocessing
13import signal
14import sys
15import time
16
17import common
18from autotest_lib.client.common_lib.global_config import global_config as config
19from autotest_lib.site_utils import log_socket_server
20
21
22DEFAULT_PORT = 9080
23LOGGING_FORMAT = '%(asctime)s.%(msecs)03d %(levelname)-5.5s| %(message)s'
24MEGABYTE = 1024 * 1024
25
26
27class LogServerAlreadyRunningError(Exception):
28 pass
29
30
31class LogServer(object):
32 """A wrapper class to start and stop a TCP server for logging."""
33
34 process = None
35
36 @staticmethod
37 def start(port, log_handler):
38 """Start Log Record Socket Receiver in a new process.
39
40 @param port: Port to listen on.
41 @param log_handler: Logging handler.
42
43 @raise Exception: if TCP server is already running.
44 """
45 if LogServer.process:
46 raise LogServerAlreadyRunningError('LogServer is already running.')
47 server_started = multiprocessing.Value(ctypes.c_bool, False)
48 LogServer.process = multiprocessing.Process(
49 target=LogServer._run,
50 args=(server_started, port, log_handler))
51 LogServer.process.start()
52 while not server_started.value:
53 time.sleep(0.1)
54 print 'LogServer is started at port %d.' % port
55
56
57 @staticmethod
58 def _run(server_started, port, log_handler):
59 """Run LogRecordSocketReceiver to receive log.
60
61 @param server_started: True if socket log server is started.
62 @param port: Port used by socket log server.
63 @param log_handler: Logging handler.
64 """
65 # Clear all existing log handlers.
66 logging.getLogger().handlers = []
67 logging.getLogger().addHandler(log_handler)
68
69 tcp_server = log_socket_server.LogRecordSocketReceiver(
70 port=port)
71 print('Starting LogServer...')
72 server_started.value = True
73 tcp_server.serve_until_stopped()
74
75
76 @staticmethod
77 def stop():
78 """Stop LogServer."""
79 if LogServer.process:
80 LogServer.process.terminate()
81 LogServer.process = None
82
83
84def signal_handler(signal, frame):
85 """Handler for signal SIGINT.
86
87 @param signal: SIGINT
88 @param frame: the current stack frame
89 """
90 LogServer.stop()
91 sys.exit(0)
92
93
94def get_logging_handler():
95 """Return a logging handler.
96
97 Configure a RPC logging handler based on global_config and return
98 the handler.
99 """
100 max_log_size = config.get_config_value('SERVER', 'rpc_max_log_size_mb',
101 type=int)
102 number_of_old_logs = config.get_config_value('SERVER', 'rpc_num_old_logs',
103 type=int)
104 log_path = config.get_config_value('SERVER', 'rpc_log_path')
105
106 formatter = logging.Formatter(
107 fmt=LOGGING_FORMAT, datefmt='%m/%d %H:%M:%S')
108 handler = logging.handlers.RotatingFileHandler(
109 log_path,
110 maxBytes=max_log_size*MEGABYTE,
111 backupCount=number_of_old_logs)
112 handler.setFormatter(formatter)
113 return handler
114
115
116def main():
117 parser = argparse.ArgumentParser(
118 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
119 parser.add_argument('-p', type=int, dest='port',
120 help=('Listening port number'), default=DEFAULT_PORT)
121 options = parser.parse_args()
122
123 signal.signal(signal.SIGINT, signal_handler)
124
125 LogServer.start(options.port, get_logging_handler())
126
127
128if __name__ == '__main__':
129 sys.exit(main())