10
10
#include "postgres.h"
11
11
12
12
#include <signal.h>
13
+ #include <time.h>
13
14
14
15
#include "compat.h"
15
16
#include "miscadmin.h"
30
31
#include "utils/resowner.h"
31
32
#include "utils/timestamp.h"
32
33
34
+ #define check_bestatus_dimensions (dimensions ) \
35
+ (dimensions & (PGWS_DIMENSIONS_BE_TYPE |\
36
+ PGWS_DIMENSIONS_BE_STATE |\
37
+ PGWS_DIMENSIONS_BE_START_TIME |\
38
+ PGWS_DIMENSIONS_CLIENT_ADDR |\
39
+ PGWS_DIMENSIONS_CLIENT_HOSTNAME |\
40
+ PGWS_DIMENSIONS_APPNAME))
33
41
static volatile sig_atomic_t shutdown_requested = false;
34
42
35
43
static void handle_sigterm (SIGNAL_ARGS );
@@ -162,25 +170,103 @@ probe_waits(History *observations, HTAB *profile_hash,
162
170
LWLockAcquire (ProcArrayLock , LW_SHARED );
163
171
for (i = 0 ; i < ProcGlobal -> allProcCount ; i ++ )
164
172
{
165
- HistoryItem item ,
173
+ HistoryItem item_history ,
166
174
* observation ;
175
+ ProfileItem item_profile ;
167
176
PGPROC * proc = & ProcGlobal -> allProcs [i ];
177
+ int pid ;
178
+ uint32 wait_event_info ;
168
179
169
- if (!pgws_should_sample_proc (proc , & item .pid , & item .wait_event_info ))
180
+ /* Check if we need to sample this process */
181
+ if (!pgws_should_sample_proc (proc , & pid , & wait_event_info ))
170
182
continue ;
171
183
184
+ /* We zero whole HistoryItem to avoid doing it field-by-field */
185
+ memset (& item_history , 0 , sizeof (HistoryItem ));
186
+ memset (& item_profile , 0 , sizeof (ProfileItem ));
187
+
188
+ item_history .pid = pid ;
189
+ item_profile .pid = pid ;
190
+
191
+ item_history .wait_event_info = wait_event_info ;
192
+ item_profile .wait_event_info = wait_event_info ;
193
+
172
194
if (pgws_profileQueries )
173
- item .queryId = pgws_proc_queryids [i ];
174
- else
175
- item .queryId = 0 ;
195
+ {
196
+ item_history .queryId = pgws_proc_queryids [i ];
197
+ item_profile .queryId = pgws_proc_queryids [i ];
198
+ }
176
199
177
- item .ts = ts ;
200
+ item_history .ts = ts ;
201
+
202
+ /* Copy everything we need from PGPROC */
203
+ if (pgws_history_dimensions & PGWS_DIMENSIONS_ROLE_ID )
204
+ item_history .role_id = proc -> roleId ;
205
+ if (pgws_profile_dimensions & PGWS_DIMENSIONS_ROLE_ID )
206
+ item_profile .role_id = proc -> roleId ;
207
+
208
+ if (pgws_history_dimensions & PGWS_DIMENSIONS_DB_ID )
209
+ item_history .database_id = proc -> databaseId ;
210
+ if (pgws_profile_dimensions & PGWS_DIMENSIONS_DB_ID )
211
+ item_profile .database_id = proc -> databaseId ;
212
+
213
+ if (pgws_history_dimensions & PGWS_DIMENSIONS_PARALLEL_LEADER_PID )
214
+ item_history .parallel_leader_pid = (proc -> lockGroupLeader ?
215
+ proc -> lockGroupLeader -> pid :
216
+ 0 );
217
+ if (pgws_profile_dimensions & PGWS_DIMENSIONS_PARALLEL_LEADER_PID )
218
+ item_profile .parallel_leader_pid = (proc -> lockGroupLeader ?
219
+ proc -> lockGroupLeader -> pid :
220
+ 0 );
221
+ /* Look into BackendStatus only if necessary */
222
+ if (check_bestatus_dimensions (pgws_history_dimensions ) ||
223
+ check_bestatus_dimensions (pgws_profile_dimensions ))
224
+ {
225
+ #if PG_VERSION_NUM >= 170000
226
+ PgBackendStatus * bestatus = pgstat_get_beentry_by_proc_number (GetNumberFromPGProc (proc ));
227
+ #else
228
+ PgBackendStatus * bestatus = get_beentry_by_procpid (proc -> pid );
229
+ #endif
230
+ /* Copy everything we need from BackendStatus */
231
+ if (bestatus )
232
+ {
233
+ if (pgws_history_dimensions & PGWS_DIMENSIONS_BE_TYPE )
234
+ item_history .backend_type = bestatus -> st_backendType ;
235
+ if (pgws_profile_dimensions & PGWS_DIMENSIONS_BE_TYPE )
236
+ item_profile .backend_type = bestatus -> st_backendType ;
237
+
238
+ if (pgws_history_dimensions & PGWS_DIMENSIONS_BE_STATE )
239
+ item_history .backend_state = bestatus -> st_state ;
240
+ if (pgws_profile_dimensions & PGWS_DIMENSIONS_BE_STATE )
241
+ item_profile .backend_state = bestatus -> st_state ;
242
+
243
+ if (pgws_history_dimensions & PGWS_DIMENSIONS_BE_START_TIME )
244
+ item_history .proc_start = bestatus -> st_proc_start_timestamp ;
245
+ if (pgws_profile_dimensions & PGWS_DIMENSIONS_BE_START_TIME )
246
+ item_profile .proc_start = bestatus -> st_proc_start_timestamp ;
247
+
248
+ if (pgws_history_dimensions & PGWS_DIMENSIONS_CLIENT_ADDR )
249
+ item_history .client_addr = bestatus -> st_clientaddr ;
250
+ if (pgws_profile_dimensions & PGWS_DIMENSIONS_CLIENT_ADDR )
251
+ item_profile .client_addr = bestatus -> st_clientaddr ;
252
+
253
+ if (pgws_history_dimensions & PGWS_DIMENSIONS_CLIENT_HOSTNAME )
254
+ strcpy (item_history .client_hostname , bestatus -> st_clienthostname );
255
+ if (pgws_profile_dimensions & PGWS_DIMENSIONS_CLIENT_HOSTNAME )
256
+ strcpy (item_profile .client_hostname , bestatus -> st_clienthostname );
257
+
258
+ if (pgws_history_dimensions & PGWS_DIMENSIONS_APPNAME )
259
+ strcpy (item_history .appname , bestatus -> st_appname );
260
+ if (pgws_profile_dimensions & PGWS_DIMENSIONS_APPNAME )
261
+ strcpy (item_profile .appname , bestatus -> st_appname );
262
+ }
263
+ }
178
264
179
265
/* Write to the history if needed */
180
266
if (write_history )
181
267
{
182
268
observation = get_next_observation (observations );
183
- * observation = item ;
269
+ * observation = item_history ;
184
270
}
185
271
186
272
/* Write to the profile if needed */
@@ -190,16 +276,21 @@ probe_waits(History *observations, HTAB *profile_hash,
190
276
bool found ;
191
277
192
278
if (!profile_pid )
193
- item .pid = 0 ;
279
+ item_profile .pid = 0 ;
194
280
195
- profileItem = (ProfileItem * ) hash_search (profile_hash , & item , HASH_ENTER , & found );
281
+ profileItem = (ProfileItem * ) hash_search (profile_hash , & item_profile , HASH_ENTER , & found );
196
282
if (found )
197
283
profileItem -> count ++ ;
198
284
else
199
285
profileItem -> count = 1 ;
200
286
}
201
287
}
202
288
LWLockRelease (ProcArrayLock );
289
+ #if PG_VERSION_NUM >= 140000
290
+ pgstat_clear_backend_activity_snapshot ();
291
+ #else
292
+ pgstat_clear_snapshot ();
293
+ #endif
203
294
}
204
295
205
296
/*
@@ -287,10 +378,12 @@ make_profile_hash()
287
378
{
288
379
HASHCTL hash_ctl ;
289
380
290
- if (pgws_profileQueries )
291
- hash_ctl .keysize = offsetof(ProfileItem , count );
292
- else
293
- hash_ctl .keysize = offsetof(ProfileItem , queryId );
381
+ /*
382
+ * Since adding additional dimensions we include everyting except count
383
+ * into hashtable key. This is fine for cases when some fields are 0 since
384
+ * it doesn't impede our ability to search the hash table for entries
385
+ */
386
+ hash_ctl .keysize = offsetof(ProfileItem , count );
294
387
295
388
hash_ctl .entrysize = sizeof (ProfileItem );
296
389
return hash_create ("Waits profile hash" , 1024 , & hash_ctl ,
0 commit comments