Skip to content

Commit e8a49b7

Browse files
chore: Better timing and requestId detail for slower store db queries (#2994)
* Better timing and requestId detail for store db queries slower than two seconds * Adapt tests and client to allow sending custom store requestId
1 parent fd84363 commit e8a49b7

File tree

20 files changed

+111
-27
lines changed

20 files changed

+111
-27
lines changed

tests/waku_store_legacy/test_client.nim

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ suite "Store Client":
4444
pubsubTopic: some(DefaultPubsubTopic),
4545
contentTopics: @[DefaultContentTopic],
4646
direction: PagingDirection.FORWARD,
47+
requestId: "customRequestId",
4748
)
4849

4950
serverSwitch = newTestSwitch()
@@ -93,33 +94,39 @@ suite "Store Client":
9394
pubsubTopic: some(DefaultPubsubTopic),
9495
contentTopics: @[],
9596
direction: PagingDirection.FORWARD,
97+
requestId: "reqId1",
9698
)
9799
invalidQuery2 = HistoryQuery(
98100
pubsubTopic: PubsubTopic.none(),
99101
contentTopics: @[DefaultContentTopic],
100102
direction: PagingDirection.FORWARD,
103+
requestId: "reqId2",
101104
)
102105
invalidQuery3 = HistoryQuery(
103106
pubsubTopic: some(DefaultPubsubTopic),
104107
contentTopics: @[DefaultContentTopic],
105108
pageSize: 0,
109+
requestId: "reqId3",
106110
)
107111
invalidQuery4 = HistoryQuery(
108112
pubsubTopic: some(DefaultPubsubTopic),
109113
contentTopics: @[DefaultContentTopic],
110114
pageSize: 0,
115+
requestId: "reqId4",
111116
)
112117
invalidQuery5 = HistoryQuery(
113118
pubsubTopic: some(DefaultPubsubTopic),
114119
contentTopics: @[DefaultContentTopic],
115120
startTime: some(0.Timestamp),
116121
endTime: some(0.Timestamp),
122+
requestId: "reqId5",
117123
)
118124
invalidQuery6 = HistoryQuery(
119125
pubsubTopic: some(DefaultPubsubTopic),
120126
contentTopics: @[DefaultContentTopic],
121127
startTime: some(0.Timestamp),
122128
endTime: some(-1.Timestamp),
129+
requestId: "reqId6",
123130
)
124131

125132
# When the query is sent to the server

tests/waku_store_legacy/test_waku_store.nim

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ suite "Waku Store - query handler legacy":
4444
client = newTestWakuStoreClient(clientSwitch)
4545

4646
let req = HistoryQuery(
47-
contentTopics: @[DefaultContentTopic], direction: PagingDirection.FORWARD
47+
contentTopics: @[DefaultContentTopic],
48+
direction: PagingDirection.FORWARD,
49+
requestId: "reqId",
4850
)
4951

5052
## When
@@ -96,7 +98,9 @@ suite "Waku Store - query handler legacy":
9698
client = newTestWakuStoreClient(clientSwitch)
9799

98100
let req = HistoryQuery(
99-
contentTopics: @[DefaultContentTopic], direction: PagingDirection.FORWARD
101+
contentTopics: @[DefaultContentTopic],
102+
direction: PagingDirection.FORWARD,
103+
requestId: "reqId",
100104
)
101105

102106
info "check point" # log added to track flaky test

waku/common/databases/db_postgres/pgasyncpool.nim

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
# Inspired by: https://github.com/treeform/pg/
33
{.push raises: [].}
44

5-
import std/[sequtils, nre, strformat, sets], results, chronos
6-
import ./dbconn, ../common
5+
import std/[sequtils, nre, strformat, sets], results, chronos, chronicles
6+
import ./dbconn, ../common, ../../../waku_core/time
77

88
type PgAsyncPoolState {.pure.} = enum
99
Closed
@@ -149,18 +149,26 @@ proc releaseConn(pool: PgAsyncPool, conn: DbConn) =
149149
if pool.conns[i].dbConn == conn:
150150
pool.conns[i].busy = false
151151

152+
const SlowQueryThresholdInNanoSeconds = 2_000_000_000
153+
152154
proc pgQuery*(
153155
pool: PgAsyncPool,
154156
query: string,
155157
args: seq[string] = newSeq[string](0),
156158
rowCallback: DataProc = nil,
159+
requestId: string = "",
157160
): Future[DatabaseResult[void]] {.async.} =
158161
let connIndex = (await pool.getConnIndex()).valueOr:
159162
return err("connRes.isErr in query: " & $error)
160163

164+
let queryStartTime = getNowInNanosecondTime()
161165
let conn = pool.conns[connIndex].dbConn
162166
defer:
163167
pool.releaseConn(conn)
168+
let queryDuration = getNowInNanosecondTime() - queryStartTime
169+
if queryDuration > SlowQueryThresholdInNanoSeconds:
170+
debug "pgQuery slow query",
171+
query_duration_secs = (queryDuration / 1_000_000_000), query, requestId
164172

165173
(await conn.dbConnQuery(sql(query), args, rowCallback)).isOkOr:
166174
return err("error in asyncpool query: " & $error)
@@ -175,6 +183,7 @@ proc runStmt*(
175183
paramLengths: seq[int32],
176184
paramFormats: seq[int32],
177185
rowCallback: DataProc = nil,
186+
requestId: string = "",
178187
): Future[DatabaseResult[void]] {.async.} =
179188
## Runs a stored statement, for performance purposes.
180189
## The stored statements are connection specific and is a technique of caching a very common
@@ -187,8 +196,16 @@ proc runStmt*(
187196
return err("Error in runStmt: " & $error)
188197

189198
let conn = pool.conns[connIndex].dbConn
199+
let queryStartTime = getNowInNanosecondTime()
200+
190201
defer:
191202
pool.releaseConn(conn)
203+
let queryDuration = getNowInNanosecondTime() - queryStartTime
204+
if queryDuration > SlowQueryThresholdInNanoSeconds:
205+
debug "runStmt slow query",
206+
query_duration = queryDuration / 1_000_000_000,
207+
query = stmtDefinition,
208+
requestId
192209

193210
if not pool.conns[connIndex].preparedStmts.contains(stmtName):
194211
# The connection doesn't have that statement yet. Let's create it.

waku/node/waku_node.nim

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,7 @@ proc toArchiveQuery(
769769
endTime: request.endTime,
770770
pageSize: request.pageSize.uint,
771771
direction: request.direction,
772+
requestId: request.requestId,
772773
)
773774

774775
# TODO: Review this mapping logic. Maybe, move it to the appplication code
@@ -910,6 +911,7 @@ proc toArchiveQuery(request: StoreQueryRequest): waku_archive.ArchiveQuery =
910911
query.hashes = request.messageHashes
911912
query.cursor = request.paginationCursor
912913
query.direction = request.paginationForward
914+
query.requestId = request.requestId
913915

914916
if request.paginationLimit.isSome():
915917
query.pageSize = uint(request.paginationLimit.get())

waku/waku_archive/archive.nim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ proc findMessages*(
145145
hashes = query.hashes,
146146
maxPageSize = maxPageSize + 1,
147147
ascendingOrder = isAscendingOrder,
148+
requestId = query.requestId,
148149
)
149150
).valueOr:
150151
return err(ArchiveError(kind: ArchiveErrorKind.DRIVER_ERROR, cause: error))

waku/waku_archive/common.nim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type
1818
hashes*: seq[WakuMessageHash]
1919
pageSize*: uint
2020
direction*: PagingDirection
21+
requestId*: string
2122

2223
ArchiveResponse* = object
2324
hashes*: seq[WakuMessageHash]

waku/waku_archive/driver.nim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ method getMessages*(
3737
hashes = newSeq[WakuMessageHash](0),
3838
maxPageSize = DefaultPageSize,
3939
ascendingOrder = true,
40+
requestId = "",
4041
): Future[ArchiveDriverResult[seq[ArchiveRow]]] {.base, async.} =
4142
discard
4243

waku/waku_archive/driver/postgres_driver/postgres_driver.nim

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ proc getMessagesArbitraryQuery(
425425
hexHashes: seq[string] = @[],
426426
maxPageSize = DefaultPageSize,
427427
ascendingOrder = true,
428+
requestId: string,
428429
): Future[ArchiveDriverResult[seq[ArchiveRow]]] {.async.} =
429430
## This proc allows to handle atypical queries. We don't use prepared statements for those.
430431

@@ -489,7 +490,7 @@ proc getMessagesArbitraryQuery(
489490
proc rowCallback(pqResult: ptr PGresult) =
490491
rowCallbackImpl(pqResult, rows)
491492

492-
(await s.readConnPool.pgQuery(query, args, rowCallback)).isOkOr:
493+
(await s.readConnPool.pgQuery(query, args, rowCallback, requestId)).isOkOr:
493494
return err("failed to run query: " & $error)
494495

495496
return ok(rows)
@@ -504,6 +505,7 @@ proc getMessageHashesArbitraryQuery(
504505
hexHashes: seq[string] = @[],
505506
maxPageSize = DefaultPageSize,
506507
ascendingOrder = true,
508+
requestId: string,
507509
): Future[ArchiveDriverResult[seq[(WakuMessageHash, PubsubTopic, WakuMessage)]]] {.
508510
async
509511
.} =
@@ -571,7 +573,7 @@ proc getMessageHashesArbitraryQuery(
571573
proc rowCallback(pqResult: ptr PGresult) =
572574
hashCallbackImpl(pqResult, rows)
573575

574-
(await s.readConnPool.pgQuery(query, args, rowCallback)).isOkOr:
576+
(await s.readConnPool.pgQuery(query, args, rowCallback, requestId)).isOkOr:
575577
return err("failed to run query: " & $error)
576578

577579
return ok(rows)
@@ -586,6 +588,7 @@ proc getMessagesPreparedStmt(
586588
hashes: string,
587589
maxPageSize = DefaultPageSize,
588590
ascOrder = true,
591+
requestId: string,
589592
): Future[ArchiveDriverResult[seq[ArchiveRow]]] {.async.} =
590593
## This proc aims to run the most typical queries in a more performant way,
591594
## i.e. by means of prepared statements.
@@ -619,6 +622,7 @@ proc getMessagesPreparedStmt(
619622
],
620623
@[int32(0), int32(0), int32(0), int32(0), int32(0)],
621624
rowCallback,
625+
requestId,
622626
)
623627
).isOkOr:
624628
return err(stmtName & ": " & $error)
@@ -659,6 +663,7 @@ proc getMessagesPreparedStmt(
659663
],
660664
@[int32(0), int32(0), int32(0), int32(0), int32(0), int32(0), int32(0), int32(0)],
661665
rowCallback,
666+
requestId,
662667
)
663668
).isOkOr:
664669
return err(stmtName & ": " & $error)
@@ -675,6 +680,7 @@ proc getMessageHashesPreparedStmt(
675680
hashes: string,
676681
maxPageSize = DefaultPageSize,
677682
ascOrder = true,
683+
requestId: string,
678684
): Future[ArchiveDriverResult[seq[ArchiveRow]]] {.async.} =
679685
## This proc aims to run the most typical queries in a more performant way,
680686
## i.e. by means of prepared statements.
@@ -710,6 +716,7 @@ proc getMessageHashesPreparedStmt(
710716
],
711717
@[int32(0), int32(0), int32(0), int32(0), int32(0), int32(0)],
712718
rowCallback,
719+
requestId,
713720
)
714721
).isOkOr:
715722
return err(stmtName & ": " & $error)
@@ -753,14 +760,15 @@ proc getMessageHashesPreparedStmt(
753760
],
754761
@[int32(0), int32(0), int32(0), int32(0), int32(0), int32(0), int32(0), int32(0)],
755762
rowCallback,
763+
requestId,
756764
)
757765
).isOkOr:
758766
return err(stmtName & ": " & $error)
759767

760768
return ok(rows)
761769

762770
proc getMessagesByMessageHashes(
763-
s: PostgresDriver, hashes: string, maxPageSize: uint
771+
s: PostgresDriver, hashes: string, maxPageSize: uint, requestId: string
764772
): Future[ArchiveDriverResult[seq[ArchiveRow]]] {.async.} =
765773
## Retrieves information only filtering by a given messageHashes list.
766774
## This proc levarages on the messages_lookup table to have better query performance
@@ -797,7 +805,11 @@ proc getMessagesByMessageHashes(
797805
proc rowCallback(pqResult: ptr PGresult) =
798806
rowCallbackImpl(pqResult, rows)
799807

800-
(await s.readConnPool.pgQuery(query = query, rowCallback = rowCallback)).isOkOr:
808+
(
809+
await s.readConnPool.pgQuery(
810+
query = query, rowCallback = rowCallback, requestId = requestId
811+
)
812+
).isOkOr:
801813
return err("failed to run query: " & $error)
802814

803815
debug "end of getMessagesByMessageHashes"
@@ -814,6 +826,7 @@ method getMessages*(
814826
hashes = newSeq[WakuMessageHash](0),
815827
maxPageSize = DefaultPageSize,
816828
ascendingOrder = true,
829+
requestId = "",
817830
): Future[ArchiveDriverResult[seq[ArchiveRow]]] {.async.} =
818831
debug "beginning of getMessages"
819832

@@ -825,8 +838,9 @@ method getMessages*(
825838

826839
if cursor.isNone() and pubsubTopic.isNone() and contentTopics.len == 0 and
827840
startTime.isNone() and endTime.isNone() and hexHashes.len > 0:
828-
return
829-
await s.getMessagesByMessageHashes("'" & hexHashes.join("','") & "'", maxPageSize)
841+
return await s.getMessagesByMessageHashes(
842+
"'" & hexHashes.join("','") & "'", maxPageSize, requestId
843+
)
830844

831845
if contentTopics.len > 0 and hexHashes.len > 0 and pubsubTopic.isSome() and
832846
startTime.isSome() and endTime.isSome():
@@ -841,6 +855,7 @@ method getMessages*(
841855
hexHashes.join(","),
842856
maxPageSize,
843857
ascendingOrder,
858+
requestId,
844859
)
845860
else:
846861
return await s.getMessageHashesPreparedStmt(
@@ -852,18 +867,19 @@ method getMessages*(
852867
hexHashes.join(","),
853868
maxPageSize,
854869
ascendingOrder,
870+
requestId,
855871
)
856872
else:
857873
if includeData:
858874
## We will run atypical query. In this case we don't use prepared statemets
859875
return await s.getMessagesArbitraryQuery(
860876
contentTopics, pubsubTopic, cursor, startTime, endTime, hexHashes, maxPageSize,
861-
ascendingOrder,
877+
ascendingOrder, requestId,
862878
)
863879
else:
864880
return await s.getMessageHashesArbitraryQuery(
865881
contentTopics, pubsubTopic, cursor, startTime, endTime, hexHashes, maxPageSize,
866-
ascendingOrder,
882+
ascendingOrder, requestId,
867883
)
868884

869885
proc getStr(

waku/waku_archive/driver/queue_driver/queue_driver.nim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ method getMessages*(
256256
hashes: seq[WakuMessageHash] = @[],
257257
maxPageSize = DefaultPageSize,
258258
ascendingOrder = true,
259+
requestId = "",
259260
): Future[ArchiveDriverResult[seq[ArchiveRow]]] {.async.} =
260261
var index = none(Index)
261262

waku/waku_archive/driver/sqlite_driver/sqlite_driver.nim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ method getMessages*(
8383
hashes = newSeq[WakuMessageHash](0),
8484
maxPageSize = DefaultPageSize,
8585
ascendingOrder = true,
86+
requestId = "",
8687
): Future[ArchiveDriverResult[seq[ArchiveRow]]] {.async.} =
8788
if not includeData:
8889
return s.db.selectMessageHashesByStoreQueryWithLimit(

0 commit comments

Comments
 (0)