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)
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)
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()
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()
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
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
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)
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)
def test_custom_client_class(self): handler = SentryHandler('http://*****:*****@example.com/1', client_cls=TempStoreClient) self.assertTrue(type(handler.client), TempStoreClient)
def test_first_arg_as_dsn(self): handler = SentryHandler('http://*****:*****@example.com/1') self.assertTrue(isinstance(handler.client, Client))
def test_client_kwarg(self): client = TempStoreClient(include_paths=['tests']) handler = SentryHandler(client=client) self.assertEquals(handler.client, client)
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',))
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)
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
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
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( '================================================================' )
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()