Esempio n. 1
0
    def init_plugins():
        """初始化日志、错误追踪插件,并将当前配置信息打 log"""
        from everyclass.common.flask import print_config
        from everyclass.common.env import get_env

        # Sentry
        if get_env() in __app.config['SENTRY_AVAILABLE_IN']:
            sentry.init_app(app=__app)
            sentry_handler = SentryHandler(sentry.client)
            sentry_handler.setLevel(logging.WARNING)
            logging.getLogger().addHandler(sentry_handler)

            logger.info('Sentry is inited because you are in {} mode.'.format(
                __app.config['CONFIG_NAME']))

        print_config(__app, logger)
Esempio n. 2
0
    def init_log_handlers():
        global __app

        # Sentry
        if __app.config['CONFIG_NAME'] in __app.config['SENTRY_AVAILABLE_IN']:
            sentry.init_app(app=__app)
            sentry_handler = SentryHandler(
                sentry.client, level='WARNING')  # Sentry 只处理 WARNING 以上的
            logger.handlers.append(sentry_handler)
Esempio n. 3
0
def config_sentry(args):
    # Configure the default client
    config = get_config(args.config_file)
    if 'sentry_dsn' not in config or not config['sentry_dsn']:
        return

    handler = SentryHandler(
        config['sentry_dsn'],
        level='INFO',
        bubble=True
    ).push_application()
Esempio n. 4
0
def setup_sentry(project_name, channel, SENTRY_DSN):
    '''
    Setup sentry account using taskcluster secrets
    '''

    from raven import Client
    from raven.handlers.logbook import SentryHandler

    sentry_client = Client(
        dsn=SENTRY_DSN,
        site=project_name,
        name='mozilla-releng/services',
        environment=channel,
        # TODO:
        # release=read(VERSION) we need to promote that as well via secrets
        # tags=...
        # repos=...
    )

    sentry = SentryHandler(sentry_client, level=logbook.WARNING, bubble=True)

    sentry.push_application()
Esempio n. 5
0
    def init_log_handlers():
        """init log handlers and print current configuration to log"""
        from everyclass.server.utils.logbook_logstash.handler import LogstashHandler
        from elasticapm.contrib.flask import ElasticAPM
        from everyclass.server.config import print_config
        ElasticAPM.request_finished = monkey_patch.ElasticAPM.request_finished(
            ElasticAPM.request_finished)

        global __app, __first_spawn

        # Elastic APM
        if __app.config['CONFIG_NAME'] in __app.config['APM_AVAILABLE_IN']:
            ElasticAPM(__app)
            print('APM is inited because you are in {} mode.'.format(
                __app.config['CONFIG_NAME']))

        # Logstash centralized log
        if __app.config['CONFIG_NAME'] in __app.config[
                'LOGSTASH_AVAILABLE_IN']:
            logstash_handler = LogstashHandler(
                host=__app.config['LOGSTASH']['HOST'],
                port=__app.config['LOGSTASH']['PORT'],
                release=__app.config['GIT_DESCRIBE'],
                bubble=True,
                logger=logger,
                filter=lambda r, h: r.level >= 11)  # do not send DEBUG
            logger.handlers.append(logstash_handler)
            print(
                'LogstashHandler is inited because you are in {} mode.'.format(
                    __app.config['CONFIG_NAME']))

        # Sentry
        if __app.config['CONFIG_NAME'] in __app.config['SENTRY_AVAILABLE_IN']:
            sentry.init_app(app=__app)
            sentry_handler = SentryHandler(sentry.client,
                                           level='INFO')  # Sentry 只处理 INFO 以上的
            logger.handlers.append(sentry_handler)
            print('Sentry is inited because you are in {} mode.'.format(
                __app.config['CONFIG_NAME']))

        # print current configuration
        import uwsgi
        if uwsgi.worker_id() == 1 and __first_spawn:
            # set to warning level because we want to monitor restarts
            logger.warning('App (re)started in `{0}` environment'.format(
                __app.config['CONFIG_NAME']),
                           stack=False)
            print_config(__app)
            __first_spawn = False
Esempio n. 6
0
    def init_log_handlers():
        """初始化 log handlers 并将当前配置信息打 log"""
        from everyclass.server.utils.logbook_logstash.handler import LogstashHandler
        from elasticapm.contrib.flask import ElasticAPM
        from everyclass.server.config import print_config
        ElasticAPM.request_finished = monkey_patch.ElasticAPM.request_finished(
            ElasticAPM.request_finished)

        # Elastic APM
        if __app.config['CONFIG_NAME'] in __app.config['APM_AVAILABLE_IN']:
            ElasticAPM(__app)
            print('APM is inited because you are in {} mode.'.format(
                __app.config['CONFIG_NAME']))

        # Logstash centralized log
        if __app.config['CONFIG_NAME'] in __app.config[
                'LOGSTASH_AVAILABLE_IN']:
            logstash_handler = LogstashHandler(
                host=__app.config['LOGSTASH']['HOST'],
                port=__app.config['LOGSTASH']['PORT'],
                release=__app.config['GIT_DESCRIBE'],
                bubble=True,
                logger=logger,
                filter=lambda r, h: r.level >= 11)  # do not send DEBUG
            logger.handlers.append(logstash_handler)
            print(
                'LogstashHandler is inited because you are in {} mode.'.format(
                    __app.config['CONFIG_NAME']))

        # Sentry
        if __app.config['CONFIG_NAME'] in __app.config['SENTRY_AVAILABLE_IN']:
            sentry.init_app(app=__app)
            sentry_handler = SentryHandler(sentry.client,
                                           level='INFO')  # Sentry 只处理 INFO 以上的
            logger.handlers.append(sentry_handler)
            print('Sentry is inited because you are in {} mode.'.format(
                __app.config['CONFIG_NAME']))

        # 如果当前时间与模块加载时间相差一分钟之内,认为是第一次 spawn(进程随着时间的推移可能会被 uwsgi 回收),
        # 在 1 号 worker 里打印当前配置
        import uwsgi
        if uwsgi.worker_id() == 1 and (datetime.datetime.now() - __load_time
                                       ) < datetime.timedelta(minutes=1):
            # 这里设置等级为 warning 因为我们希望在 sentry 里监控重启情况
            logger.warning('App (re)started in `{0}` environment'.format(
                __app.config['CONFIG_NAME']),
                           stack=False)
            print_config(__app)
    def init_log_handlers():
        """init log handlers"""
        from everyclass.api_server.util.logbook_logstash.handler import LogstashHandler
        from elasticapm.contrib.flask import ElasticAPM

        global __app, __first_spawn, __sentry_available

        # Sentry
        if __app.config['CONFIG_NAME'] in __app.config['SENTRY_AVAILABLE_IN']:
            sentry.init_app(app=__app)
            sentry_handler = SentryHandler(
                sentry.client, level='WARNING')  # Sentry 只处理 WARNING 以上的
            logger.handlers.append(sentry_handler)
            __sentry_available = True
            logger.info('You are in {} mode, so Sentry is inited.'.format(
                __app.config['CONFIG_NAME']))

        # Elastic APM
        if __app.config['CONFIG_NAME'] in __app.config['APM_AVAILABLE_IN']:
            ElasticAPM(__app)
            logger.info('You are in {} mode, so APM is inited.'.format(
                __app.config['CONFIG_NAME']))

        # Logstash centralized log
        if __app.config['CONFIG_NAME'] in __app.config[
                'LOGSTASH_AVAILABLE_IN']:
            logstash_handler = LogstashHandler(
                host=__app.config['LOGSTASH']['HOST'],
                port=__app.config['LOGSTASH']['PORT'],
                release=__app.config['GIT_DESCRIBE'],
                bubble=True,
                logger=logger,
                filter=lambda r, h: r.level >= 11)  # do not send DEBUG
            logger.handlers.append(logstash_handler)
            logger.info(
                'You are in {} mode, so LogstashHandler is inited.'.format(
                    __app.config['CONFIG_NAME']))

        import uwsgi
        if uwsgi.worker_id() == 1 and __first_spawn:
            from everyclass.api_server.util import mysql_connect, get_semester_list

            logger.info('数据库可用学期:' +
                        ';'.join(get_semester_list(__app.mongo_pool)))

            __first_spawn = False
Esempio n. 8
0
def setup(level='debug', show_log=False, filename=settings.LOG['file']):
    ''' Hivy formated logger '''

    level = level.upper()
    handlers = [
        logbook.NullHandler()
    ]
    if show_log:
        handlers.append(
            logbook.StreamHandler(sys.stdout,
                                  format_string=settings.LOG['format'],
                                  level=level))
    else:
        handlers.append(
            logbook.FileHandler(filename,
                                format_string=settings.LOG['format'],
                                level=level))

    sentry_dns = settings.LOG['sentry_dns']
    if sentry_dns:
        handlers.append(SentryHandler(sentry_dns, level='ERROR'))

    return logbook.NestedSetup(handlers)
Esempio n. 9
0
    def test_logger(self):
        client = TempStoreClient(include_paths=['tests', 'raven'])
        handler = SentryHandler(client)
        logger = self.logger

        with handler.applicationbound():
            logger.error('This is a test error')

            self.assertEquals(len(client.events), 1)
            event = client.events.pop(0)
            self.assertEquals(event['logger'], __name__)
            self.assertEquals(event['level'], 'error')
            self.assertEquals(event['message'], 'This is a test error')
            self.assertFalse('sentry.interfaces.Exception' in event)
            self.assertTrue('sentry.interfaces.Message' in event)
            msg = event['sentry.interfaces.Message']
            self.assertEquals(msg['message'], 'This is a test error')
            self.assertEquals(msg['params'], ())

            logger.warning('This is a test warning')
            self.assertEquals(len(client.events), 1)
            event = client.events.pop(0)
            self.assertEquals(event['logger'], __name__)
            self.assertEquals(event['level'], 'warning')
            self.assertEquals(event['message'], 'This is a test warning')
            self.assertFalse('sentry.interfaces.Exception' in event)
            self.assertTrue('sentry.interfaces.Message' in event)
            msg = event['sentry.interfaces.Message']
            self.assertEquals(msg['message'], 'This is a test warning')
            self.assertEquals(msg['params'], ())

            logger.info('This is a test info with a url',
                        extra=dict(url='http://example.com', ))
            self.assertEquals(len(client.events), 1)
            event = client.events.pop(0)
            if six.PY3:
                expected = "'http://example.com'"
            else:
                expected = "u'http://example.com'"
            self.assertEquals(event['extra']['url'], expected)
            self.assertFalse('sentry.interfaces.Exception' in event)
            self.assertTrue('sentry.interfaces.Message' in event)
            msg = event['sentry.interfaces.Message']
            self.assertEquals(msg['message'], 'This is a test info with a url')
            self.assertEquals(msg['params'], ())

            try:
                raise ValueError('This is a test ValueError')
            except ValueError:
                logger.info('This is a test info with an exception',
                            exc_info=True)

            self.assertEquals(len(client.events), 1)
            event = client.events.pop(0)

            self.assertEquals(event['message'],
                              'This is a test info with an exception')
            self.assertTrue('sentry.interfaces.Exception' in event)
            exc = event['sentry.interfaces.Exception']
            self.assertEquals(exc['type'], 'ValueError')
            self.assertEquals(exc['value'], 'This is a test ValueError')
            self.assertTrue('sentry.interfaces.Message' in event)
            msg = event['sentry.interfaces.Message']
            self.assertEquals(msg['message'],
                              'This is a test info with an exception')
            self.assertEquals(msg['params'], ())

            # test args
            logger.info('This is a test of {0}', 'args')
            self.assertEquals(len(client.events), 1)
            event = client.events.pop(0)
            self.assertEquals(event['message'], 'This is a test of args')
            self.assertFalse('sentry.interfaces.Exception' in event)
            self.assertTrue('sentry.interfaces.Message' in event)
            msg = event['sentry.interfaces.Message']
            self.assertEquals(msg['message'], 'This is a test of {0}')
            expected = ("'args'", ) if six.PY3 else ("u'args'", )
            self.assertEquals(msg['params'], expected)
Esempio n. 10
0
 def test_custom_client_class(self):
     handler = SentryHandler('http://*****:*****@example.com/1',
                             client_cls=TempStoreClient)
     self.assertTrue(type(handler.client), TempStoreClient)
Esempio n. 11
0
 def test_first_arg_as_dsn(self):
     handler = SentryHandler('http://*****:*****@example.com/1')
     self.assertTrue(isinstance(handler.client, Client))
Esempio n. 12
0
 def test_client_kwarg(self):
     client = TempStoreClient(include_paths=['tests'])
     handler = SentryHandler(client=client)
     self.assertEquals(handler.client, client)
Esempio n. 13
0
    def test_logger(self):
        client = TempStoreClient(include_paths=['tests', 'raven'])
        handler = SentryHandler(client)
        logger = self.logger

        with handler.applicationbound():
            logger.error('This is a test error')

            self.assertEquals(len(client.events), 1)
            event = client.events.pop(0)
            self.assertEquals(event['logger'], __name__)
            self.assertEquals(event['level'], logbook.ERROR)
            self.assertEquals(event['message'], 'This is a test error')
            self.assertFalse('sentry.interfaces.Stacktrace' in event)
            self.assertFalse('sentry.interfaces.Exception' in event)
            self.assertTrue('sentry.interfaces.Message' in event)
            msg = event['sentry.interfaces.Message']
            self.assertEquals(msg['message'], 'This is a test error')
            self.assertEquals(msg['params'], ())

            logger.warning('This is a test warning')
            self.assertEquals(len(client.events), 1)
            event = client.events.pop(0)
            self.assertEquals(event['logger'], __name__)
            self.assertEquals(event['level'], logbook.WARNING)
            self.assertEquals(event['message'], 'This is a test warning')
            self.assertFalse('sentry.interfaces.Stacktrace' in event)
            self.assertFalse('sentry.interfaces.Exception' in event)
            self.assertTrue('sentry.interfaces.Message' in event)
            msg = event['sentry.interfaces.Message']
            self.assertEquals(msg['message'], 'This is a test warning')
            self.assertEquals(msg['params'], ())

            logger.info('This is a test info with a url', extra=dict(
                url='http://example.com',
            ))
            self.assertEquals(len(client.events), 1)
            event = client.events.pop(0)
            self.assertEquals(event['extra']['url'], 'http://example.com')
            self.assertFalse('sentry.interfaces.Stacktrace' in event)
            self.assertFalse('sentry.interfaces.Exception' in event)
            self.assertTrue('sentry.interfaces.Message' in event)
            msg = event['sentry.interfaces.Message']
            self.assertEquals(msg['message'], 'This is a test info with a url')
            self.assertEquals(msg['params'], ())

            try:
                raise ValueError('This is a test ValueError')
            except ValueError:
                logger.info('This is a test info with an exception', exc_info=True)

            self.assertEquals(len(client.events), 1)
            event = client.events.pop(0)

            self.assertEquals(event['message'], 'This is a test info with an exception')
            self.assertTrue('sentry.interfaces.Stacktrace' in event)
            self.assertTrue('sentry.interfaces.Exception' in event)
            exc = event['sentry.interfaces.Exception']
            self.assertEquals(exc['type'], 'ValueError')
            self.assertEquals(exc['value'], 'This is a test ValueError')
            self.assertTrue('sentry.interfaces.Message' in event)
            msg = event['sentry.interfaces.Message']
            self.assertEquals(msg['message'], 'This is a test info with an exception')
            self.assertEquals(msg['params'], ())

            # test args
            logger.info('This is a test of %s', 'args')
            self.assertEquals(len(client.events), 1)
            event = client.events.pop(0)
            self.assertEquals(event['message'], 'This is a test of args')
            self.assertFalse('sentry.interfaces.Stacktrace' in event)
            self.assertFalse('sentry.interfaces.Exception' in event)
            self.assertTrue('sentry.interfaces.Message' in event)
            msg = event['sentry.interfaces.Message']
            self.assertEquals(msg['message'], 'This is a test of %s')
            self.assertEquals(msg['params'], ('args',))
Esempio n. 14
0
    def test_logger(self):
        client = TempStoreClient(include_paths=['tests', 'raven'])
        handler = SentryHandler(client)
        logger = self.logger

        with handler.applicationbound():
            logger.error('This is a test error')

            self.assertEquals(len(client.events), 1)
            event = client.events.pop(0)
            self.assertEquals(event['logger'], __name__)
            self.assertEquals(event['level'], 'error')
            self.assertEquals(event['message'], 'This is a test error')
            self.assertFalse('exception' in event)
            self.assertTrue('sentry.interfaces.Message' in event)
            msg = event['sentry.interfaces.Message']
            self.assertEquals(msg['message'], 'This is a test error')
            self.assertEquals(msg['params'], ())

            logger.warning('This is a test warning')
            self.assertEquals(len(client.events), 1)
            event = client.events.pop(0)
            self.assertEquals(event['logger'], __name__)
            self.assertEquals(event['level'], 'warning')
            self.assertEquals(event['message'], 'This is a test warning')
            self.assertFalse('exception' in event)
            self.assertTrue('sentry.interfaces.Message' in event)
            msg = event['sentry.interfaces.Message']
            self.assertEquals(msg['message'], 'This is a test warning')
            self.assertEquals(msg['params'], ())

            logger.info('This is a test info with a url', extra=dict(
                url='http://example.com',
            ))
            self.assertEquals(len(client.events), 1)
            event = client.events.pop(0)
            if six.PY3:
                expected = "'http://example.com'"
            else:
                expected = "u'http://example.com'"
            self.assertEquals(event['extra']['url'], expected)
            self.assertFalse('exception' in event)
            self.assertTrue('sentry.interfaces.Message' in event)
            msg = event['sentry.interfaces.Message']
            self.assertEquals(msg['message'], 'This is a test info with a url')
            self.assertEquals(msg['params'], ())

            try:
                raise ValueError('This is a test ValueError')
            except ValueError:
                logger.info('This is a test info with an exception', exc_info=True)

            self.assertEquals(len(client.events), 1)
            event = client.events.pop(0)

            self.assertEquals(event['message'], 'This is a test info with an exception')
            assert 'exception' in event
            exc = event['exception']['values'][-1]
            self.assertEquals(exc['type'], 'ValueError')
            self.assertEquals(exc['value'], 'This is a test ValueError')
            self.assertTrue('sentry.interfaces.Message' in event)
            msg = event['sentry.interfaces.Message']
            self.assertEquals(msg['message'], 'This is a test info with an exception')
            self.assertEquals(msg['params'], ())

            # test args
            logger.info('This is a test of {0}', 'args')
            self.assertEquals(len(client.events), 1)
            event = client.events.pop(0)
            self.assertEquals(event['message'], 'This is a test of args')
            assert 'exception' not in event
            self.assertTrue('sentry.interfaces.Message' in event)
            msg = event['sentry.interfaces.Message']
            self.assertEquals(msg['message'], 'This is a test of {0}')
            expected = ("'args'",) if six.PY3 else ("u'args'",)
            self.assertEquals(msg['params'], expected)
Esempio n. 15
0
def create_app(offline=False) -> Flask:
    """创建 flask app
    @param offline: 如果设置为 `True`,则为离线模式。此模式下不会连接到 Sentry 和 ElasticAPM
    """
    app = Flask(__name__,
                static_folder='../../frontend/dist',
                static_url_path='',
                template_folder="../../frontend/templates")

    # load app config
    from everyclass.server.config import get_config
    _config = get_config()
    app.config.from_object(_config)

    # CDN
    CDN(app)

    # logbook handlers
    # 规则如下:
    # - 全部输出到 stdout(本地开发调试、服务器端文件日志)
    # - Elastic APM 或者 LogStash(日志中心)
    # - WARNING 以上级别的输出到 Sentry
    #
    # 日志等级:
    # critical – for errors that lead to termination
    # error – for errors that occur, but are handled
    # warning – for exceptional circumstances that might not be errors
    # notice – for non-error messages you usually want to see
    # info – for messages you usually don’t want to see
    # debug – for debug messages
    #
    # Elastic APM:
    # log.info("Nothing to see here", stack=False)
    # stack 默认是 True,设置为 False 将不会向 Elastic APM 发送 stack trace
    # https://discuss.elastic.co/t/how-to-use-logbook-handler/146209/6
    #
    # Sentry:
    # https://docs.sentry.io/clients/python/api/#raven.Client.captureMessage
    # - stack 默认是 False,和 Elastic APM 的不一致,所以还是每次手动指定吧...
    # - 默认事件类型是 `raven.events.Message`,设置 `exc_info` 为 `True` 将把事件类型升级为`raven.events.Exception`
    stderr_handler = logbook.StderrHandler(bubble=True)
    logger.handlers.append(stderr_handler)

    if not offline:
        # Sentry
        sentry.init_app(app=app)
        sentry_handler = SentryHandler(
            sentry.client, level='WARNING')  # Sentry 只处理 WARNING 以上的
        logger.handlers.append(sentry_handler)

        # Elastic APM
        apm = ElasticAPM(app)
        elastic_handler = ElasticHandler(client=apm.client, bubble=True)
        logger.handlers.append(elastic_handler)

    # 初始化数据库
    if os.getenv('MODE', None) != "CI":
        init_pool(app)

    # 导入并注册 blueprints
    from everyclass.server.calendar.views import cal_blueprint
    from everyclass.server.query import query_blueprint
    from everyclass.server.views import main_blueprint as main_blueprint
    from everyclass.server.api import api_v1 as api_blueprint
    app.register_blueprint(cal_blueprint)
    app.register_blueprint(query_blueprint)
    app.register_blueprint(main_blueprint)
    app.register_blueprint(api_blueprint, url_prefix='/api/v1')

    @app.before_request
    def set_user_id():
        """在请求之前设置 session uid,方便 Elastic APM 记录用户请求"""
        if not session.get('user_id', None):
            # 数据库中生成唯一 ID,参考 https://blog.csdn.net/longjef/article/details/53117354
            conn = get_local_conn()
            cursor = conn.cursor()
            cursor.execute(
                "REPLACE INTO user_id_sequence (stub) VALUES ('a');")
            session['user_id'] = cursor.lastrowid
            cursor.close()

    @app.teardown_request
    def close_db(error):
        """结束时关闭数据库连接"""
        if hasattr(g, 'mysql_db') and g.mysql_db:
            g.mysql_db.close()

    @app.after_request
    def response_minify(response):
        """用 htmlmin 压缩 HTML,减轻带宽压力"""
        if app.config[
                'HTML_MINIFY'] and response.content_type == u'text/html; charset=utf-8':
            response.set_data(minify(response.get_data(as_text=True)))
        return response

    @app.template_filter('versioned')
    def version_filter(filename):
        """
        模板过滤器。如果 STATIC_VERSIONED,返回类似 'style-v1-c012dr.css' 的文件,而不是 'style-v1.css'

        :param filename: 文件名
        :return: 新的文件名
        """
        if app.config['STATIC_VERSIONED']:
            if filename[:4] == 'css/':
                new_filename = app.config['STATIC_MANIFEST'][filename[4:]]
                return 'css/' + new_filename
            elif filename[:3] == 'js/':
                new_filename = app.config['STATIC_MANIFEST'][filename[3:]]
                return new_filename
            else:
                return app.config['STATIC_MANIFEST'][filename]
        return filename

    @app.errorhandler(500)
    def internal_server_error(error):
        return render_template(
            '500.html',
            event_id=g.sentry_event_id,
            public_dsn=sentry.client.get_public_dsn('https'))

    logger.info('App created with `{}` config'.format(
        app.config['CONFIG_NAME']),
                stack=False)
    return app
Esempio n. 16
0
def create_app(offline=False) -> Flask:
    """创建 flask app
    @param offline: 如果设置为 `True`,则为离线模式。此模式下不会连接到 Sentry 和 ElasticAPM
    """
    from everyclass.api_server.db.dao import new_user_id_sequence
    from everyclass.api_server.db.mysql import get_connection, init_pool
    from everyclass.api_server.utils.log import LogstashHandler, LogstashFormatter, LOG_FORMAT_STRING

    app = Flask(__name__)

    # load app config
    from everyclass.api_server.config import get_config
    _config = get_config()
    app.config.from_object(_config)
    """
    每课统一日志机制


    规则如下:
    - WARNING 以下 log 输出到 stdout
    - WARNING 以上输出到 stderr
    - DEBUG 以上日志以 json 形式通过 TCP 输出到 Logstash,然后发送到日志中心
    - WARNING 以上级别的输出到 Sentry


    日志等级:
    critical – for errors that lead to termination
    error – for errors that occur, but are handled
    warning – for exceptional circumstances that might not be errors
    notice – for non-error messages you usually want to see
    info – for messages you usually don’t want to see
    debug – for debug messages
    
    
    Sentry:
    https://docs.sentry.io/clients/python/api/#raven.Client.captureMessage
    - stack 默认是 False
    
    """
    stdout_handler = logbook.StreamHandler(stream=sys.stdout,
                                           bubble=True,
                                           filter=lambda r, h: r.level < 13)
    stdout_handler.format_string = LOG_FORMAT_STRING
    logger.handlers.append(stdout_handler)

    stderr_handler = logbook.StreamHandler(stream=sys.stderr,
                                           bubble=True,
                                           level='WARNING')
    stderr_handler.format_string = LOG_FORMAT_STRING
    logger.handlers.append(stderr_handler)

    if not offline and (app.config['CONFIG_NAME']
                        in ["production", "staging", "testing"]):
        # Sentry
        sentry.init_app(app=app)
        sentry_handler = SentryHandler(
            sentry.client, level='WARNING')  # Sentry 只处理 WARNING 以上的
        logger.handlers.append(sentry_handler)

        # Elastic APM
        ElasticAPM(app)

        # Log to Logstash
        logstash_handler = LogstashHandler(
            host=app.config['LOGSTASH']['HOST'],
            port=app.config['LOGSTASH']['PORT'],
            release=app.config['GIT_DESCRIBE'],
            bubble=True,
            logger=logger,
            filter=lambda r, h: r.level >= 11)  # do not send DEBUG
        logger.handlers.append(logstash_handler)

    # 初始化数据库
    if not offline and (app.config['CONFIG_NAME']
                        in ("production", "staging", "testing",
                            "development")):
        init_pool(app)

    # 导入并注册 blueprints
    from everyclass.api_server.views import main_blueprint as main_blueprint
    from everyclass.api_server.api import api_v1 as api_blueprint
    app.register_blueprint(main_blueprint)
    app.register_blueprint(api_blueprint, url_prefix='/api/v1')

    @app.errorhandler(500)
    def internal_server_error():
        return jsonify({
            'success': False,
            'message': 'Server could not response to the request.'
        })

    logger.info('App created with `{0}` config'.format(
        app.config['CONFIG_NAME']),
                stack=False)

    # 输出配置内容
    logger.info('Below are configurations we are using:')
    logger.info(
        '================================================================')
    for key, value in app.config.items():
        if key not in ('SECRET_KEY', ):
            value = copy.copy(value)

            # 敏感内容抹去
            if key == 'SENTRY_CONFIG':
                value['dsn'] = '[secret]'
            if key == 'MYSQL_CONFIG':
                value['password'] = '******'
            if key == 'ELASTIC_APM':
                value['SECRET_TOKEN'] = '[secret]'

            logger.info('{}: {}'.format(key, value))
    logger.info(
        '================================================================')

    return app
Esempio n. 17
0
    def init_log_handlers():
        """init log handlers"""
        from everyclass.server.utils.logbook_logstash.handler import LogstashHandler
        from elasticapm.contrib.flask import ElasticAPM
        from everyclass.server.utils import monkey_patch
        ElasticAPM.request_finished = monkey_patch.ElasticAPM.request_finished(
            ElasticAPM.request_finished)

        global __app
        # Sentry
        if __app.config['CONFIG_NAME'] in __app.config['SENTRY_AVAILABLE_IN']:
            sentry.init_app(app=__app)
            sentry_handler = SentryHandler(
                sentry.client, level='WARNING')  # Sentry 只处理 WARNING 以上的
            logger.handlers.append(sentry_handler)
            logger.info('You are in {} mode, so Sentry is inited.'.format(
                __app.config['CONFIG_NAME']))

        # Elastic APM
        if __app.config['CONFIG_NAME'] in __app.config['APM_AVAILABLE_IN']:
            ElasticAPM(__app)
            logger.info('You are in {} mode, so APM is inited.'.format(
                __app.config['CONFIG_NAME']))

        # Logstash centralized log
        if __app.config['CONFIG_NAME'] in __app.config[
                'LOGSTASH_AVAILABLE_IN']:
            logstash_handler = LogstashHandler(
                host=__app.config['LOGSTASH']['HOST'],
                port=__app.config['LOGSTASH']['PORT'],
                release=__app.config['GIT_DESCRIBE'],
                bubble=True,
                logger=logger,
                filter=lambda r, h: r.level >= 11)  # do not send DEBUG
            logger.handlers.append(logstash_handler)
            logger.info(
                'You are in {} mode, so LogstashHandler is inited.'.format(
                    __app.config['CONFIG_NAME']))

        # print current configuration
        import uwsgi
        if uwsgi.worker_id() == 1:
            # set to warning level because we want to monitor restarts
            logger.warning('App (re)started in `{0}` environment'.format(
                __app.config['CONFIG_NAME']),
                           stack=False)

            logger.info('Below are configurations we are using:')
            logger.info(
                '================================================================'
            )
            for key, value in __app.config.items():
                if key not in ('SECRET_KEY', ):
                    value = copy.copy(value)

                    # 敏感内容抹去
                    if key == 'SENTRY_CONFIG':
                        value['dsn'] = '[secret]'
                    if key == 'MYSQL_CONFIG':
                        value['password'] = '******'
                    if key == 'ELASTIC_APM':
                        value['SECRET_TOKEN'] = '[secret]'

                    logger.info('{}: {}'.format(key, value))
            logger.info(
                '================================================================'
            )
Esempio n. 18
0
    chain: Signature = signature("tasks.fetch", kwargs={"url": url})
    chain |= signature("tasks.analyze", kwargs={"url": url})
    try:
        task: AsyncResult = chain()
    except OperationalError:
        log.critical("Cannot connect to broker: {0}".format(
            configs[environment].broker_url))
        return json(Protocol(500, "Something went wrong. Sorry :(")._asdict())
    return json(Protocol(200, task.task_id)._asdict())


def main() -> None:  # pragma: no cover
    """Run the application.
    :return: None
    """
    import asyncio
    from multiprocessing import cpu_count
    import uvloop
    asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
    workers: int = cpu_count()
    app.run(host="0.0.0.0",
            port=configs[environment].PORT,
            workers=workers,
            debug=configs[environment].DEBUG)


if __name__ == '__main__':
    handler = SentryHandler(client=configs[environment].sentry_client)
    with handler.applicationbound():
        main()