1# Copyright 2020, Google Inc.
2# All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are
6# met:
7#
8#     * Redistributions of source code must retain the above copyright
9# notice, this list of conditions and the following disclaimer.
10#     * Redistributions in binary form must reproduce the above
11# copyright notice, this list of conditions and the following disclaimer
12# in the documentation and/or other materials provided with the
13# distribution.
14#     * Neither the name of Google Inc. nor the names of its
15# contributors may be used to endorse or promote products derived from
16# this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29"""Server related utilities."""
30
31from __future__ import absolute_import
32
33import logging
34import logging.handlers
35import threading
36import time
37
38from mod_pywebsocket import common
39from mod_pywebsocket import util
40
41
42def _get_logger_from_class(c):
43    return logging.getLogger('%s.%s' % (c.__module__, c.__name__))
44
45
46def configure_logging(options):
47    logging.addLevelName(common.LOGLEVEL_FINE, 'FINE')
48
49    logger = logging.getLogger()
50    logger.setLevel(logging.getLevelName(options.log_level.upper()))
51    if options.log_file:
52        handler = logging.handlers.RotatingFileHandler(options.log_file, 'a',
53                                                       options.log_max,
54                                                       options.log_count)
55    else:
56        handler = logging.StreamHandler()
57    formatter = logging.Formatter(
58        '[%(asctime)s] [%(levelname)s] %(name)s: %(message)s')
59    handler.setFormatter(formatter)
60    logger.addHandler(handler)
61
62    deflate_log_level_name = logging.getLevelName(
63        options.deflate_log_level.upper())
64    _get_logger_from_class(util._Deflater).setLevel(deflate_log_level_name)
65    _get_logger_from_class(util._Inflater).setLevel(deflate_log_level_name)
66
67
68class ThreadMonitor(threading.Thread):
69    daemon = True
70
71    def __init__(self, interval_in_sec):
72        threading.Thread.__init__(self, name='ThreadMonitor')
73
74        self._logger = util.get_class_logger(self)
75
76        self._interval_in_sec = interval_in_sec
77
78    def run(self):
79        while True:
80            thread_name_list = []
81            for thread in threading.enumerate():
82                thread_name_list.append(thread.name)
83            self._logger.info("%d active threads: %s",
84                              threading.active_count(),
85                              ', '.join(thread_name_list))
86            time.sleep(self._interval_in_sec)
87
88
89# vi:sts=4 sw=4 et
90