Compare commits
4 Commits
05029106f6
...
dd0568bf91
| Author | SHA1 | Date | |
|---|---|---|---|
| dd0568bf91 | |||
| 8f5778fd1a | |||
| 925f820bfd | |||
| 0eec2f2187 |
@@ -366,6 +366,53 @@ services:
|
|||||||
source: minio_data
|
source: minio_data
|
||||||
target: /data
|
target: /data
|
||||||
|
|
||||||
|
zipkin:
|
||||||
|
image: docker.io/openzipkin/zipkin:3
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-O", "-", "http://localhost:9411/health"]
|
||||||
|
interval: 1m30s
|
||||||
|
timeout: 5s
|
||||||
|
start_period: 5s
|
||||||
|
start_interval: 2s
|
||||||
|
retries: 5
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
target: 9411
|
||||||
|
published: 13247
|
||||||
|
host_ip: 127.0.0.1
|
||||||
|
protocol: tcp
|
||||||
|
app_protocol: http
|
||||||
|
- name: api
|
||||||
|
target: 9411
|
||||||
|
published: 13247
|
||||||
|
host_ip: 127.0.0.1
|
||||||
|
protocol: tcp
|
||||||
|
app_protocol: http
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
loadtest:
|
||||||
|
build:
|
||||||
|
context: ./services/loadtest
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
depends_on:
|
||||||
|
backend:
|
||||||
|
restart: false
|
||||||
|
condition: service_healthy
|
||||||
|
required: true
|
||||||
|
env_file:
|
||||||
|
- path: ./infrastructure/loadtest/.env.template
|
||||||
|
required: true
|
||||||
|
- path: ./infrastructure/loadtest/.env
|
||||||
|
required: false
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
target: 5001
|
||||||
|
published: 13248
|
||||||
|
host_ip: 127.0.0.1
|
||||||
|
protocol: tcp
|
||||||
|
app_protocol: http
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
redis_data:
|
redis_data:
|
||||||
postgres_data:
|
postgres_data:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
DJANGO_SECRET_KEY=secretees
|
DJANGO_SECRET_KEY=very_insecure_key
|
||||||
DJANGO_DEBUG=False
|
DJANGO_DEBUG=False
|
||||||
DJANGO_ALLOWED_HOSTS=*
|
DJANGO_ALLOWED_HOSTS=*
|
||||||
DJANGO_CSRF_TRUSTED_ORIGINS=http://localhost,http://127.0.0.1
|
DJANGO_CSRF_TRUSTED_ORIGINS=http://localhost,http://127.0.0.1
|
||||||
@@ -21,3 +21,7 @@ MINIO_ENDPOINT=minio:9000
|
|||||||
MINIO_CUSTOM_ENDPOINT_URL=http://127.0.0.1:13244
|
MINIO_CUSTOM_ENDPOINT_URL=http://127.0.0.1:13244
|
||||||
MINIO_ACCESS_KEY=admin
|
MINIO_ACCESS_KEY=admin
|
||||||
MINIO_SECRET_KEY=password
|
MINIO_SECRET_KEY=password
|
||||||
|
|
||||||
|
OTEL_METRICS_EXPORTER=none
|
||||||
|
OTEL_EXPORTER_ZIPKIN_ENDPOINT=http://zipkin:9411/api/v2/spans
|
||||||
|
OTEL_TRACES_EXPORTER=zipkin_json
|
||||||
|
|||||||
@@ -171,3 +171,6 @@ cython_debug/
|
|||||||
|
|
||||||
# Collected static files
|
# Collected static files
|
||||||
static
|
static
|
||||||
|
|
||||||
|
# Profile files
|
||||||
|
*.prof
|
||||||
|
|||||||
@@ -32,11 +32,12 @@ USER app
|
|||||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||||
PYTHONUNBUFFERED=1 \
|
PYTHONUNBUFFERED=1 \
|
||||||
PYTHONOPTIMIZE=2 \
|
PYTHONOPTIMIZE=2 \
|
||||||
PATH="/opt/venv/bin:$PATH"
|
PATH="/opt/venv/bin:$PATH" \
|
||||||
|
DJANGO_SETTINGS_MODULE=config.settings
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|
||||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --start-interval=2s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --start-interval=2s --retries=3 \
|
||||||
CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:8080/health?format=json || exit 1
|
CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:8080/health?format=json || exit 1
|
||||||
|
|
||||||
CMD [ "gunicorn", "config.wsgi", "--workers=8", "-b", "0.0.0.0:8080", "--access-logfile", "-", "--error-logfile", "-" ]
|
CMD [ "opentelemetry-instrument", "--service_name", "backend-django", "--traces_exporter", "zipkin_json", "gunicorn", "config.wsgi", "--workers=8", "-b", "0.0.0.0:8080", "--access-logfile", "-", "--error-logfile", "-" ]
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from uuid import UUID
|
|||||||
from django.http import Http404, HttpRequest
|
from django.http import Http404, HttpRequest
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from ninja import Router
|
from ninja import Router
|
||||||
|
from silk.profiling.profiler import silk_profile
|
||||||
|
|
||||||
from api.v1 import schemas as global_schemas
|
from api.v1 import schemas as global_schemas
|
||||||
from api.v1.ads import schemas
|
from api.v1.ads import schemas
|
||||||
@@ -21,6 +22,7 @@ router = Router(tags=["ads"])
|
|||||||
status.NOT_FOUND: global_schemas.NotFoundError,
|
status.NOT_FOUND: global_schemas.NotFoundError,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@silk_profile("Get Advertisment")
|
||||||
def get_advertisment(
|
def get_advertisment(
|
||||||
request: HttpRequest, client_id: UUID
|
request: HttpRequest, client_id: UUID
|
||||||
) -> tuple[status, Campaign]:
|
) -> tuple[status, Campaign]:
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import contextlib
|
|||||||
import logging
|
import logging
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import django_stubs_ext
|
import django_stubs_ext
|
||||||
import environ
|
import environ
|
||||||
@@ -12,6 +13,10 @@ from health_check.plugins import plugin_dir
|
|||||||
|
|
||||||
from integrations.yandexai.healthcheck import YandexAIHealthCheck
|
from integrations.yandexai.healthcheck import YandexAIHealthCheck
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
env = environ.Env()
|
env = environ.Env()
|
||||||
@@ -53,7 +58,7 @@ REDIS_URI = env("REDIS_URI", default="redis://localhost:6379")
|
|||||||
|
|
||||||
CACHES = {
|
CACHES = {
|
||||||
"default": {
|
"default": {
|
||||||
"BACKEND": "django.core.cache.backends.redis.RedisCache",
|
"BACKEND": "django_prometheus.cache.backends.redis.RedisCache",
|
||||||
"LOCATION": REDIS_URI,
|
"LOCATION": REDIS_URI,
|
||||||
"TIMEOUT": None,
|
"TIMEOUT": None,
|
||||||
"KEY_PREFIX": "backend",
|
"KEY_PREFIX": "backend",
|
||||||
@@ -80,6 +85,9 @@ CELERY_TASK_TRACK_STARTED = True
|
|||||||
# Database
|
# Database
|
||||||
|
|
||||||
DB_URI = env.db_url("DJANGO_DB_URI", default="sqlite:///db.sqlite3")
|
DB_URI = env.db_url("DJANGO_DB_URI", default="sqlite:///db.sqlite3")
|
||||||
|
DB_URI["ENGINE"] = DB_URI["ENGINE"].replace(
|
||||||
|
"django.db.backends", "django_prometheus.db.backends"
|
||||||
|
)
|
||||||
|
|
||||||
DATABASES = {"default": {**DB_URI, "CONN_MAX_AGE": 50}}
|
DATABASES = {"default": {**DB_URI, "CONN_MAX_AGE": 50}}
|
||||||
|
|
||||||
@@ -284,12 +292,15 @@ INTERNAL_IPS = env(
|
|||||||
)
|
)
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
"silk.middleware.SilkyMiddleware",
|
||||||
|
"django_prometheus.middleware.PrometheusBeforeMiddleware",
|
||||||
"django_guid.middleware.guid_middleware",
|
"django_guid.middleware.guid_middleware",
|
||||||
"corsheaders.middleware.CorsMiddleware",
|
"corsheaders.middleware.CorsMiddleware",
|
||||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||||
"django.middleware.csrf.CsrfViewMiddleware",
|
"django.middleware.csrf.CsrfViewMiddleware",
|
||||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||||
"django.contrib.messages.middleware.MessageMiddleware",
|
"django.contrib.messages.middleware.MessageMiddleware",
|
||||||
|
"django_prometheus.middleware.PrometheusAfterMiddleware",
|
||||||
]
|
]
|
||||||
|
|
||||||
SIGNING_BACKEND = "django.core.signing.TimestampSigner"
|
SIGNING_BACKEND = "django.core.signing.TimestampSigner"
|
||||||
@@ -442,8 +453,10 @@ INSTALLED_APPS = [
|
|||||||
"corsheaders",
|
"corsheaders",
|
||||||
"django_extensions",
|
"django_extensions",
|
||||||
"django_guid",
|
"django_guid",
|
||||||
|
"django_prometheus",
|
||||||
"ninja",
|
"ninja",
|
||||||
"minio_storage",
|
"minio_storage",
|
||||||
|
"silk",
|
||||||
# Internal apps
|
# Internal apps
|
||||||
"apps.core",
|
"apps.core",
|
||||||
"apps.advertiser",
|
"apps.advertiser",
|
||||||
@@ -516,6 +529,13 @@ SECRET_KEY = env("DJANGO_SECRET_KEY", default="very_insecure_key")
|
|||||||
SECRET_KEY_FALLBACKS: list[str] = []
|
SECRET_KEY_FALLBACKS: list[str] = []
|
||||||
|
|
||||||
|
|
||||||
|
# Auth
|
||||||
|
|
||||||
|
LOGIN_REDIRECT_URL = "/admin/"
|
||||||
|
|
||||||
|
LOGIN_URL = "/admin/"
|
||||||
|
|
||||||
|
|
||||||
# Sessions
|
# Sessions
|
||||||
|
|
||||||
SESSION_CACHE_ALIAS = "default"
|
SESSION_CACHE_ALIAS = "default"
|
||||||
@@ -594,3 +614,63 @@ DEBUG_TOOLBAR_CONFIG = {"SHOW_COLLAPSED": True, "UPDATE_ON_FETCH": True}
|
|||||||
if DEBUG and DEBUG_TOOLBAR_ENABLED:
|
if DEBUG and DEBUG_TOOLBAR_ENABLED:
|
||||||
INSTALLED_APPS.append("debug_toolbar")
|
INSTALLED_APPS.append("debug_toolbar")
|
||||||
MIDDLEWARE.append("debug_toolbar.middleware.DebugToolbarMiddleware")
|
MIDDLEWARE.append("debug_toolbar.middleware.DebugToolbarMiddleware")
|
||||||
|
|
||||||
|
|
||||||
|
# Prometheus
|
||||||
|
|
||||||
|
PROMETHEUS_LATENCY_BUCKETS = (
|
||||||
|
0.005,
|
||||||
|
0.01,
|
||||||
|
0.025,
|
||||||
|
0.05,
|
||||||
|
0.075,
|
||||||
|
0.1,
|
||||||
|
0.25,
|
||||||
|
0.5,
|
||||||
|
0.75,
|
||||||
|
1.0,
|
||||||
|
2.5,
|
||||||
|
5.0,
|
||||||
|
7.5,
|
||||||
|
10.0,
|
||||||
|
25.0,
|
||||||
|
50.0,
|
||||||
|
75.0,
|
||||||
|
float("inf"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# django-silk
|
||||||
|
|
||||||
|
SILKY_PYTHON_PROFILER = True
|
||||||
|
|
||||||
|
SILKY_PYTHON_PROFILER_BINARY = True
|
||||||
|
|
||||||
|
SILKY_PYTHON_PROFILER_RESULT_PATH = "./profiles"
|
||||||
|
|
||||||
|
SILKY_PYTHON_PROFILER_EXTENDED_FILE_NAME = True
|
||||||
|
|
||||||
|
SILKY_AUTHENTICATION = True
|
||||||
|
|
||||||
|
SILKY_AUTHORISATION = True
|
||||||
|
|
||||||
|
|
||||||
|
def is_allowed_to_use_profiling(user: "User") -> bool:
|
||||||
|
return user.is_staff
|
||||||
|
|
||||||
|
|
||||||
|
SILKY_PERMISSIONS = is_allowed_to_use_profiling
|
||||||
|
|
||||||
|
SILKY_MAX_RECORDED_REQUESTS = 10**3
|
||||||
|
|
||||||
|
SILKY_MAX_RECORDED_REQUESTS_CHECK_PERCENT = 10
|
||||||
|
|
||||||
|
SILKY_MAX_REQUEST_BODY_SIZE = 128
|
||||||
|
|
||||||
|
SILKY_INTERCEPT_PERCENT = 25
|
||||||
|
|
||||||
|
SILKY_META = True
|
||||||
|
|
||||||
|
SILKY_DYNAMIC_PROFILING = [
|
||||||
|
{"module": "api.v1.ads.views", "function": "get_advertisment"}
|
||||||
|
]
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ urlpatterns = [
|
|||||||
path("admin/", admin.site.urls),
|
path("admin/", admin.site.urls),
|
||||||
# API urls
|
# API urls
|
||||||
path("", include("api.urls")),
|
path("", include("api.urls")),
|
||||||
|
# Prometheus urls
|
||||||
|
path("", include("django_prometheus.urls")),
|
||||||
|
# Django-silk
|
||||||
|
path("silk/", include("silk.urls", namespace="silk")),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,29 @@ dependencies = [
|
|||||||
"django-health-check>=3.18.3,<4.0.0",
|
"django-health-check>=3.18.3,<4.0.0",
|
||||||
"django-minio-storage>=0.5.7,<0.6.0",
|
"django-minio-storage>=0.5.7,<0.6.0",
|
||||||
"django-ninja>=1.3.0,<2.0.0",
|
"django-ninja>=1.3.0,<2.0.0",
|
||||||
|
"django-prometheus>=2.4.1,<3.0.0",
|
||||||
|
"django-redis>=6.0.0,<7.0.0",
|
||||||
|
"django-silk[formatting]>=5.4.0,<6.0.0",
|
||||||
"django-stubs-ext>=5.1.3,<6.0.0",
|
"django-stubs-ext>=5.1.3,<6.0.0",
|
||||||
"gunicorn>=23.0.0,<24.0.0",
|
"gunicorn>=23.0.0,<24.0.0",
|
||||||
"httpx>=0.28.1,<0.29.0",
|
"httpx>=0.28.1,<0.29.0",
|
||||||
|
"opentelemetry-api>=1.35.0",
|
||||||
|
"opentelemetry-distro>=0.56b0",
|
||||||
|
"opentelemetry-exporter-otlp>=1.35.0",
|
||||||
|
"opentelemetry-exporter-zipkin-proto-http>=1.11.1",
|
||||||
|
"opentelemetry-instrumentation-asyncio>=0.56b0",
|
||||||
|
"opentelemetry-instrumentation-celery>=0.56b0",
|
||||||
|
"opentelemetry-instrumentation-dbapi>=0.56b0",
|
||||||
|
"opentelemetry-instrumentation-django>=0.56b0",
|
||||||
|
"opentelemetry-instrumentation-httpx>=0.56b0",
|
||||||
|
"opentelemetry-instrumentation-psycopg2>=0.56b0",
|
||||||
|
"opentelemetry-instrumentation-requests>=0.56b0",
|
||||||
|
"opentelemetry-instrumentation-sqlite3>=0.56b0",
|
||||||
|
"opentelemetry-instrumentation-threading>=0.56b0",
|
||||||
|
"opentelemetry-instrumentation-urllib>=0.56b0",
|
||||||
|
"opentelemetry-instrumentation-urllib3>=0.56b0",
|
||||||
|
"opentelemetry-instrumentation-wsgi>=0.56b0",
|
||||||
|
"opentelemetry-sdk>=1.35.0",
|
||||||
"pillow>=11.1.0,<12.0.0",
|
"pillow>=11.1.0,<12.0.0",
|
||||||
"psycopg2-binary>=2.9.10,<3.0.0",
|
"psycopg2-binary>=2.9.10,<3.0.0",
|
||||||
"pydantic>=2.10.5,<3.0.0",
|
"pydantic>=2.10.5,<3.0.0",
|
||||||
|
|||||||
@@ -11,3 +11,4 @@ if [ "$DJANGO_CREATE_SUPERUSER" = "True" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
python manage.py init_cache
|
python manage.py init_cache
|
||||||
|
python manage.py silk_clear_request_log
|
||||||
|
|||||||
Reference in New Issue
Block a user