import contextlib import logging import os import sentry_sdk from aiohttp import ClientSession, TCPConnector, TraceConfig, web from aiohttp_apispec import validation_middleware, setup_aiohttp_apispec from aiojobs.aiohttp import setup from ddtrace import patch_all, tracer, config as dd_config from ddtrace.contrib.aiohttp import trace_app from sentry_sdk.integrations.aiohttp import AioHttpIntegration from sentry_sdk.utils import BadDsn import config from server.apple.client import AppleMusic from server.apple.routes import init_routes as init_apple_routes from server.core.cache.storage import cache_backend from server.core.middlewares import auth_middleware, error_middleware, header_middleware, logging_middleware from server.core.routes import init_routes as init_core_routes from server.core.sqs import get_sqs_client from server.spotify.client import Spotify, SpotifyClientCredentials from server.spotify.routes import init_routes as init_spotify_routes logger = logging.getLogger("app") def init_sentry(): """Init sentry for project""" if config.SENTRY_DSN: try: sentry_sdk.init( dsn=config.SENTRY_DSN, environment=config.ENVIRONMENT, release=f"{config.SENTRY_PROJECT}@{config.VERSION}", integrations=[AioHttpIntegration()], ) except BadDsn: pass async def on_request_end(session, trace_config_ctx, params): req = params.response logger.info(f"Request {req.method} {req.url} {req.status}") async def context(app: web.Application) -> None: if config.DEBUG: trace_config = TraceConfig() trace_config.on_request_end.append(on_request_end) trace_configs = [trace_config] else: trace_configs = None session = ClientSession(connector=TCPConnector(ssl=False, limit=0), trace_configs=trace_configs) app["apple_api"] = AppleMusic(session) app["spotify_api"] = Spotify(session=session, credentials=SpotifyClientCredentials()) app["cache_backend"] = cache_backend app["cache_backend"].init() context_stack = contextlib.AsyncExitStack() app["context_stack"] = context_stack app["sqs_client"] = await get_sqs_client(context_stack) yield await app["context_stack"].aclose() await app["cache_backend"].close() await session.close() def create_app() -> web.Application: """Application factory""" logging.basicConfig(level=logging.INFO) init_sentry() app = web.Application( middlewares=[error_middleware, logging_middleware, auth_middleware, validation_middleware, header_middleware], handler_args={"max_line_size": config.MAX_LINE_SIZE, "max_field_size": config.MAX_FIELD_SIZE}, ) app.cleanup_ctx.append(context) setup_aiohttp_apispec( app=app, title="Vendor API", version="1.0.0", swagger_path="/api/doc/", securityDefinitions={ "apiKey": { "type": "apiKey", "name": "Authorization", "in": "header", "description": "For example: Bearer test", } }, schemes=["http", "https"], security=[{"apiKey": []}], ) init_apple_routes(app) init_spotify_routes(app) init_core_routes(app) if os.environ.get("DATADOG_SERVICE_NAME"): patch_all() dd_config.http.trace_query_string = True dd_config.trace_headers(config.DD_TRACE_HEADERS) trace_app(app, tracer) setup(app) return app async def main() -> web.Application: """Main entry point""" return create_app() if __name__ == "__main__": web.run_app(main())