diff --git a/guillotina/db/storages/pg.py b/guillotina/db/storages/pg.py index 4dfd7b8f5..d7d1bdde6 100644 --- a/guillotina/db/storages/pg.py +++ b/guillotina/db/storages/pg.py @@ -89,6 +89,10 @@ class watch_lock(metrics.watch_lock): def __init__(self, lock: asyncio.Lock, operation: str): super().__init__(lock, PG_LOCK_ACQUIRE_TIME, labels={"type": operation}) + class watch_nonlock(metrics.watch_nonlock): + def __init__(self, operation: str): + super().__init__(PG_LOCK_ACQUIRE_TIME, labels={"type": operation}) + except ImportError: watch = metrics.dummy_watch # type: ignore @@ -967,7 +971,7 @@ async def store(self, oid, old_serial, writer, serialized, obj, txn): update = True conn = await txn.get_connection() - async with watch_lock(txn._lock, "store_object"): + async with watch_nonlock("store_object"): try: with watch("store_object"): result = await conn.fetch( @@ -1088,7 +1092,7 @@ async def start_transaction(self, txn, retries=0): if txn._db_txn is not None: return - async with watch_lock(txn._lock, "start_txn"): + async with watch_nonlock("start_txn"): txn._db_txn = await self._async_db_transaction_factory(txn) try: @@ -1142,7 +1146,7 @@ async def get_conflicts(self, txn): return await conn.fetch(sql, txn._tid) async def commit(self, transaction): - async with watch_lock(transaction._lock, "commit_txn"): + async with watch_nonlock("commit_txn"): if transaction._db_txn is not None: with watch("commit_txn"): await transaction._db_txn.commit() @@ -1151,7 +1155,7 @@ async def commit(self, transaction): return transaction._tid async def abort(self, transaction): - async with watch_lock(transaction._lock, "rollback_txn"): + async with watch_nonlock("rollback_txn"): if transaction._db_txn is not None: try: with watch("rollback_txn"): diff --git a/guillotina/metrics.py b/guillotina/metrics.py index baad16b23..8d5679747 100644 --- a/guillotina/metrics.py +++ b/guillotina/metrics.py @@ -101,3 +101,28 @@ async def __aexit__(self, exc_type, exc, tb): return self.lock.release() + + +class watch_nonlock: + def __init__( + self, + histogram: Optional[Histogram] = None, + labels: Optional[Dict[str, str]] = None, + ): + self.histogram = histogram + self.labels = labels or {} + + async def __aenter__(self) -> None: + if self.histogram is None: + return + + start = time.time() + finished = time.time() + if len(self.labels) > 0: + self.histogram.labels(**self.labels).observe(finished - start) + else: + self.histogram.observe(finished - start) + + async def __aexit__(self, exc_type, exc, tb): + if self.histogram is None: + return \ No newline at end of file