Coverage for src/app.py: 0%

50 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-12-29 01:26 +0000

1import logging 

2import signal 

3import sys 

4 

5import sentry_sdk 

6from sentry_sdk.integrations import argv, atexit, dedupe, modules, stdlib, threading 

7from sentry_sdk.integrations import logging as sentry_logging 

8from sqlalchemy.sql import text 

9 

10from couchers.config import check_config, config 

11from couchers.db import apply_migrations, session_scope 

12from couchers.jobs.worker import start_jobs_scheduler, start_jobs_worker 

13from couchers.metrics import create_prometheus_server, main_process_registry 

14from couchers.server import create_main_server, create_media_server 

15from couchers.tracing import setup_tracing 

16from dummy_data import add_dummy_data 

17 

18check_config() 

19 

20logging.basicConfig(format="[%(process)5d:%(thread)20d] %(asctime)s: %(name)s: %(message)s", level=logging.INFO) 

21logger = logging.getLogger(__name__) 

22 

23logging.getLogger("couchers.jobs.worker").setLevel(logging.INFO) 

24 

25if config["SENTRY_ENABLED"]: 

26 # Sends exception tracebacks to Sentry, a cloud service for collecting exceptions 

27 sentry_sdk.init( 

28 config["SENTRY_URL"], 

29 traces_sample_rate=0.0, 

30 environment=config["COOKIE_DOMAIN"], 

31 release=config["VERSION"], 

32 default_integrations=False, 

33 integrations=[ 

34 # we need to manually list out the integrations, there is no other way of disabling the global excepthook integration 

35 # we want to disable that because it seems to be picking up already handled gRPC errors (e.g. grpc.StatusCode.NOT_FOUND) 

36 argv.ArgvIntegration(), 

37 atexit.AtexitIntegration(), 

38 dedupe.DedupeIntegration(), 

39 sentry_logging.LoggingIntegration(), 

40 modules.ModulesIntegration(), 

41 stdlib.StdlibIntegration(), 

42 threading.ThreadingIntegration(), 

43 ], 

44 ) 

45 

46# used to export metrics 

47create_prometheus_server(main_process_registry, 8000) 

48 

49 

50def log_unhandled_exception(exc_type, exc_value, exc_traceback): 

51 """Make sure that any unhandled exceptions will write to the logs""" 

52 if issubclass(exc_type, KeyboardInterrupt): 

53 # call the default excepthook saved at __excepthook__ 

54 sys.__excepthook__(exc_type, exc_value, exc_traceback) 

55 return 

56 logger.critical("Unhandled exception", exc_info=(exc_type, exc_value, exc_traceback)) 

57 

58 

59sys.excepthook = log_unhandled_exception 

60 

61logger.info("Checking DB connection") 

62 

63with session_scope() as session: 

64 res = session.execute(text("SELECT 42;")) 

65 if list(res) != [(42,)]: 

66 raise Exception("Failed to connect to DB") 

67 

68logger.info("Running DB migrations") 

69 

70apply_migrations() 

71 

72if config["ADD_DUMMY_DATA"]: 

73 add_dummy_data() 

74 

75logger.info("Starting") 

76 

77if config["ROLE"] in ["scheduler", "all"]: 

78 scheduler = start_jobs_scheduler() 

79 

80if config["ROLE"] in ["worker", "all"]: 

81 worker = start_jobs_worker() 

82 

83setup_tracing() 

84 

85if config["ROLE"] in ["api", "all"]: 

86 server = create_main_server(port=1751) 

87 server.start() 

88 media_server = create_media_server(port=1753) 

89 media_server.start() 

90 logger.info("Serving on 1751 (secure) and 1753 (media)") 

91 

92logger.info("App waiting for signal...") 

93 

94signal.pause()