Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions application.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
import os

from apig_wsgi import make_lambda_handler
from aws_xray_sdk.core import patch_all, xray_recorder
from aws_xray_sdk.ext.flask.middleware import XRayMiddleware
from dotenv import load_dotenv
from flask import Flask
from werkzeug.middleware.proxy_fix import ProxyFix

from app import create_app

load_dotenv()
# Patch all supported libraries for X-Ray
# Used to trace requests and responses through the stack
patch_all()

# OpenTelemetry auto-instrumentation will handle all tracing
# No manual patching or middleware needed

application = Flask("app")
application.wsgi_app = ProxyFix(application.wsgi_app) # type: ignore
xray_recorder.configure(service="Notify-Admin")
XRayMiddleware(application, xray_recorder)

create_app(application)

apig_wsgi_handler = make_lambda_handler(application, binary_support=True)
Expand Down
66 changes: 64 additions & 2 deletions gunicorn_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,23 @@
import time
import traceback

# Check if OpenTelemetry auto-instrumentation is active
# If so, use sync workers to avoid monkey patching conflicts
otel_env_vars = [
"OTEL_SERVICE_NAME",
"OTEL_RESOURCE_ATTRIBUTES",
"OTEL_EXPORTER_OTLP_ENDPOINT",
"OTEL_TRACES_EXPORTER",
"OTEL_METRICS_EXPORTER",
]

otel_detected = any(os.environ.get(var) for var in otel_env_vars)

# Also check if opentelemetry is in the Python path (auto-instrumentation)
pythonpath = os.environ.get("PYTHONPATH", "")
if "otel-auto-instrumentation" in pythonpath or "opentelemetry" in pythonpath:
otel_detected = True

import gunicorn # type: ignore
import newrelic.agent # See https://bit.ly/2xBVKBH

Expand All @@ -12,8 +29,15 @@
# Guincorn sets the server type on our app. We don't want to show it in the header in the response.
gunicorn.SERVER = "Undisclosed"

workers = 5
worker_class = "gevent"
# Use sync workers when OpenTelemetry is detected to avoid SSL monkey patching conflicts
worker_class = "sync" if otel_detected else "gevent"

# Adjust worker count based on worker class
# Sync workers need more processes to handle the same load as gevent
if otel_detected:
workers = 8 # More workers for sync mode
else:
workers = 5 # Standard worker count for gevent
bind = "0.0.0.0:{}".format(os.getenv("PORT"))
accesslog = "-"

Expand Down Expand Up @@ -48,12 +72,36 @@
graceful_timeout = 85
timeout = 90

# Additional configuration for sync workers when using OpenTelemetry
if otel_detected:
# Sync workers might need slightly longer timeout for instrumented requests
timeout = 95

Check notice

Code scanning / CodeQL

Unused global variable Note

The global variable 'timeout' is not used.

Copilot Autofix

AI 3 months ago

Copilot could not generate an autofix suggestion

Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.

graceful_timeout = 90

Check notice

Code scanning / CodeQL

Unused global variable Note

The global variable 'graceful_timeout' is not used.

Copilot Autofix

AI 3 months ago

Copilot could not generate an autofix suggestion

Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.


# Start timer for total running time
start_time = time.time()


def on_starting(server):
server.log.info("Starting Notifications Admin")
server.log.info(f"Using worker class: {worker_class}")

# Log telemetry configuration using the same detection logic
server.log.info(f"OpenTelemetry detected: {otel_detected}")

if otel_detected:
server.log.info("✅ OpenTelemetry auto-instrumentation active - using sync workers to avoid SSL conflicts")
# Log which env vars triggered detection
active_vars = [var for var in otel_env_vars if os.environ.get(var)]
if active_vars:
server.log.info(f"OTEL environment variables: {active_vars}")
pythonpath = os.environ.get("PYTHONPATH", "")
if "otel-auto-instrumentation" in pythonpath:
server.log.info("OTEL auto-instrumentation detected in PYTHONPATH")
else:
server.log.info("No OpenTelemetry detected - using gevent workers for better performance")

server.log.info("AWS X-Ray removed - OpenTelemetry handles all tracing")


def worker_abort(worker):
Expand All @@ -70,3 +118,17 @@

def worker_int(worker):
worker.log.info("worker: received SIGINT {}".format(worker.pid))


def post_worker_init(worker):
"""Initialize worker process - useful for OpenTelemetry sync workers"""
if otel_detected:
worker.log.info(f"Initializing sync worker {worker.pid} for OpenTelemetry instrumentation")
# Ensure clean SSL context in sync workers
import ssl

# Reset any cached SSL contexts to prevent recursion issues
if hasattr(ssl, "_create_default_https_context"):
ssl._create_default_https_context = ssl.create_default_context
else:
worker.log.info(f"Initializing gevent worker {worker.pid}")
3 changes: 0 additions & 3 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,4 @@ ignore_missing_imports = True
ignore_missing_imports = True

[mypy-newrelic.*]
ignore_missing_imports = True

[mypy-aws_xray_sdk.*]
ignore_missing_imports = True
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.0.1",
"description": "Admin front end for Notification",
"engines": {
"node": "16"
"node": ">=16"
},
"scripts": {
"test": "jest --config tests/javascripts/jest.config.js tests/javascripts",
Expand Down
96 changes: 1 addition & 95 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ build-backend = "poetry.core.masonry.api"
[tool.poetry.dependencies]
python = "~3.12.7"
apig-wsgi = "2.18.0"
aws-xray-sdk = "^2.14.0"

# PaaS
awscli-cwlogs = "^1.4.6"
Expand Down
Loading