diff --git a/.env-devel b/.env-devel index af3cb9ae7cc3..f47839476369 100644 --- a/.env-devel +++ b/.env-devel @@ -274,10 +274,12 @@ VENDOR_DEV_MANUAL_SUBDOMAIN=manual WB_API_WEBSERVER_HOST=wb-api-server WB_API_WEBSERVER_PORT=8080 -WB_AUTH_WEBSERVER_HOST=wb-auth -WB_AUTH_WEBSERVER_PORT=8080 +WB_AUTH_DIAGNOSTICS={} WB_AUTH_LOGLEVEL=INFO +WB_AUTH_PROFILING=1 WB_AUTH_TRACING={} +WB_AUTH_WEBSERVER_HOST=wb-auth +WB_AUTH_WEBSERVER_PORT=8080 WB_GC_ACTIVITY=null WB_GC_ANNOUNCEMENTS=0 diff --git a/packages/service-library/src/servicelib/aiohttp/tracing.py b/packages/service-library/src/servicelib/aiohttp/tracing.py index 9aa8b9e57285..7f26ebf27ded 100644 --- a/packages/service-library/src/servicelib/aiohttp/tracing.py +++ b/packages/service-library/src/servicelib/aiohttp/tracing.py @@ -63,11 +63,11 @@ def _create_span_processor(tracing_destination: str) -> SpanProcessor: otlp_exporter = OTLPSpanExporterHTTP( endpoint=tracing_destination, ) - span_processor = BatchSpanProcessor(otlp_exporter) - return span_processor + return BatchSpanProcessor(otlp_exporter) def _startup( + *, app: web.Application, tracing_settings: TracingSettings, service_name: str, @@ -177,7 +177,7 @@ async def response_trace_id_header_middleware(request: web.Request, handler): except web.HTTPException as exc: if headers: exc.headers.update(headers) - raise exc + raise if headers: response.headers.update(headers) return response diff --git a/packages/service-library/src/servicelib/utils_meta.py b/packages/service-library/src/servicelib/utils_meta.py index dfdcc6447522..1109e3089c59 100644 --- a/packages/service-library/src/servicelib/utils_meta.py +++ b/packages/service-library/src/servicelib/utils_meta.py @@ -34,10 +34,11 @@ def __init__(self, package_name: str): self._distribution = distribution(package_name) # property checks if re.match(_APP_NAME_PATTERN, self.app_name) is None: - raise ValueError( + msg = ( f"Invalid package name {self.app_name}. " "It must be all lowercase and words separated by dashes ('-')." ) + raise ValueError(msg) @property def project_name(self) -> str: diff --git a/services/docker-compose.yml b/services/docker-compose.yml index 8411efad7b22..b5546e697c87 100644 --- a/services/docker-compose.yml +++ b/services/docker-compose.yml @@ -12,6 +12,13 @@ x-tracing-open-telemetry: &tracing_open_telemetry_environs TRACING_OPENTELEMETRY_COLLECTOR_PORT: ${TRACING_OPENTELEMETRY_COLLECTOR_PORT} TRACING_OPENTELEMETRY_COLLECTOR_SAMPLING_PERCENTAGE: ${TRACING_OPENTELEMETRY_COLLECTOR_SAMPLING_PERCENTAGE} +x-webserver-diagnostics: &webserver_diagnostics_environs + DIAGNOSTICS_HEALTHCHECK_ENABLED: ${DIAGNOSTICS_HEALTHCHECK_ENABLED} + DIAGNOSTICS_MAX_AVG_LATENCY: ${DIAGNOSTICS_MAX_AVG_LATENCY} + DIAGNOSTICS_MAX_TASK_DELAY: ${DIAGNOSTICS_MAX_TASK_DELAY} + DIAGNOSTICS_SLOW_DURATION_SECS: ${DIAGNOSTICS_SLOW_DURATION_SECS} + + services: api-server: @@ -19,6 +26,7 @@ services: init: true hostname: "{{.Node.Hostname}}-{{.Task.Slot}}" environment: + <<: *tracing_open_telemetry_environs API_SERVER_DEV_FEATURES_ENABLED: ${API_SERVER_DEV_FEATURES_ENABLED} API_SERVER_LOG_FORMAT_LOCAL_DEV_ENABLED: ${LOG_FORMAT_LOCAL_DEV_ENABLED} API_SERVER_LOG_FILTER_MAPPING: ${LOG_FILTER_MAPPING} @@ -50,7 +58,6 @@ services: WEBSERVER_PORT: ${WB_API_WEBSERVER_PORT} WEBSERVER_SESSION_SECRET_KEY: ${WEBSERVER_SESSION_SECRET_KEY} API_SERVER_TRACING: ${API_SERVER_TRACING} - <<: *tracing_open_telemetry_environs deploy: labels: @@ -78,6 +85,7 @@ services: networks: - autoscaling_subnet environment: + <<: *tracing_open_telemetry_environs AUTOSCALING_LOGLEVEL: ${AUTOSCALING_LOGLEVEL} AUTOSCALING_POLL_INTERVAL: ${AUTOSCALING_POLL_INTERVAL} AUTOSCALING_DRAIN_NODES_WITH_LABELS: ${AUTOSCALING_DRAIN_NODES_WITH_LABELS} @@ -136,7 +144,6 @@ services: REGISTRY_SSL: ${REGISTRY_SSL} REGISTRY_AUTH: ${REGISTRY_AUTH} AUTOSCALING_TRACING: ${AUTOSCALING_TRACING} - <<: *tracing_open_telemetry_environs volumes: - "/var/run/docker.sock:/var/run/docker.sock" deploy: @@ -156,6 +163,7 @@ services: init: true hostname: "cat-{{.Node.Hostname}}-{{.Task.Slot}}" environment: + <<: *tracing_open_telemetry_environs CATALOG_BACKGROUND_TASK_REST_TIME: ${CATALOG_BACKGROUND_TASK_REST_TIME} CATALOG_DEV_FEATURES_ENABLED: ${CATALOG_DEV_FEATURES_ENABLED} CATALOG_LOGLEVEL: ${CATALOG_LOGLEVEL} @@ -179,7 +187,6 @@ services: RABBIT_SECURE: ${RABBIT_SECURE} RABBIT_USER: ${RABBIT_USER} CATALOG_TRACING: ${CATALOG_TRACING} - <<: *tracing_open_telemetry_environs networks: - default @@ -190,6 +197,7 @@ services: networks: - default environment: + <<: *tracing_open_telemetry_environs CLUSTERS_KEEPER_COMPUTATIONAL_BACKEND_DOCKER_IMAGE_TAG: ${CLUSTERS_KEEPER_COMPUTATIONAL_BACKEND_DOCKER_IMAGE_TAG} CLUSTERS_KEEPER_COMPUTATIONAL_BACKEND_DEFAULT_CLUSTER_AUTH: ${CLUSTERS_KEEPER_COMPUTATIONAL_BACKEND_DEFAULT_CLUSTER_AUTH} CLUSTERS_KEEPER_DASK_NTHREADS: ${CLUSTERS_KEEPER_DASK_NTHREADS} @@ -248,7 +256,6 @@ services: WORKERS_EC2_INSTANCES_SUBNET_ID: ${WORKERS_EC2_INSTANCES_SUBNET_ID} WORKERS_EC2_INSTANCES_CUSTOM_TAGS: ${WORKERS_EC2_INSTANCES_CUSTOM_TAGS} CLUSTERS_KEEPER_TRACING: ${CLUSTERS_KEEPER_TRACING} - <<: *tracing_open_telemetry_environs secrets: *dask_tls_secrets director: @@ -256,6 +263,7 @@ services: init: true hostname: "{{.Node.Hostname}}-{{.Task.Slot}}" environment: + <<: *tracing_open_telemetry_environs DIRECTOR_DEFAULT_MAX_MEMORY: ${DIRECTOR_DEFAULT_MAX_MEMORY} DIRECTOR_DEFAULT_MAX_NANO_CPUS: ${DIRECTOR_DEFAULT_MAX_NANO_CPUS} DIRECTOR_GENERIC_RESOURCE_PLACEMENT_CONSTRAINTS_SUBSTITUTIONS: ${DIRECTOR_GENERIC_RESOURCE_PLACEMENT_CONSTRAINTS_SUBSTITUTIONS} @@ -285,7 +293,6 @@ services: STORAGE_ENDPOINT: ${STORAGE_ENDPOINT} SWARM_STACK_NAME: ${SWARM_STACK_NAME} - <<: *tracing_open_telemetry_environs TRAEFIK_SIMCORE_ZONE: ${TRAEFIK_SIMCORE_ZONE} volumes: @@ -303,6 +310,7 @@ services: init: true hostname: "{{.Node.Hostname}}-{{.Task.Slot}}" environment: + <<: *tracing_open_telemetry_environs AWS_S3_CLI_S3: ${AWS_S3_CLI_S3} CATALOG_HOST: ${CATALOG_HOST} @@ -390,7 +398,6 @@ services: TRAEFIK_SIMCORE_ZONE: ${TRAEFIK_SIMCORE_ZONE} DIRECTOR_V2_TRACING: ${DIRECTOR_V2_TRACING} - <<: *tracing_open_telemetry_environs # WEBSERVER_AUTH_SETTINGS WEBSERVER_HOST: ${WB_AUTH_WEBSERVER_HOST} @@ -415,6 +422,7 @@ services: networks: - default environment: + <<: *tracing_open_telemetry_environs LOG_FORMAT_LOCAL_DEV_ENABLED: ${LOG_FORMAT_LOCAL_DEV_ENABLED} LOG_FILTER_MAPPING: ${LOG_FILTER_MAPPING} RABBIT_HOST: ${RABBIT_HOST} @@ -443,7 +451,6 @@ services: EFS_MOUNTED_PATH: ${EFS_MOUNTED_PATH} EFS_PROJECT_SPECIFIC_DATA_DIRECTORY: ${EFS_PROJECT_SPECIFIC_DATA_DIRECTORY} EFS_GUARDIAN_TRACING: ${EFS_GUARDIAN_TRACING} - <<: *tracing_open_telemetry_environs invitations: image: ${DOCKER_REGISTRY:-itisfoundation}/invitations:${DOCKER_IMAGE_TAG:-latest} @@ -452,17 +459,17 @@ services: networks: - default environment: + <<: *tracing_open_telemetry_environs INVITATIONS_DEFAULT_PRODUCT: ${INVITATIONS_DEFAULT_PRODUCT} INVITATIONS_LOGLEVEL: ${INVITATIONS_LOGLEVEL} INVITATIONS_OSPARC_URL: ${INVITATIONS_OSPARC_URL} INVITATIONS_PASSWORD: ${INVITATIONS_PASSWORD} INVITATIONS_SECRET_KEY: ${INVITATIONS_SECRET_KEY} INVITATIONS_SWAGGER_API_DOC_ENABLED: ${INVITATIONS_SWAGGER_API_DOC_ENABLED} + INVITATIONS_TRACING: ${INVITATIONS_TRACING} INVITATIONS_USERNAME: ${INVITATIONS_USERNAME} LOG_FORMAT_LOCAL_DEV_ENABLED: ${LOG_FORMAT_LOCAL_DEV_ENABLED} LOG_FILTER_MAPPING: ${LOG_FILTER_MAPPING} - INVITATIONS_TRACING: ${INVITATIONS_TRACING} - <<: *tracing_open_telemetry_environs payments: image: ${DOCKER_REGISTRY:-itisfoundation}/payments:${DOCKER_IMAGE_TAG:-latest} @@ -471,8 +478,10 @@ services: networks: - default environment: - LOG_FORMAT_LOCAL_DEV_ENABLED: ${LOG_FORMAT_LOCAL_DEV_ENABLED} + <<: *tracing_open_telemetry_environs + LOG_FILTER_MAPPING: ${LOG_FILTER_MAPPING} + LOG_FORMAT_LOCAL_DEV_ENABLED: ${LOG_FORMAT_LOCAL_DEV_ENABLED} PAYMENTS_ACCESS_TOKEN_EXPIRE_MINUTES: ${PAYMENTS_ACCESS_TOKEN_EXPIRE_MINUTES} PAYMENTS_ACCESS_TOKEN_SECRET_KEY: ${PAYMENTS_ACCESS_TOKEN_SECRET_KEY} PAYMENTS_AUTORECHARGE_DEFAULT_MONTHLY_LIMIT: ${PAYMENTS_AUTORECHARGE_DEFAULT_MONTHLY_LIMIT} @@ -480,13 +489,15 @@ services: PAYMENTS_AUTORECHARGE_ENABLED: ${PAYMENTS_AUTORECHARGE_ENABLED} PAYMENTS_AUTORECHARGE_MIN_BALANCE_IN_CREDITS: ${PAYMENTS_AUTORECHARGE_MIN_BALANCE_IN_CREDITS} PAYMENTS_BCC_EMAIL: ${PAYMENTS_BCC_EMAIL} + PAYMENTS_EMAIL: ${PAYMENTS_EMAIL} PAYMENTS_GATEWAY_API_SECRET: ${PAYMENTS_GATEWAY_API_SECRET} PAYMENTS_GATEWAY_URL: ${PAYMENTS_GATEWAY_URL} PAYMENTS_LOGLEVEL: ${PAYMENTS_LOGLEVEL} PAYMENTS_PASSWORD: ${PAYMENTS_PASSWORD} - PAYMENTS_STRIPE_URL: ${PAYMENTS_STRIPE_URL} PAYMENTS_STRIPE_API_SECRET: ${PAYMENTS_STRIPE_API_SECRET} + PAYMENTS_STRIPE_URL: ${PAYMENTS_STRIPE_URL} PAYMENTS_SWAGGER_API_DOC_ENABLED: ${PAYMENTS_SWAGGER_API_DOC_ENABLED} + PAYMENTS_TRACING: ${PAYMENTS_TRACING} PAYMENTS_USERNAME: ${PAYMENTS_USERNAME} POSTGRES_DB: ${POSTGRES_DB} POSTGRES_HOST: ${POSTGRES_HOST} @@ -500,14 +511,12 @@ services: RABBIT_USER: ${RABBIT_USER} RESOURCE_USAGE_TRACKER_HOST: ${RESOURCE_USAGE_TRACKER_HOST} RESOURCE_USAGE_TRACKER_PORT: ${RESOURCE_USAGE_TRACKER_EXTERNAL_PORT} - PAYMENTS_EMAIL: ${PAYMENTS_EMAIL} SMTP_HOST: ${SMTP_HOST} SMTP_PASSWORD: ${SMTP_PASSWORD} SMTP_PORT: ${SMTP_PORT} SMTP_PROTOCOL: ${SMTP_PROTOCOL} SMTP_USERNAME: ${SMTP_USERNAME} - PAYMENTS_TRACING: ${PAYMENTS_TRACING} - <<: *tracing_open_telemetry_environs + resource-usage-tracker: image: ${DOCKER_REGISTRY:-itisfoundation}/resource-usage-tracker:${DOCKER_IMAGE_TAG:-latest} @@ -516,6 +525,8 @@ services: networks: - default environment: + <<: *tracing_open_telemetry_environs + LOG_FORMAT_LOCAL_DEV_ENABLED: ${LOG_FORMAT_LOCAL_DEV_ENABLED} LOG_FILTER_MAPPING: ${LOG_FILTER_MAPPING} POSTGRES_DB: ${POSTGRES_DB} @@ -544,7 +555,7 @@ services: RESOURCE_USAGE_TRACKER_S3: ${RESOURCE_USAGE_TRACKER_S3} RESOURCE_USAGE_TRACKER_TRACING: ${RESOURCE_USAGE_TRACKER_TRACING} RESOURCE_USAGE_TRACKER_PORT: ${RESOURCE_USAGE_TRACKER_PORT} - <<: *tracing_open_telemetry_environs + dynamic-schdlr: image: ${DOCKER_REGISTRY:-itisfoundation}/dynamic-scheduler:${DOCKER_IMAGE_TAG:-latest} @@ -554,6 +565,8 @@ services: - default - docker-api-network environment: + <<: *tracing_open_telemetry_environs + CATALOG_HOST: ${CATALOG_HOST} CATALOG_PORT: ${CATALOG_PORT} DIRECTOR_V2_HOST: ${DIRECTOR_V2_HOST} @@ -594,7 +607,6 @@ services: REDIS_SECURE: ${REDIS_SECURE} REDIS_USER: ${REDIS_USER} - <<: *tracing_open_telemetry_environs docker-api-proxy: image: ${DOCKER_REGISTRY:-itisfoundation}/docker-api-proxy:${DOCKER_IMAGE_TAG:-latest} @@ -670,6 +682,10 @@ services: init: true hostname: "wb-{{.Node.Hostname}}-{{.Task.Slot}}" # the hostname is used in conjonction with other services and must be unique see https://github.com/ITISFoundation/osparc-simcore/pull/5931 environment: &webserver_environment + <<: + - *tracing_open_telemetry_environs + - *webserver_diagnostics_environs + AIODEBUG_SLOW_DURATION_SECS: ${AIODEBUG_SLOW_DURATION_SECS} SWARM_STACK_NAME: ${SWARM_STACK_NAME} @@ -714,10 +730,6 @@ services: # WEBSERVER_DIAGNOSTICS WEBSERVER_DIAGNOSTICS: ${WEBSERVER_DIAGNOSTICS} - DIAGNOSTICS_HEALTHCHECK_ENABLED: ${DIAGNOSTICS_HEALTHCHECK_ENABLED} - DIAGNOSTICS_MAX_AVG_LATENCY: ${DIAGNOSTICS_MAX_AVG_LATENCY} - DIAGNOSTICS_MAX_TASK_DELAY: ${DIAGNOSTICS_MAX_TASK_DELAY} - DIAGNOSTICS_SLOW_DURATION_SECS: ${DIAGNOSTICS_SLOW_DURATION_SECS} # WEBSERVER_DIRECTOR_V2 DIRECTOR_V2_HOST: ${DIRECTOR_V2_HOST} @@ -819,7 +831,6 @@ services: STUDIES_DEFAULT_SERVICE_THUMBNAIL: ${STUDIES_DEFAULT_SERVICE_THUMBNAIL} WEBSERVER_TRACING: ${WEBSERVER_TRACING} - <<: *tracing_open_telemetry_environs # WEBSERVER_PROJECTS WEBSERVER_PROJECTS: ${WEBSERVER_PROJECTS} @@ -1009,6 +1020,8 @@ services: init: true hostname: "gc-{{.Node.Hostname}}-{{.Task.Slot}}" # the hostname is used in conjonction with other services and must be unique see https://github.com/ITISFoundation/osparc-simcore/pull/5931 environment: + <<: + - *tracing_open_telemetry_environs # WEBSERVER_DIRECTOR_V2 DIRECTOR_V2_HOST: ${DIRECTOR_V2_HOST} @@ -1091,7 +1104,6 @@ services: WEBSERVER_STUDIES_DISPATCHER: ${WB_GC_STUDIES_DISPATCHER} WEBSERVER_TAGS: ${WB_GC_TAGS} WEBSERVER_TRACING: ${WB_GC_TRACING} - <<: *tracing_open_telemetry_environs WEBSERVER_USERS: ${WB_GC_USERS} WEBSERVER_WALLETS: ${WB_GC_WALLETS} @@ -1104,8 +1116,14 @@ services: init: true hostname: "auth-{{.Node.Hostname}}-{{.Task.Slot}}" # the hostname is used in conjonction with other services and must be unique see https://github.com/ITISFoundation/osparc-simcore/pull/5931 environment: + <<: + - *webserver_diagnostics_environs + - *tracing_open_telemetry_environs + + APP_NAME: "simcore_service_wb_auth" WEBSERVER_APP_FACTORY_NAME: WEBSERVER_AUTHZ_APP_FACTORY WEBSERVER_LOGLEVEL: ${WB_AUTH_LOGLEVEL} + GUNICORN_CMD_ARGS: ${WEBSERVER_GUNICORN_CMD_ARGS} # WEBSERVER_DB @@ -1116,6 +1134,9 @@ services: POSTGRES_PORT: ${POSTGRES_PORT} POSTGRES_USER: ${POSTGRES_USER} + # WEBSERVER_DIAGNOSTICS + WEBSERVER_DIAGNOSTICS: ${WB_AUTH_DIAGNOSTICS} + # WEBSERVER_REST REST_SWAGGER_API_DOC_ENABLED: 0 @@ -1148,6 +1169,7 @@ services: WEBSERVER_LOGIN: "null" WEBSERVER_NOTIFICATIONS: 0 WEBSERVER_PAYMENTS: "null" + WEBSERVER_PROFILING: ${WB_AUTH_PROFILING} WEBSERVER_PRODUCTS: 1 WEBSERVER_PROJECTS: "null" WEBSERVER_PUBLICATIONS: 0 @@ -1162,7 +1184,6 @@ services: WEBSERVER_STUDIES_DISPATCHER: "null" WEBSERVER_TAGS: 0 WEBSERVER_TRACING: ${WB_AUTH_TRACING} - <<: *tracing_open_telemetry_environs WEBSERVER_USERS: "null" networks: - default diff --git a/services/web/server/src/simcore_service_webserver/application.py b/services/web/server/src/simcore_service_webserver/application.py index 6fc915ec07af..32e96663433b 100644 --- a/services/web/server/src/simcore_service_webserver/application.py +++ b/services/web/server/src/simcore_service_webserver/application.py @@ -194,12 +194,22 @@ def create_application() -> web.Application: def create_application_auth() -> web.Application: app = create_safe_application() - setup_settings(app) - setup_app_tracing(app) # WARNING: must be UPPERMOST middleware + settings = setup_settings(app) + assert settings.WEBSERVER_APP_FACTORY_NAME == "WEBSERVER_AUTHZ_APP_FACTORY" # nosec + + # Monitoring and diagnostics + setup_app_tracing( + # WARNING: must be UPPERMOST middleware + # NOTE: uses settings.APP_NAME + app + ) + setup_diagnostics(app) + setup_profiling_middleware(app) + + # Core modules setup_rest(app) setup_db(app) - setup_login_auth(app) # NOTE: *last* events @@ -207,7 +217,8 @@ def create_application_auth() -> web.Application: app.on_shutdown.append(_create_finished_banner()) _logger.debug( - "Routes in application-auth: \n %s", pformat(app.router.named_resources()) + "Routes in application-auth: \n %s", + lambda: pformat(app.router.named_resources()), ) return app diff --git a/services/web/server/src/simcore_service_webserver/application_settings.py b/services/web/server/src/simcore_service_webserver/application_settings.py index a858290461c7..919b3947f9b0 100644 --- a/services/web/server/src/simcore_service_webserver/application_settings.py +++ b/services/web/server/src/simcore_service_webserver/application_settings.py @@ -4,6 +4,7 @@ from aiohttp import web from common_library.basic_types import DEFAULT_FACTORY +from common_library.exclude import Unset from common_library.pydantic_fields_extension import is_nullable from models_library.basic_types import LogLevel, PortInt, VersionTag from models_library.utils.change_case import snake_to_camel @@ -587,12 +588,16 @@ def to_client_statics(self) -> dict[str, Any]: return {snake_to_camel(k): v for k, v in data.items()} +_unset = Unset.VALUE + + def setup_settings(app: web.Application) -> ApplicationSettings: + settings: ApplicationSettings = ApplicationSettings.create_from_envs() app[APP_SETTINGS_KEY] = settings _logger.debug( "Captured app settings:\n%s", - app[APP_SETTINGS_KEY].model_dump_json(indent=1), + lambda: settings.model_dump_json(indent=1), ) return settings diff --git a/services/web/server/src/simcore_service_webserver/diagnostics/_monitoring.py b/services/web/server/src/simcore_service_webserver/diagnostics/_monitoring.py index 10fba7e44748..c04767058c53 100644 --- a/services/web/server/src/simcore_service_webserver/diagnostics/_monitoring.py +++ b/services/web/server/src/simcore_service_webserver/diagnostics/_monitoring.py @@ -5,10 +5,11 @@ from aiohttp import web from servicelib.aiohttp import monitor_services +from servicelib.aiohttp.application_setup import ensure_single_setup from servicelib.aiohttp.monitoring import get_collector_registry from servicelib.aiohttp.monitoring import setup_monitoring as service_lib_setup -from .. import _meta +from ..application_settings import get_application_settings from ._healthcheck import HEALTH_LATENCY_PROBE, DelayWindowProbe, is_sensing_enabled _logger = logging.getLogger(__name__) @@ -46,16 +47,20 @@ async def exit_middleware_cb(request: web.Request, _response: web.StreamResponse request.app[HEALTH_LATENCY_PROBE].observe(resp_time_secs) +@ensure_single_setup(f"{__name__}.setup_monitoring", logger=_logger) def setup_monitoring(app: web.Application): + settings = get_application_settings(app) + prometheus_friendly_app_name = settings.APP_NAME.replace("-", "_") + service_lib_setup( app, - _meta.APP_NAME, + app_name=prometheus_friendly_app_name, enter_middleware_cb=enter_middleware_cb, exit_middleware_cb=exit_middleware_cb, ) monitor_services.add_instrumentation( - app, get_collector_registry(app), _meta.PROMETHEUS_FRIENDLY_APP_NAME + app, reg=get_collector_registry(app), app_name=prometheus_friendly_app_name ) # on-the fly stats diff --git a/services/web/server/src/simcore_service_webserver/diagnostics/plugin.py b/services/web/server/src/simcore_service_webserver/diagnostics/plugin.py index 8c843699bd51..5dbd41d8375b 100644 --- a/services/web/server/src/simcore_service_webserver/diagnostics/plugin.py +++ b/services/web/server/src/simcore_service_webserver/diagnostics/plugin.py @@ -33,9 +33,7 @@ async def _on_healthcheck_async_adapter(app: web.Application) -> None: settings_name="WEBSERVER_DIAGNOSTICS", logger=_logger, ) -def setup_diagnostics( - app: web.Application, -) -> None: +def setup_diagnostics(app: web.Application): setup_rest(app) settings: DiagnosticsSettings = get_plugin_settings(app) @@ -60,8 +58,12 @@ def setup_diagnostics( app[HEALTH_PLUGIN_START_TIME] = time.time() -def setup_profiling_middleware( - app: web.Application, -) -> None: - if get_application_settings(app).WEBSERVER_PROFILING: - app.middlewares.append(profiling_middleware) +@app_module_setup( + __name__, + ModuleCategory.ADDON, + settings_name="WEBSERVER_PROFILING", + logger=_logger, +) +def setup_profiling_middleware(app: web.Application): + assert get_application_settings(app).WEBSERVER_PROFILING # nosec + app.middlewares.append(profiling_middleware) diff --git a/services/web/server/src/simcore_service_webserver/tracing.py b/services/web/server/src/simcore_service_webserver/tracing.py index 0c18954dcb9f..83b0b3f101ba 100644 --- a/services/web/server/src/simcore_service_webserver/tracing.py +++ b/services/web/server/src/simcore_service_webserver/tracing.py @@ -5,7 +5,7 @@ from servicelib.aiohttp.tracing import get_tracing_lifespan from settings_library.tracing import TracingSettings -from ._meta import APP_NAME +from .application_settings import get_application_settings from .constants import APP_SETTINGS_KEY log = logging.getLogger(__name__) @@ -22,12 +22,24 @@ def get_plugin_settings(app: web.Application) -> TracingSettings: __name__, ModuleCategory.ADDON, settings_name="WEBSERVER_TRACING", logger=log ) def setup_app_tracing(app: web.Application): + """ + Sets up OpenTelemetry tracing for the application. + + NOTE: uses app[APP_SETTINGS_KEY].APP_NAME to set the service name advertised to the + tracing backend. This is used to identify the service in the tracing UI. + Note that this defaults in _meta.APP_NAME to "simcore-service-webserver" if not set otherwise + in setup_settings(app, app_name="...") in the application factory. + + """ + + app_settings = get_application_settings(app) tracing_settings: TracingSettings = get_plugin_settings(app) + app.cleanup_ctx.append( get_tracing_lifespan( app=app, tracing_settings=tracing_settings, - service_name=APP_NAME, + service_name=app_settings.APP_NAME, add_response_trace_id_header=True, ) ) diff --git a/services/web/server/tests/unit/isolated/test_diagnostics_healthcheck.py b/services/web/server/tests/unit/isolated/test_diagnostics_healthcheck.py index 0ca10ba20f20..8aa41b00d6a6 100644 --- a/services/web/server/tests/unit/isolated/test_diagnostics_healthcheck.py +++ b/services/web/server/tests/unit/isolated/test_diagnostics_healthcheck.py @@ -173,7 +173,7 @@ async def delay_response(request: web.Request): def test_diagnostics_setup(client: TestClient): assert client.app assert {m.__middleware_name__ for m in client.app.middlewares} == { - "servicelib.aiohttp.monitoring.monitor_simcore-service-webserver", + "servicelib.aiohttp.monitoring.monitor_simcore_service_webserver", "servicelib.aiohttp.rest_middlewares.envelope_v0", "servicelib.aiohttp.rest_middlewares.error_v0", "simcore_service_webserver.session.plugin.session", diff --git a/services/web/server/tests/unit/with_dbs/03/test_login_auth_app.py b/services/web/server/tests/unit/with_dbs/03/test_login_auth_app.py index e0cf82a3e8ed..8f80e463063c 100644 --- a/services/web/server/tests/unit/with_dbs/03/test_login_auth_app.py +++ b/services/web/server/tests/unit/with_dbs/03/test_login_auth_app.py @@ -20,7 +20,10 @@ from pytest_simcore.helpers.webserver_login import UserInfoDict from servicelib.aiohttp import status from simcore_service_webserver.application import create_application_auth -from simcore_service_webserver.application_settings import ApplicationSettings +from simcore_service_webserver.application_settings import ( + ApplicationSettings, + get_application_settings, +) from simcore_service_webserver.application_settings_utils import AppConfigDict from simcore_service_webserver.security import security_web @@ -39,17 +42,19 @@ def app_environment_for_wb_authz_service_dict( postgres_cfg = default_app_cfg["db"]["postgres"] + # Checks that docker-compose service environment is correct assert ( docker_compose_service_environment_dict["WEBSERVER_APP_FACTORY_NAME"] == "WEBSERVER_AUTHZ_APP_FACTORY" ) - # expected tracing in the docker-environ BUT we will disable it for tests assert "WEBSERVER_TRACING" in docker_compose_service_environment_dict assert ( "TRACING_OPENTELEMETRY_COLLECTOR_ENDPOINT" in docker_compose_service_environment_dict ) + assert "WEBSERVER_DIAGNOSTICS" in docker_compose_service_environment_dict + assert "WEBSERVER_PROFILING" in docker_compose_service_environment_dict return { **docker_compose_service_environment_dict, @@ -96,7 +101,7 @@ def app_environment_for_wb_authz_service( @pytest.fixture -async def auth_app( +async def wb_auth_app( app_environment_for_wb_authz_service: EnvVarsDict, ) -> web.Application: assert app_environment_for_wb_authz_service @@ -104,6 +109,12 @@ async def auth_app( # creates auth application instead app = create_application_auth() + settings = get_application_settings(app) + assert settings.WEBSERVER_APP_FACTORY_NAME == "WEBSERVER_AUTHZ_APP_FACTORY" + assert ( + settings.APP_NAME == "simcore_service_wb_auth" + ), "APP_NAME in docker-compose for wb-auth is not set correctly" + # checks endpoint exposed url = app.router["check_auth"].url_for() assert url.path == "/v0/auth:check" @@ -114,7 +125,7 @@ async def auth_app( @pytest_asyncio.fixture(loop_scope="function", scope="function") async def web_server( postgres_db: sa.engine.Engine, # sets up postgres database - auth_app: web.Application, + wb_auth_app: web.Application, webserver_test_server_port: int, # tools aiohttp_server: Callable, @@ -134,10 +145,10 @@ async def test_logout(request: web.Request) -> web.Response: await security_web.forget_identity(request, response) return response - auth_app.router.add_post("/v0/test/login", test_login) - auth_app.router.add_post("/v0/test/logout", test_logout) + wb_auth_app.router.add_post("/v0/test/login", test_login) + wb_auth_app.router.add_post("/v0/test/logout", test_logout) - return await aiohttp_server(auth_app, port=webserver_test_server_port) + return await aiohttp_server(wb_auth_app, port=webserver_test_server_port) # @pytest.mark.parametrize(