Skip to content

Commit 3394456

Browse files
committed
[Operating] allow to identify DB connection "owner"
When having several different services running as part of a CRCon setup, and trying to identify what component/service is using a particular amount/number of DB connections is hard, apart from telling the total number of open connections. This commit aims to solve this issue by providing a proper identification for a DB connection. It is composed out of the name of the component that initiated the connection (e.g. gunicorn for the API backend, auto_settings for the autosettings component, etc) together with the server number. The name is inferred from the application start commands to keep the API for using the DB layer in the CRCon stable and to not bother callers to provide any identification. If a component name cannot be inferred, a generic "CRCon Generic" name is used. The connection name will show up as the "application_name" in the pg_stat_activity table of postgres, which can be quried with: select * from pg_stat_activity;
1 parent b3858fd commit 3394456

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

rcon/models.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import logging
22
import os
33
import re
4+
import sys
45
from collections import defaultdict
56
from contextlib import contextmanager
67
from datetime import datetime, timezone
7-
from typing import Any, Generator, List, Literal, Optional, Sequence, overload, TypedDict
8+
from typing import Any, Generator, List, Literal, Optional, Sequence, overload
89

910
import pydantic
1011
from sqlalchemy import TIMESTAMP, Enum, ForeignKey, String, create_engine, select, text, JSON
@@ -73,6 +74,30 @@
7374
_ENGINE = None
7475

7576

77+
def _connection_name() -> str:
78+
"""
79+
Identify what application component is using the SQLAlchemy session. This can be helpful when inspecting the connections
80+
in Postgres to identify the purpose of a connection. The connection name will be used as the application_name connection
81+
property and show up in the pg_stat_activity table:
82+
select * from pg_stat_activity;
83+
84+
:return: str
85+
"""
86+
args = sys.argv
87+
name = 'CRCon Generic'
88+
if "manage.py" not in args[0]:
89+
# stuff like daphne, gunicorn (backend) etc
90+
name = args[0]
91+
elif len(args) > 1 and args[1] != "":
92+
# Take whatever argument we passed to manage.py (for Supervisor services, such as log_loop, etc)
93+
name = args[1]
94+
95+
name = (os.getenv("SERVER_NUMBER") or "") + name
96+
# in the standard build (which we use in teh default docker setup) the name cannot exceed 63 chars (less than 64),
97+
# see https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-APPLICATION-NAME
98+
return name[:63]
99+
100+
76101
def get_engine():
77102
global _ENGINE
78103

@@ -84,7 +109,7 @@ def get_engine():
84109
logger.error(msg)
85110
raise ValueError(msg)
86111

87-
_ENGINE = create_engine(url, echo=False)
112+
_ENGINE = create_engine(url, echo=False, connect_args={"application_name":_connection_name()})
88113
return _ENGINE
89114

90115

rconweb/rconweb/settings.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,9 @@
253253
"HOST": db_info["HOST"],
254254
"PORT": db_info["PORT"],
255255
"NAME": db_info["NAME"],
256+
"OPTIONS": {
257+
"application_name": (os.getenv("SERVER_NUMBER") or "") + "Django",
258+
}
256259
}
257260
}
258261

0 commit comments

Comments
 (0)