refactor(monitoring): remove django-prometheus integration

Replaced `django-prometheus` with the default Django components, including model mixins, database backends, and cache configuration. This change simplifies monitoring setup by removing unnecessary dependencies, reducing overhead, and improving compatibility.

**Details:**
- Removed Prometheus metrics endpoints and middleware.
- Updated database, cache, and model configurations to remove `django-prometheus`.
- Adjusted WSGI settings to integrate OpenTelemetry instrumentation instead of Prometheus.
- Updated dependency files and migration schemas accordingly.
This commit is contained in:
Egor Pavlovich Gorbunov 2026-02-21 23:44:15 +03:00
parent 1756c3f2b2
commit 069d416585
12 changed files with 30 additions and 77 deletions

View file

@ -1,7 +1,6 @@
import uuid import uuid
import django_extensions.db.fields import django_extensions.db.fields
import django_prometheus.models
from django.db import migrations, models from django.db import migrations, models
@ -251,10 +250,7 @@ class Migration(migrations.Migration):
"verbose_name": "category tag", "verbose_name": "category tag",
"verbose_name_plural": "category tags", "verbose_name_plural": "category tags",
}, },
bases=( bases=(models.Model,),
django_prometheus.models.ExportModelOperationsMixin("category_tag"),
models.Model,
),
), ),
migrations.AddField( migrations.AddField(
model_name="category", model_name="category",

View file

@ -2,7 +2,6 @@ import uuid
import django.db.models.deletion import django.db.models.deletion
import django_extensions.db.fields import django_extensions.db.fields
import django_prometheus.models
from django.db import migrations, models from django.db import migrations, models
@ -80,10 +79,7 @@ class Migration(migrations.Migration):
"verbose_name": "order CRM link", "verbose_name": "order CRM link",
"verbose_name_plural": "orders CRM links", "verbose_name_plural": "orders CRM links",
}, },
bases=( bases=(models.Model,),
django_prometheus.models.ExportModelOperationsMixin("crm_provider"),
models.Model,
),
), ),
migrations.CreateModel( migrations.CreateModel(
name="OrderCrmLink", name="OrderCrmLink",
@ -148,9 +144,6 @@ class Migration(migrations.Migration):
"verbose_name": "order CRM link", "verbose_name": "order CRM link",
"verbose_name_plural": "orders CRM links", "verbose_name_plural": "orders CRM links",
}, },
bases=( bases=(models.Model,),
django_prometheus.models.ExportModelOperationsMixin("order_crm_link"),
models.Model,
),
), ),
] ]

View file

@ -46,7 +46,6 @@ from django.utils.functional import cached_property
from django.utils.http import urlsafe_base64_encode from django.utils.http import urlsafe_base64_encode
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django_extensions.db.fields import AutoSlugField from django_extensions.db.fields import AutoSlugField
from django_prometheus.models import ExportModelOperationsMixin
from mptt.fields import TreeForeignKey from mptt.fields import TreeForeignKey
from mptt.models import MPTTModel from mptt.models import MPTTModel
@ -76,7 +75,7 @@ from schon.utils.misc import create_object
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class AttributeGroup(ExportModelOperationsMixin("attribute_group"), NiceModel): class AttributeGroup(NiceModel):
__doc__ = _( __doc__ = _(
"Represents a group of attributes, which can be hierarchical." "Represents a group of attributes, which can be hierarchical."
" This class is used to manage and organize attribute groups." " This class is used to manage and organize attribute groups."
@ -109,7 +108,7 @@ class AttributeGroup(ExportModelOperationsMixin("attribute_group"), NiceModel):
verbose_name_plural = _("attribute groups") verbose_name_plural = _("attribute groups")
class Vendor(ExportModelOperationsMixin("vendor"), NiceModel): class Vendor(NiceModel):
__doc__ = _( __doc__ = _(
"Represents a vendor entity capable of storing information about external vendors and their interaction requirements." "Represents a vendor entity capable of storing information about external vendors and their interaction requirements."
" The Vendor class is used to define and manage information related to an external vendor." " The Vendor class is used to define and manage information related to an external vendor."
@ -193,7 +192,7 @@ class Vendor(ExportModelOperationsMixin("vendor"), NiceModel):
] ]
class ProductTag(ExportModelOperationsMixin("product_tag"), NiceModel): class ProductTag(NiceModel):
__doc__ = _( __doc__ = _(
"Represents a product tag used for classifying or identifying products." "Represents a product tag used for classifying or identifying products."
" The ProductTag class is designed to uniquely identify and classify products through a combination" " The ProductTag class is designed to uniquely identify and classify products through a combination"
@ -225,7 +224,7 @@ class ProductTag(ExportModelOperationsMixin("product_tag"), NiceModel):
verbose_name_plural = _("product tags") verbose_name_plural = _("product tags")
class CategoryTag(ExportModelOperationsMixin("category_tag"), NiceModel): class CategoryTag(NiceModel):
__doc__ = _( __doc__ = _(
"Represents a category tag used for products." "Represents a category tag used for products."
" This class models a category tag that can be used to associate and classify products." " This class models a category tag that can be used to associate and classify products."
@ -256,7 +255,7 @@ class CategoryTag(ExportModelOperationsMixin("category_tag"), NiceModel):
verbose_name_plural = _("category tags") verbose_name_plural = _("category tags")
class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel): class Category(NiceModel, MPTTModel):
__doc__ = _( __doc__ = _(
"Represents a category entity to organize and group related items in a hierarchical structure." "Represents a category entity to organize and group related items in a hierarchical structure."
" Categories may have hierarchical relationships with other categories, supporting parent-child relationships." " Categories may have hierarchical relationships with other categories, supporting parent-child relationships."
@ -457,7 +456,7 @@ class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel):
ordering = ["tree_id", "lft"] ordering = ["tree_id", "lft"]
class Brand(ExportModelOperationsMixin("brand"), NiceModel): class Brand(NiceModel):
__doc__ = _( __doc__ = _(
"Represents a Brand object in the system. " "Represents a Brand object in the system. "
"This class handles information and attributes related to a brand, including its name, logos, " "This class handles information and attributes related to a brand, including its name, logos, "
@ -527,7 +526,7 @@ class Brand(ExportModelOperationsMixin("brand"), NiceModel):
verbose_name_plural = _("brands") verbose_name_plural = _("brands")
class Stock(ExportModelOperationsMixin("stock"), NiceModel): class Stock(NiceModel):
__doc__ = _( __doc__ = _(
"Represents the stock of a product managed in the system." "Represents the stock of a product managed in the system."
" This class provides details about the relationship between vendors, products, and their stock information, " " This class provides details about the relationship between vendors, products, and their stock information, "
@ -595,7 +594,7 @@ class Stock(ExportModelOperationsMixin("stock"), NiceModel):
verbose_name_plural = _("stock entries") verbose_name_plural = _("stock entries")
class Product(ExportModelOperationsMixin("product"), NiceModel): class Product(NiceModel):
__doc__ = _( __doc__ = _(
"Represents a product with attributes such as category, brand, tags, digital status, name, description, part number, and slug." "Represents a product with attributes such as category, brand, tags, digital status, name, description, part number, and slug."
" Provides related utility properties to retrieve ratings, feedback counts, price, quantity, and total orders." " Provides related utility properties to retrieve ratings, feedback counts, price, quantity, and total orders."
@ -767,7 +766,7 @@ class Product(ExportModelOperationsMixin("product"), NiceModel):
return self.images.exists() return self.images.exists()
class Attribute(ExportModelOperationsMixin("attribute"), NiceModel): class Attribute(NiceModel):
__doc__ = _( __doc__ = _(
"Represents an attribute in the system." "Represents an attribute in the system."
" This class is used to define and manage attributes," " This class is used to define and manage attributes,"
@ -826,7 +825,7 @@ class Attribute(ExportModelOperationsMixin("attribute"), NiceModel):
verbose_name_plural = _("attributes") verbose_name_plural = _("attributes")
class AttributeValue(ExportModelOperationsMixin("attribute_value"), NiceModel): class AttributeValue(NiceModel):
__doc__ = _( __doc__ = _(
"Represents a specific value for an attribute that is linked to a product. " "Represents a specific value for an attribute that is linked to a product. "
"It links the 'attribute' to a unique 'value', allowing " "It links the 'attribute' to a unique 'value', allowing "
@ -866,7 +865,7 @@ class AttributeValue(ExportModelOperationsMixin("attribute_value"), NiceModel):
verbose_name_plural = _("attribute values") verbose_name_plural = _("attribute values")
class ProductImage(ExportModelOperationsMixin("product_image"), NiceModel): class ProductImage(NiceModel):
__doc__ = _( __doc__ = _(
"Represents a product image associated with a product in the system. " "Represents a product image associated with a product in the system. "
"This class is designed to manage images for products, including functionality " "This class is designed to manage images for products, including functionality "
@ -920,7 +919,7 @@ class ProductImage(ExportModelOperationsMixin("product_image"), NiceModel):
verbose_name_plural = _("product images") verbose_name_plural = _("product images")
class Promotion(ExportModelOperationsMixin("promotion"), NiceModel): class Promotion(NiceModel):
__doc__ = _( __doc__ = _(
"Represents a promotional campaign for products with a discount. " "Represents a promotional campaign for products with a discount. "
"This class is used to define and manage promotional campaigns that offer a " "This class is used to define and manage promotional campaigns that offer a "
@ -966,7 +965,7 @@ class Promotion(ExportModelOperationsMixin("promotion"), NiceModel):
return str(self.id) return str(self.id)
class Wishlist(ExportModelOperationsMixin("wishlist"), NiceModel): class Wishlist(NiceModel):
__doc__ = _( __doc__ = _(
"Represents a user's wishlist for storing and managing desired products. " "Represents a user's wishlist for storing and managing desired products. "
"The class provides functionality to manage a collection of products, " "The class provides functionality to manage a collection of products, "
@ -1037,7 +1036,7 @@ class Wishlist(ExportModelOperationsMixin("wishlist"), NiceModel):
return self return self
class Documentary(ExportModelOperationsMixin("attribute_group"), NiceModel): class Documentary(NiceModel):
__doc__ = _( __doc__ = _(
"Represents a documentary record tied to a product. " "Represents a documentary record tied to a product. "
"This class is used to store information about documentaries related to specific " "This class is used to store information about documentaries related to specific "
@ -1068,7 +1067,7 @@ class Documentary(ExportModelOperationsMixin("attribute_group"), NiceModel):
return self.document.name.split(".")[-1] or _("unresolved") return self.document.name.split(".")[-1] or _("unresolved")
class Address(ExportModelOperationsMixin("address"), NiceModel): class Address(NiceModel):
__doc__ = _( __doc__ = _(
"Represents an address entity that includes location details and associations with a user. " "Represents an address entity that includes location details and associations with a user. "
"Provides functionality for geographic and address data storage, as well " "Provides functionality for geographic and address data storage, as well "
@ -1133,7 +1132,7 @@ class Address(ExportModelOperationsMixin("address"), NiceModel):
return f"{base} for {self.user.email}" if self.user else base return f"{base} for {self.user.email}" if self.user else base
class PromoCode(ExportModelOperationsMixin("promocode"), NiceModel): class PromoCode(NiceModel):
__doc__ = _( __doc__ = _(
"Represents a promotional code that can be used for discounts, managing its validity, " "Represents a promotional code that can be used for discounts, managing its validity, "
"type of discount, and application. " "type of discount, and application. "
@ -1264,7 +1263,7 @@ class PromoCode(ExportModelOperationsMixin("promocode"), NiceModel):
return promo_amount return promo_amount
class Order(ExportModelOperationsMixin("order"), NiceModel): class Order(NiceModel):
__doc__ = _( __doc__ = _(
"Represents an order placed by a user." "Represents an order placed by a user."
" This class models an order within the application," " This class models an order within the application,"
@ -1834,7 +1833,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel):
return None return None
class Feedback(ExportModelOperationsMixin("feedback"), NiceModel): class Feedback(NiceModel):
__doc__ = _( __doc__ = _(
"Manages user feedback for products. " "Manages user feedback for products. "
"This class is designed to capture and store user feedback for specific products " "This class is designed to capture and store user feedback for specific products "
@ -1883,7 +1882,7 @@ class Feedback(ExportModelOperationsMixin("feedback"), NiceModel):
verbose_name_plural = _("feedbacks") verbose_name_plural = _("feedbacks")
class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel): class OrderProduct(NiceModel):
__doc__ = _( __doc__ = _(
"Represents products associated with orders and their attributes. " "Represents products associated with orders and their attributes. "
"The OrderProduct model maintains information about a product that is part of an order, " "The OrderProduct model maintains information about a product that is part of an order, "
@ -2046,9 +2045,7 @@ class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel):
return None return None
class CustomerRelationshipManagementProvider( class CustomerRelationshipManagementProvider(NiceModel):
ExportModelOperationsMixin("crm_provider"), NiceModel
):
name = CharField(max_length=128, unique=True, verbose_name=_("name")) name = CharField(max_length=128, unique=True, verbose_name=_("name"))
integration_url = URLField( integration_url = URLField(
blank=True, null=True, help_text=_("URL of the integration") blank=True, null=True, help_text=_("URL of the integration")
@ -2091,7 +2088,7 @@ class CustomerRelationshipManagementProvider(
verbose_name_plural = _("CRMs") verbose_name_plural = _("CRMs")
class OrderCrmLink(ExportModelOperationsMixin("order_crm_link"), NiceModel): class OrderCrmLink(NiceModel):
order = ForeignKey(to=Order, on_delete=PROTECT, related_name="crm_links") order = ForeignKey(to=Order, on_delete=PROTECT, related_name="crm_links")
crm = ForeignKey( crm = ForeignKey(
to=CustomerRelationshipManagementProvider, to=CustomerRelationshipManagementProvider,
@ -2108,7 +2105,7 @@ class OrderCrmLink(ExportModelOperationsMixin("order_crm_link"), NiceModel):
verbose_name_plural = _("orders CRM links") verbose_name_plural = _("orders CRM links")
class DigitalAssetDownload(ExportModelOperationsMixin("attribute_group"), NiceModel): class DigitalAssetDownload(NiceModel):
__doc__ = _( __doc__ = _(
"Represents the downloading functionality for digital assets associated with orders. " "Represents the downloading functionality for digital assets associated with orders. "
"The DigitalAssetDownload class provides the ability to manage and access " "The DigitalAssetDownload class provides the ability to manage and access "

View file

@ -3,16 +3,6 @@ global:
evaluation_interval: 15s evaluation_interval: 15s
scrape_configs: scrape_configs:
- job_name: 'app'
metrics_path: /prometheus/metrics
scheme: http
static_configs:
- targets: [ 'app:8000' ]
- job_name: 'worker'
static_configs:
- targets: [ 'worker:8888' ]
- job_name: 'database' - job_name: 'database'
static_configs: static_configs:
- targets: [ 'database_exporter:9187' ] - targets: [ 'database_exporter:9187' ]

View file

@ -29,7 +29,6 @@ dependencies = [
"django-md-field==0.1.0", "django-md-field==0.1.0",
"django-modeltranslation==0.19.19", "django-modeltranslation==0.19.19",
"django-mptt==0.18.0", "django-mptt==0.18.0",
"django-prometheus==2.4.1",
"django-redis==6.0.0", "django-redis==6.0.0",
"django-ratelimit==4.1.0", "django-ratelimit==4.1.0",
"django-storages==1.14.6", "django-storages==1.14.6",

View file

@ -108,7 +108,6 @@ UNSAFE_CACHE_KEYS: list[str] = []
SITE_ID: int = 1 SITE_ID: int = 1
INSTALLED_APPS: list[str] = [ INSTALLED_APPS: list[str] = [
"django_prometheus",
"unfold", "unfold",
"unfold.contrib.filters", "unfold.contrib.filters",
"unfold.contrib.forms", "unfold.contrib.forms",
@ -164,7 +163,6 @@ if DEBUG:
MIDDLEWARE: list[str] = [ MIDDLEWARE: list[str] = [
"schon.middleware.BlockInvalidHostMiddleware", "schon.middleware.BlockInvalidHostMiddleware",
"schon.middleware.RateLimitMiddleware", "schon.middleware.RateLimitMiddleware",
"django_prometheus.middleware.PrometheusBeforeMiddleware",
"django.middleware.security.SecurityMiddleware", "django.middleware.security.SecurityMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware", "whitenoise.middleware.WhiteNoiseMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware", "django.contrib.sessions.middleware.SessionMiddleware",
@ -177,7 +175,6 @@ MIDDLEWARE: list[str] = [
"django.middleware.clickjacking.XFrameOptionsMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware",
"schon.middleware.CustomLocaleMiddleware", "schon.middleware.CustomLocaleMiddleware",
"schon.middleware.CamelCaseMiddleWare", "schon.middleware.CamelCaseMiddleWare",
"django_prometheus.middleware.PrometheusAfterMiddleware",
] ]
if DEBUG: if DEBUG:

View file

@ -5,7 +5,7 @@ from schon.settings.base import REDIS_PASSWORD
CACHES = { CACHES = {
"default": { "default": {
"BACKEND": "django_prometheus.cache.backends.redis.RedisCache", "BACKEND": "django_redis.cache.RedisCache",
"LOCATION": getenv( "LOCATION": getenv(
"CELERY_BROKER_URL", f"redis://:{REDIS_PASSWORD}@redis:6379/0" "CELERY_BROKER_URL", f"redis://:{REDIS_PASSWORD}@redis:6379/0"
), ),

View file

@ -2,7 +2,7 @@ from os import getenv
DATABASES = { DATABASES = {
"default": { "default": {
"ENGINE": "django_prometheus.db.backends.postgis", "ENGINE": "django.contrib.gis.db.backends.postgis",
"NAME": getenv("POSTGRES_DB"), "NAME": getenv("POSTGRES_DB"),
"USER": getenv("POSTGRES_USER"), "USER": getenv("POSTGRES_USER"),
"PASSWORD": getenv("POSTGRES_PASSWORD"), "PASSWORD": getenv("POSTGRES_PASSWORD"),

View file

@ -88,7 +88,6 @@ The API supports multiple response formats:
## Health & Monitoring ## Health & Monitoring
- Health checks: `/health/` - Health checks: `/health/`
- Prometheus metrics: `/prometheus/metrics/`
## Version ## Version
Current API version: {version} Current API version: {version}

View file

@ -46,12 +46,6 @@ urlpatterns = [
), ),
name="health_check", name="health_check",
), ),
path(
r"prometheus/",
include(
"django_prometheus.urls",
),
),
path( path(
r"i18n/setlang/", r"i18n/setlang/",
set_language, set_language,

View file

@ -10,7 +10,10 @@ https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
import os import os
from django.core.wsgi import get_wsgi_application from django.core.wsgi import get_wsgi_application
from opentelemetry.instrumentation.django import DjangoInstrumentor
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "schon.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "schon.settings")
DjangoInstrumentor().instrument()
application = get_wsgi_application() application = get_wsgi_application()

15
uv.lock
View file

@ -980,19 +980,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/51/9e/78aad58a90f2e4d0c898eeadd2f2b720bcae29b43676dd37c2b627c4c6c6/django_mptt-0.18.0-py3-none-any.whl", hash = "sha256:bfa3f01627e3966a1df901aeca74570a3e933e66809ebf58d9df673e63627afb", size = 120157, upload-time = "2025-08-26T09:27:02.168Z" }, { url = "https://files.pythonhosted.org/packages/51/9e/78aad58a90f2e4d0c898eeadd2f2b720bcae29b43676dd37c2b627c4c6c6/django_mptt-0.18.0-py3-none-any.whl", hash = "sha256:bfa3f01627e3966a1df901aeca74570a3e933e66809ebf58d9df673e63627afb", size = 120157, upload-time = "2025-08-26T09:27:02.168Z" },
] ]
[[package]]
name = "django-prometheus"
version = "2.4.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "django" },
{ name = "prometheus-client" },
]
sdist = { url = "https://files.pythonhosted.org/packages/98/f4/cb39ddd2a41e07a274c4e162c076e906ae232d63b66bbabdea0300878877/django_prometheus-2.4.1.tar.gz", hash = "sha256:073628243d2a6de6a8a8c20e5b512872dfb85d66e1b60b28bcf1eca0155dad95", size = 24464, upload-time = "2025-06-25T15:45:37.149Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/01/50/9c5e022fa92574e5d20606687f15a2aa255e10512a17d11a8216fa117f72/django_prometheus-2.4.1-py2.py3-none-any.whl", hash = "sha256:7fe5af7f7c9ad9cd8a429fe0f3f1bf651f0e244f77162147869eab7ec09cc5e7", size = 29541, upload-time = "2025-06-25T15:45:35.433Z" },
]
[[package]] [[package]]
name = "django-ratelimit" name = "django-ratelimit"
version = "4.1.0" version = "4.1.0"
@ -3360,7 +3347,6 @@ dependencies = [
{ name = "django-model-utils" }, { name = "django-model-utils" },
{ name = "django-modeltranslation" }, { name = "django-modeltranslation" },
{ name = "django-mptt" }, { name = "django-mptt" },
{ name = "django-prometheus" },
{ name = "django-ratelimit" }, { name = "django-ratelimit" },
{ name = "django-redis" }, { name = "django-redis" },
{ name = "django-storages" }, { name = "django-storages" },
@ -3461,7 +3447,6 @@ requires-dist = [
{ name = "django-model-utils", specifier = "==5.0.0" }, { name = "django-model-utils", specifier = "==5.0.0" },
{ name = "django-modeltranslation", specifier = "==0.19.19" }, { name = "django-modeltranslation", specifier = "==0.19.19" },
{ name = "django-mptt", specifier = "==0.18.0" }, { name = "django-mptt", specifier = "==0.18.0" },
{ name = "django-prometheus", specifier = "==2.4.1" },
{ name = "django-ratelimit", specifier = "==4.1.0" }, { name = "django-ratelimit", specifier = "==4.1.0" },
{ name = "django-redis", specifier = "==6.0.0" }, { name = "django-redis", specifier = "==6.0.0" },
{ name = "django-storages", specifier = "==1.14.6" }, { name = "django-storages", specifier = "==1.14.6" },