Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit e3debf9

Browse files
authored
Add logging on startup/shutdown (#8448)
This is so we can tell what is going on when things are taking a while to start up. The main change here is to ensure that transactions that are created during startup get correctly logged like normal transactions.
1 parent ec10bdd commit e3debf9

25 files changed

+152
-113
lines changed

changelog.d/8448.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add SQL logging on queries that happen during startup.

scripts/synapse_port_db

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ class Porter(object):
489489

490490
hs = MockHomeserver(self.hs_config)
491491

492-
with make_conn(db_config, engine) as db_conn:
492+
with make_conn(db_config, engine, "portdb") as db_conn:
493493
engine.check_database(
494494
db_conn, allow_outdated_version=allow_outdated_version
495495
)

synapse/app/_base.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,11 @@ def handle_sighup(*args, **kwargs):
272272
hs.get_datastore().db_pool.start_profiling()
273273
hs.get_pusherpool().start()
274274

275+
# Log when we start the shut down process.
276+
hs.get_reactor().addSystemEventTrigger(
277+
"before", "shutdown", logger.info, "Shutting down..."
278+
)
279+
275280
setup_sentry(hs)
276281
setup_sdnotify(hs)
277282

synapse/storage/database.py

Lines changed: 74 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
overload,
3333
)
3434

35+
import attr
3536
from prometheus_client import Histogram
3637
from typing_extensions import Literal
3738

@@ -90,13 +91,17 @@ def make_pool(
9091
return adbapi.ConnectionPool(
9192
db_config.config["name"],
9293
cp_reactor=reactor,
93-
cp_openfun=engine.on_new_connection,
94+
cp_openfun=lambda conn: engine.on_new_connection(
95+
LoggingDatabaseConnection(conn, engine, "on_new_connection")
96+
),
9497
**db_config.config.get("args", {})
9598
)
9699

97100

98101
def make_conn(
99-
db_config: DatabaseConnectionConfig, engine: BaseDatabaseEngine
102+
db_config: DatabaseConnectionConfig,
103+
engine: BaseDatabaseEngine,
104+
default_txn_name: str,
100105
) -> Connection:
101106
"""Make a new connection to the database and return it.
102107
@@ -109,11 +114,60 @@ def make_conn(
109114
for k, v in db_config.config.get("args", {}).items()
110115
if not k.startswith("cp_")
111116
}
112-
db_conn = engine.module.connect(**db_params)
117+
native_db_conn = engine.module.connect(**db_params)
118+
db_conn = LoggingDatabaseConnection(native_db_conn, engine, default_txn_name)
119+
113120
engine.on_new_connection(db_conn)
114121
return db_conn
115122

116123

124+
@attr.s(slots=True)
125+
class LoggingDatabaseConnection:
126+
"""A wrapper around a database connection that returns `LoggingTransaction`
127+
as its cursor class.
128+
129+
This is mainly used on startup to ensure that queries get logged correctly
130+
"""
131+
132+
conn = attr.ib(type=Connection)
133+
engine = attr.ib(type=BaseDatabaseEngine)
134+
default_txn_name = attr.ib(type=str)
135+
136+
def cursor(
137+
self, *, txn_name=None, after_callbacks=None, exception_callbacks=None
138+
) -> "LoggingTransaction":
139+
if not txn_name:
140+
txn_name = self.default_txn_name
141+
142+
return LoggingTransaction(
143+
self.conn.cursor(),
144+
name=txn_name,
145+
database_engine=self.engine,
146+
after_callbacks=after_callbacks,
147+
exception_callbacks=exception_callbacks,
148+
)
149+
150+
def close(self) -> None:
151+
self.conn.close()
152+
153+
def commit(self) -> None:
154+
self.conn.commit()
155+
156+
def rollback(self, *args, **kwargs) -> None:
157+
self.conn.rollback(*args, **kwargs)
158+
159+
def __enter__(self) -> "Connection":
160+
self.conn.__enter__()
161+
return self
162+
163+
def __exit__(self, exc_type, exc_value, traceback) -> bool:
164+
return self.conn.__exit__(exc_type, exc_value, traceback)
165+
166+
# Proxy through any unknown lookups to the DB conn class.
167+
def __getattr__(self, name):
168+
return getattr(self.conn, name)
169+
170+
117171
# The type of entry which goes on our after_callbacks and exception_callbacks lists.
118172
#
119173
# Python 3.5.2 doesn't support Callable with an ellipsis, so we wrap it in quotes so
@@ -247,6 +301,12 @@ def _do_execute(self, func, sql: str, *args: Any) -> None:
247301
def close(self) -> None:
248302
self.txn.close()
249303

304+
def __enter__(self) -> "LoggingTransaction":
305+
return self
306+
307+
def __exit__(self, exc_type, exc_value, traceback):
308+
self.close()
309+
250310

251311
class PerformanceCounters:
252312
def __init__(self):
@@ -395,7 +455,7 @@ def loop():
395455

396456
def new_transaction(
397457
self,
398-
conn: Connection,
458+
conn: LoggingDatabaseConnection,
399459
desc: str,
400460
after_callbacks: List[_CallbackListEntry],
401461
exception_callbacks: List[_CallbackListEntry],
@@ -418,12 +478,10 @@ def new_transaction(
418478
i = 0
419479
N = 5
420480
while True:
421-
cursor = LoggingTransaction(
422-
conn.cursor(),
423-
name,
424-
self.engine,
425-
after_callbacks,
426-
exception_callbacks,
481+
cursor = conn.cursor(
482+
txn_name=name,
483+
after_callbacks=after_callbacks,
484+
exception_callbacks=exception_callbacks,
427485
)
428486
try:
429487
r = func(cursor, *args, **kwargs)
@@ -584,7 +642,10 @@ def inner_func(conn, *args, **kwargs):
584642
logger.debug("Reconnecting closed database connection")
585643
conn.reconnect()
586644

587-
return func(conn, *args, **kwargs)
645+
db_conn = LoggingDatabaseConnection(
646+
conn, self.engine, "runWithConnection"
647+
)
648+
return func(db_conn, *args, **kwargs)
588649

589650
return await make_deferred_yieldable(
590651
self._db_pool.runWithConnection(inner_func, *args, **kwargs)
@@ -1621,7 +1682,7 @@ def simple_delete_many_txn(
16211682

16221683
def get_cache_dict(
16231684
self,
1624-
db_conn: Connection,
1685+
db_conn: LoggingDatabaseConnection,
16251686
table: str,
16261687
entity_column: str,
16271688
stream_column: str,
@@ -1642,9 +1703,7 @@ def get_cache_dict(
16421703
"limit": limit,
16431704
}
16441705

1645-
sql = self.engine.convert_param_style(sql)
1646-
1647-
txn = db_conn.cursor()
1706+
txn = db_conn.cursor(txn_name="get_cache_dict")
16481707
txn.execute(sql, (int(max_value),))
16491708

16501709
cache = {row[0]: int(row[1]) for row in txn}

synapse/storage/databases/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def __init__(self, main_store_class, hs):
4646
db_name = database_config.name
4747
engine = create_engine(database_config.config)
4848

49-
with make_conn(database_config, engine) as db_conn:
49+
with make_conn(database_config, engine, "startup") as db_conn:
5050
logger.info("[database config %r]: Checking database server", db_name)
5151
engine.check_database(db_conn)
5252

synapse/storage/databases/main/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,6 @@ def _get_active_presence(self, db_conn):
284284
" last_user_sync_ts, status_msg, currently_active FROM presence_stream"
285285
" WHERE state != ?"
286286
)
287-
sql = self.database_engine.convert_param_style(sql)
288287

289288
txn = db_conn.cursor()
290289
txn.execute(sql, (PresenceState.OFFLINE,))

synapse/storage/databases/main/event_push_actions.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import attr
2121

2222
from synapse.metrics.background_process_metrics import run_as_background_process
23-
from synapse.storage._base import LoggingTransaction, SQLBaseStore, db_to_json
23+
from synapse.storage._base import SQLBaseStore, db_to_json
2424
from synapse.storage.database import DatabasePool
2525
from synapse.util import json_encoder
2626
from synapse.util.caches.descriptors import cached
@@ -74,11 +74,7 @@ def __init__(self, database: DatabasePool, db_conn, hs):
7474
self.stream_ordering_month_ago = None
7575
self.stream_ordering_day_ago = None
7676

77-
cur = LoggingTransaction(
78-
db_conn.cursor(),
79-
name="_find_stream_orderings_for_times_txn",
80-
database_engine=self.database_engine,
81-
)
77+
cur = db_conn.cursor(txn_name="_find_stream_orderings_for_times_txn")
8278
self._find_stream_orderings_for_times_txn(cur)
8379
cur.close()
8480

synapse/storage/databases/main/monthly_active_users.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,6 @@ def __init__(self, database: DatabasePool, db_conn, hs):
214214
self._mau_stats_only = hs.config.mau_stats_only
215215

216216
# Do not add more reserved users than the total allowable number
217-
# cur = LoggingTransaction(
218217
self.db_pool.new_transaction(
219218
db_conn,
220219
"initialise_mau_threepids",

synapse/storage/databases/main/roommember.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,7 @@
2121
from synapse.events.snapshot import EventContext
2222
from synapse.metrics import LaterGauge
2323
from synapse.metrics.background_process_metrics import run_as_background_process
24-
from synapse.storage._base import (
25-
LoggingTransaction,
26-
SQLBaseStore,
27-
db_to_json,
28-
make_in_list_sql_clause,
29-
)
24+
from synapse.storage._base import SQLBaseStore, db_to_json, make_in_list_sql_clause
3025
from synapse.storage.database import DatabasePool
3126
from synapse.storage.databases.main.events_worker import EventsWorkerStore
3227
from synapse.storage.engines import Sqlite3Engine
@@ -60,10 +55,8 @@ def __init__(self, database: DatabasePool, db_conn, hs):
6055
# background update still running?
6156
self._current_state_events_membership_up_to_date = False
6257

63-
txn = LoggingTransaction(
64-
db_conn.cursor(),
65-
name="_check_safe_current_state_events_membership_updated",
66-
database_engine=self.database_engine,
58+
txn = db_conn.cursor(
59+
txn_name="_check_safe_current_state_events_membership_updated"
6760
)
6861
self._check_safe_current_state_events_membership_updated_txn(txn)
6962
txn.close()

synapse/storage/databases/main/schema/delta/20/pushers.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,15 @@ def run_create(cur, database_engine, *args, **kwargs):
6666
row[8] = bytes(row[8]).decode("utf-8")
6767
row[11] = bytes(row[11]).decode("utf-8")
6868
cur.execute(
69-
database_engine.convert_param_style(
70-
"""
71-
INSERT into pushers2 (
72-
id, user_name, access_token, profile_tag, kind,
73-
app_id, app_display_name, device_display_name,
74-
pushkey, ts, lang, data, last_token, last_success,
75-
failing_since
76-
) values (%s)"""
77-
% (",".join(["?" for _ in range(len(row))]))
78-
),
69+
"""
70+
INSERT into pushers2 (
71+
id, user_name, access_token, profile_tag, kind,
72+
app_id, app_display_name, device_display_name,
73+
pushkey, ts, lang, data, last_token, last_success,
74+
failing_since
75+
) values (%s)
76+
"""
77+
% (",".join(["?" for _ in range(len(row))])),
7978
row,
8079
)
8180
count += 1

synapse/storage/databases/main/schema/delta/25/fts.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ def run_create(cur, database_engine, *args, **kwargs):
7171
" VALUES (?, ?)"
7272
)
7373

74-
sql = database_engine.convert_param_style(sql)
75-
7674
cur.execute(sql, ("event_search", progress_json))
7775

7876

synapse/storage/databases/main/schema/delta/27/ts.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ def run_create(cur, database_engine, *args, **kwargs):
5050
" VALUES (?, ?)"
5151
)
5252

53-
sql = database_engine.convert_param_style(sql)
54-
5553
cur.execute(sql, ("event_origin_server_ts", progress_json))
5654

5755

synapse/storage/databases/main/schema/delta/30/as_users.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,7 @@ def run_upgrade(cur, database_engine, config, *args, **kwargs):
5959
user_chunks = (user_ids[i : i + 100] for i in range(0, len(user_ids), n))
6060
for chunk in user_chunks:
6161
cur.execute(
62-
database_engine.convert_param_style(
63-
"UPDATE users SET appservice_id = ? WHERE name IN (%s)"
64-
% (",".join("?" for _ in chunk),)
65-
),
62+
"UPDATE users SET appservice_id = ? WHERE name IN (%s)"
63+
% (",".join("?" for _ in chunk),),
6664
[as_id] + chunk,
6765
)

synapse/storage/databases/main/schema/delta/31/pushers.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,15 @@ def run_create(cur, database_engine, *args, **kwargs):
6565
row = list(row)
6666
row[12] = token_to_stream_ordering(row[12])
6767
cur.execute(
68-
database_engine.convert_param_style(
69-
"""
70-
INSERT into pushers2 (
71-
id, user_name, access_token, profile_tag, kind,
72-
app_id, app_display_name, device_display_name,
73-
pushkey, ts, lang, data, last_stream_ordering, last_success,
74-
failing_since
75-
) values (%s)"""
76-
% (",".join(["?" for _ in range(len(row))]))
77-
),
68+
"""
69+
INSERT into pushers2 (
70+
id, user_name, access_token, profile_tag, kind,
71+
app_id, app_display_name, device_display_name,
72+
pushkey, ts, lang, data, last_stream_ordering, last_success,
73+
failing_since
74+
) values (%s)
75+
"""
76+
% (",".join(["?" for _ in range(len(row))])),
7877
row,
7978
)
8079
count += 1

synapse/storage/databases/main/schema/delta/31/search_update.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@ def run_create(cur, database_engine, *args, **kwargs):
5555
" VALUES (?, ?)"
5656
)
5757

58-
sql = database_engine.convert_param_style(sql)
59-
6058
cur.execute(sql, ("event_search_order", progress_json))
6159

6260

synapse/storage/databases/main/schema/delta/33/event_fields.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ def run_create(cur, database_engine, *args, **kwargs):
5050
" VALUES (?, ?)"
5151
)
5252

53-
sql = database_engine.convert_param_style(sql)
54-
5553
cur.execute(sql, ("event_fields_sender_url", progress_json))
5654

5755

synapse/storage/databases/main/schema/delta/33/remote_media_ts.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,5 @@ def run_create(cur, database_engine, *args, **kwargs):
2323

2424
def run_upgrade(cur, database_engine, *args, **kwargs):
2525
cur.execute(
26-
database_engine.convert_param_style(
27-
"UPDATE remote_media_cache SET last_access_ts = ?"
28-
),
29-
(int(time.time() * 1000),),
26+
"UPDATE remote_media_cache SET last_access_ts = ?", (int(time.time() * 1000),),
3027
)

synapse/storage/databases/main/schema/delta/56/unique_user_filter_index.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import logging
2+
from io import StringIO
23

34
from synapse.storage.engines import PostgresEngine
5+
from synapse.storage.prepare_database import execute_statements_from_stream
46

57
logger = logging.getLogger(__name__)
68

@@ -46,7 +48,4 @@ def run_create(cur, database_engine, *args, **kwargs):
4648
select_clause,
4749
)
4850

49-
if isinstance(database_engine, PostgresEngine):
50-
cur.execute(sql)
51-
else:
52-
cur.executescript(sql)
51+
execute_statements_from_stream(cur, StringIO(sql))

synapse/storage/databases/main/schema/delta/57/local_current_membership.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ def run_upgrade(cur, database_engine, config, *args, **kwargs):
6868
INNER JOIN room_memberships AS r USING (event_id)
6969
WHERE type = 'm.room.member' AND state_key LIKE ?
7070
"""
71-
sql = database_engine.convert_param_style(sql)
7271
cur.execute(sql, ("%:" + config.server_name,))
7372

7473
cur.execute(

0 commit comments

Comments
 (0)