pg-lock-tracer 0.5.5__tar.gz → 0.6.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. {pg_lock_tracer-0.5.5/src/pg_lock_tracer.egg-info → pg_lock_tracer-0.6.1}/PKG-INFO +79 -8
  2. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/README.md +78 -7
  3. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/setup.cfg +1 -0
  4. pg_lock_tracer-0.6.1/src/pg_lock_tracer/__init__.py +1 -0
  5. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer/animate_lock_graph.py +12 -2
  6. pg_lock_tracer-0.6.1/src/pg_lock_tracer/bpf/pg_row_lock_tracer.c +121 -0
  7. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer/helper.py +56 -1
  8. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer/oid_resolver.py +1 -0
  9. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer/pg_lock_tracer.py +149 -69
  10. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer/pg_lw_lock_tracer.py +12 -19
  11. pg_lock_tracer-0.6.1/src/pg_lock_tracer/pg_row_lock_tracer.py +372 -0
  12. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1/src/pg_lock_tracer.egg-info}/PKG-INFO +79 -8
  13. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer.egg-info/SOURCES.txt +2 -0
  14. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer.egg-info/entry_points.txt +1 -0
  15. pg_lock_tracer-0.5.5/src/pg_lock_tracer/__init__.py +0 -1
  16. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/LICENSE +0 -0
  17. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/pyproject.toml +0 -0
  18. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/setup.py +0 -0
  19. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer/bpf/__init__.py +0 -0
  20. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer/bpf/pg_lock_tracer.c +0 -0
  21. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer/bpf/pg_lw_lock_tracer.c +0 -0
  22. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer.egg-info/dependency_links.txt +0 -0
  23. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer.egg-info/requires.txt +0 -0
  24. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer.egg-info/top_level.txt +0 -0
  25. {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/tests/test_helper.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pg_lock_tracer
3
- Version: 0.5.5
3
+ Version: 0.6.1
4
4
  Summary: A BPF based lock tracer for the PostgreSQL database
5
5
  Home-page: https://github.com/jnidzwetzki/pg-lock-tracer
6
6
  Author: Jan Nidzwetzki
@@ -30,11 +30,12 @@ Requires-Dist: psycopg2
30
30
 
31
31
  This project provides tools that allow you to gain deep insights into PostgreSQL's locking activities and troubleshoot locking-related issues (e.g., performance problems or deadlocks).
32
32
 
33
- * `pg_lock_tracer` - is a lock tracer for PostgreSQL.
34
- * `pg_lw_lock_tracer` - is a tracer for PostgreSQL lightweight locks (LWLocks).
33
+ * `pg_lock_tracer` - is a PostgreSQL table level lock tracer.
34
+ * `pg_lw_lock_tracer` - is a tracer for PostgreSQL lightweight locks (LWLocks).
35
+ * `pg_row_lock_tracer` - is a tracer for PostgreSQL row locks.
35
36
  * `animate_lock_graph` - creates animated locks graphs based on the `pg_lock_tracer` output.
36
37
 
37
- __Note:__ Most of these tools employ the [BPF / eBPF](https://ebpf.io/) (_Extended Berkeley Packet Filter_) technology. At the moment, PostgreSQL 12, 13, 14, and 15 are supported (see additional information below).
38
+ __Note:__ These tools employ the [eBPF](https://ebpf.io/) (_Extended Berkeley Packet Filter_) technology. At the moment, PostgreSQL 12, 13, 14, 15, and 16 are supported (see additional information below).
38
39
 
39
40
  # pg_lock_tracer
40
41
  `pg_lock_tracer` observes the locking activity of a running PostgreSQL process (using _eBPF_ and _UProbes_). In contrast to the information that is present in the table `pg_locks` (which provides information about which locks are _currently_ requested), `pg_lock_tracer` gives you a continuous view of the locking activity and collects statistics and timings.
@@ -73,8 +74,13 @@ pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_15_1_DEBUG/bin/postgres -
73
74
  # Show statistics about locks
74
75
  pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_15_1_DEBUG/bin/postgres -p 1234 --statistics
75
76
 
76
- # Create an animated lock graph
77
- animate_lock_graph -i create_table_trace.json -o create_table_trace.html
77
+ # Create an animated lock graph (with Oids)
78
+ pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_15_1_DEBUG/bin/postgres -p 1234 -j -o locks.json
79
+ animate_lock_graph -i lock -o locks.html
80
+
81
+ # Create an animated lock graph (with table names)
82
+ pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_15_1_DEBUG/bin/postgres -p 1234 -j -r 1234:psql://jan@localhost/test2 -o locks.json
83
+ animate_lock_graph -i lock -o locks.html
78
84
  ```
79
85
 
80
86
  ## Example Output
@@ -686,7 +692,7 @@ pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_14_2_DEBUG/bin/postgres -
686
692
  ### Animated Lock Graphs
687
693
  See the content of the [examples](examples/) directory for examples.
688
694
 
689
- # pg_lw_lock_trace
695
+ # pg_lw_lock_tracer
690
696
 
691
697
  `pg_lw_lock_trace` allows to trace lightweight locks ([LWLocks](https://github.com/postgres/postgres/blob/c8e1ba736b2b9e8c98d37a5b77c4ed31baf94147/src/backend/storage/lmgr/lwlock.c)) in a PostgreSQL process via _Userland Statically Defined Tracing_ (USDT).
692
698
 
@@ -805,8 +811,73 @@ Locks per type
805
811
  +--------------+----------+
806
812
  ```
807
813
 
808
- # Additional Information
814
+ # pg_row_lock_tracer
815
+
816
+ `pg_row_lock_tracer` allows to trace row locks (see the PostgreSQL [documentation](https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-ROWS)) of a PostgreSQL process using _eBPF_ and _UProbes_
817
+
818
+ ## Usage Examples
819
+ ```
820
+ # Trace the row locks of the given PostgreSQL binary
821
+ pg_row_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres
822
+
823
+ # Trace the row locks of the PID 1234
824
+ pg_row_lock_tracer -p 1234 -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres
825
+
826
+ # Trace the row locks of the PID 1234 and 5678
827
+ pg_row_lock_tracer -p 1234 -p 5678 -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres
828
+
829
+ # Trace the row locks of the PID 1234 and be verbose
830
+ pg_row_lock_tracer -p 1234 -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres -v
831
+
832
+ # Trace the row locks and show statistics
833
+ pg_row_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres --statistics
834
+ ```
835
+
836
+ ## Example output
809
837
 
838
+ SQL Query: `SELECT * FROM temperature FOR UPDATE;`
839
+
840
+ CLI: `sudo pg_row_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres --statistics`
841
+
842
+
843
+ Tracer output:
844
+
845
+ ```
846
+ [...]
847
+ 2783502701862408 [Pid 2604491] LOCK_TUPLE_END TM_OK in 13100 ns
848
+ 2783502701877081 [Pid 2604491] LOCK_TUPLE (Tablespace 1663 database 305234 relation 313419) - (Block and offset 7 143) - LOCK_TUPLE_EXCLUSIVE LOCK_WAIT_BLOCK
849
+ 2783502701972367 [Pid 2604491] LOCK_TUPLE_END TM_OK in 95286 ns
850
+ 2783502701988387 [Pid 2604491] LOCK_TUPLE (Tablespace 1663 database 305234 relation 313419) - (Block and offset 7 144) - LOCK_TUPLE_EXCLUSIVE LOCK_WAIT_BLOCK
851
+ 2783502702001690 [Pid 2604491] LOCK_TUPLE_END TM_OK in 13303 ns
852
+ 2783502702016387 [Pid 2604491] LOCK_TUPLE (Tablespace 1663 database 305234 relation 313419) - (Block and offset 7 145) - LOCK_TUPLE_EXCLUSIVE LOCK_WAIT_BLOCK
853
+ 2783502702029375 [Pid 2604491] LOCK_TUPLE_END TM_OK in 12988 ns
854
+ ^C
855
+ Lock statistics:
856
+ ================
857
+
858
+ Used wait policies:
859
+ +---------+-----------------+----------------+-----------------+
860
+ | PID | LOCK_WAIT_BLOCK | LOCK_WAIT_SKIP | LOCK_WAIT_ERROR |
861
+ +---------+-----------------+----------------+-----------------+
862
+ | 2604491 | 1440 | 0 | 0 |
863
+ +---------+-----------------+----------------+-----------------+
864
+
865
+ Lock modes:
866
+ +---------+---------------------+------------------+---------------------------+----------------------+
867
+ | PID | LOCK_TUPLE_KEYSHARE | LOCK_TUPLE_SHARE | LOCK_TUPLE_NOKEYEXCLUSIVE | LOCK_TUPLE_EXCLUSIVE |
868
+ +---------+---------------------+------------------+---------------------------+----------------------+
869
+ | 2604491 | 0 | 0 | 0 | 1440 |
870
+ +---------+---------------------+------------------+---------------------------+----------------------+
871
+
872
+ Lock results:
873
+ +---------+-------+--------------+-----------------+------------+------------+------------------+---------------+
874
+ | PID | TM_OK | TM_INVISIBLE | TM_SELFMODIFIED | TM_UPDATED | TM_DELETED | TM_BEINGMODIFIED | TM_WOULDBLOCK |
875
+ +---------+-------+--------------+-----------------+------------+------------+------------------+---------------+
876
+ | 2604491 | 1440 | 0 | 0 | 0 | 0 | 0 | 0 |
877
+ +---------+-------+--------------+-----------------+------------+------------+------------------+---------------+
878
+ ```
879
+
880
+ # Additional Information
810
881
 
811
882
  ## Installation
812
883
 
@@ -8,11 +8,12 @@
8
8
 
9
9
  This project provides tools that allow you to gain deep insights into PostgreSQL's locking activities and troubleshoot locking-related issues (e.g., performance problems or deadlocks).
10
10
 
11
- * `pg_lock_tracer` - is a lock tracer for PostgreSQL.
12
- * `pg_lw_lock_tracer` - is a tracer for PostgreSQL lightweight locks (LWLocks).
11
+ * `pg_lock_tracer` - is a PostgreSQL table level lock tracer.
12
+ * `pg_lw_lock_tracer` - is a tracer for PostgreSQL lightweight locks (LWLocks).
13
+ * `pg_row_lock_tracer` - is a tracer for PostgreSQL row locks.
13
14
  * `animate_lock_graph` - creates animated locks graphs based on the `pg_lock_tracer` output.
14
15
 
15
- __Note:__ Most of these tools employ the [BPF / eBPF](https://ebpf.io/) (_Extended Berkeley Packet Filter_) technology. At the moment, PostgreSQL 12, 13, 14, and 15 are supported (see additional information below).
16
+ __Note:__ These tools employ the [eBPF](https://ebpf.io/) (_Extended Berkeley Packet Filter_) technology. At the moment, PostgreSQL 12, 13, 14, 15, and 16 are supported (see additional information below).
16
17
 
17
18
  # pg_lock_tracer
18
19
  `pg_lock_tracer` observes the locking activity of a running PostgreSQL process (using _eBPF_ and _UProbes_). In contrast to the information that is present in the table `pg_locks` (which provides information about which locks are _currently_ requested), `pg_lock_tracer` gives you a continuous view of the locking activity and collects statistics and timings.
@@ -51,8 +52,13 @@ pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_15_1_DEBUG/bin/postgres -
51
52
  # Show statistics about locks
52
53
  pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_15_1_DEBUG/bin/postgres -p 1234 --statistics
53
54
 
54
- # Create an animated lock graph
55
- animate_lock_graph -i create_table_trace.json -o create_table_trace.html
55
+ # Create an animated lock graph (with Oids)
56
+ pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_15_1_DEBUG/bin/postgres -p 1234 -j -o locks.json
57
+ animate_lock_graph -i lock -o locks.html
58
+
59
+ # Create an animated lock graph (with table names)
60
+ pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_15_1_DEBUG/bin/postgres -p 1234 -j -r 1234:psql://jan@localhost/test2 -o locks.json
61
+ animate_lock_graph -i lock -o locks.html
56
62
  ```
57
63
 
58
64
  ## Example Output
@@ -664,7 +670,7 @@ pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_14_2_DEBUG/bin/postgres -
664
670
  ### Animated Lock Graphs
665
671
  See the content of the [examples](examples/) directory for examples.
666
672
 
667
- # pg_lw_lock_trace
673
+ # pg_lw_lock_tracer
668
674
 
669
675
  `pg_lw_lock_trace` allows to trace lightweight locks ([LWLocks](https://github.com/postgres/postgres/blob/c8e1ba736b2b9e8c98d37a5b77c4ed31baf94147/src/backend/storage/lmgr/lwlock.c)) in a PostgreSQL process via _Userland Statically Defined Tracing_ (USDT).
670
676
 
@@ -783,8 +789,73 @@ Locks per type
783
789
  +--------------+----------+
784
790
  ```
785
791
 
786
- # Additional Information
792
+ # pg_row_lock_tracer
793
+
794
+ `pg_row_lock_tracer` allows to trace row locks (see the PostgreSQL [documentation](https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-ROWS)) of a PostgreSQL process using _eBPF_ and _UProbes_
795
+
796
+ ## Usage Examples
797
+ ```
798
+ # Trace the row locks of the given PostgreSQL binary
799
+ pg_row_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres
800
+
801
+ # Trace the row locks of the PID 1234
802
+ pg_row_lock_tracer -p 1234 -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres
803
+
804
+ # Trace the row locks of the PID 1234 and 5678
805
+ pg_row_lock_tracer -p 1234 -p 5678 -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres
806
+
807
+ # Trace the row locks of the PID 1234 and be verbose
808
+ pg_row_lock_tracer -p 1234 -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres -v
809
+
810
+ # Trace the row locks and show statistics
811
+ pg_row_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres --statistics
812
+ ```
813
+
814
+ ## Example output
787
815
 
816
+ SQL Query: `SELECT * FROM temperature FOR UPDATE;`
817
+
818
+ CLI: `sudo pg_row_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres --statistics`
819
+
820
+
821
+ Tracer output:
822
+
823
+ ```
824
+ [...]
825
+ 2783502701862408 [Pid 2604491] LOCK_TUPLE_END TM_OK in 13100 ns
826
+ 2783502701877081 [Pid 2604491] LOCK_TUPLE (Tablespace 1663 database 305234 relation 313419) - (Block and offset 7 143) - LOCK_TUPLE_EXCLUSIVE LOCK_WAIT_BLOCK
827
+ 2783502701972367 [Pid 2604491] LOCK_TUPLE_END TM_OK in 95286 ns
828
+ 2783502701988387 [Pid 2604491] LOCK_TUPLE (Tablespace 1663 database 305234 relation 313419) - (Block and offset 7 144) - LOCK_TUPLE_EXCLUSIVE LOCK_WAIT_BLOCK
829
+ 2783502702001690 [Pid 2604491] LOCK_TUPLE_END TM_OK in 13303 ns
830
+ 2783502702016387 [Pid 2604491] LOCK_TUPLE (Tablespace 1663 database 305234 relation 313419) - (Block and offset 7 145) - LOCK_TUPLE_EXCLUSIVE LOCK_WAIT_BLOCK
831
+ 2783502702029375 [Pid 2604491] LOCK_TUPLE_END TM_OK in 12988 ns
832
+ ^C
833
+ Lock statistics:
834
+ ================
835
+
836
+ Used wait policies:
837
+ +---------+-----------------+----------------+-----------------+
838
+ | PID | LOCK_WAIT_BLOCK | LOCK_WAIT_SKIP | LOCK_WAIT_ERROR |
839
+ +---------+-----------------+----------------+-----------------+
840
+ | 2604491 | 1440 | 0 | 0 |
841
+ +---------+-----------------+----------------+-----------------+
842
+
843
+ Lock modes:
844
+ +---------+---------------------+------------------+---------------------------+----------------------+
845
+ | PID | LOCK_TUPLE_KEYSHARE | LOCK_TUPLE_SHARE | LOCK_TUPLE_NOKEYEXCLUSIVE | LOCK_TUPLE_EXCLUSIVE |
846
+ +---------+---------------------+------------------+---------------------------+----------------------+
847
+ | 2604491 | 0 | 0 | 0 | 1440 |
848
+ +---------+---------------------+------------------+---------------------------+----------------------+
849
+
850
+ Lock results:
851
+ +---------+-------+--------------+-----------------+------------+------------+------------------+---------------+
852
+ | PID | TM_OK | TM_INVISIBLE | TM_SELFMODIFIED | TM_UPDATED | TM_DELETED | TM_BEINGMODIFIED | TM_WOULDBLOCK |
853
+ +---------+-------+--------------+-----------------+------------+------------+------------------+---------------+
854
+ | 2604491 | 1440 | 0 | 0 | 0 | 0 | 0 | 0 |
855
+ +---------+-------+--------------+-----------------+------------+------------+------------------+---------------+
856
+ ```
857
+
858
+ # Additional Information
788
859
 
789
860
  ## Installation
790
861
 
@@ -48,6 +48,7 @@ pg_lock_tracer.bpf =
48
48
  console_scripts =
49
49
  pg_lock_tracer = pg_lock_tracer.pg_lock_tracer:main
50
50
  pg_lw_lock_tracer = pg_lock_tracer.pg_lw_lock_tracer:main
51
+ pg_row_lock_tracer = pg_lock_tracer.pg_row_lock_tracer:main
51
52
  animate_lock_graph = pg_lock_tracer.animate_lock_graph:main
52
53
 
53
54
  [egg_info]
@@ -0,0 +1 @@
1
+ __version__ = "0.6.1"
@@ -207,7 +207,7 @@ class DOTModel:
207
207
  if self.verbose:
208
208
  print(f"Processing {event}")
209
209
 
210
- tablename = event["table"]
210
+ tablename = StringHelper.get_tablename(event)
211
211
  lock_type = event["lock_type"]
212
212
 
213
213
  if not self.graph.vs.select(label_eq=tablename):
@@ -244,7 +244,7 @@ class DOTModel:
244
244
  if self.verbose:
245
245
  print(f"Processing {event}")
246
246
 
247
- tablename = event["table"]
247
+ tablename = StringHelper.get_tablename(event)
248
248
  lock_type = event["lock_type"]
249
249
  lock_numeric_value = PostgreSQLLockHelper.lock_type_to_int(lock_type)
250
250
 
@@ -383,6 +383,16 @@ class StringHelper:
383
383
 
384
384
  return result
385
385
 
386
+ @staticmethod
387
+ def get_tablename(event):
388
+ """
389
+ Get the tablename or the Oid of the event.
390
+ """
391
+ if "table" in event:
392
+ return event["table"]
393
+
394
+ return f"Oid {event['oid']}"
395
+
386
396
 
387
397
  def main():
388
398
  """
@@ -0,0 +1,121 @@
1
+ #include <uapi/linux/ptrace.h>
2
+
3
+ /* Placeholder for auto generated defines */
4
+ __DEFINES__
5
+
6
+ typedef struct RowLockEvent_t {
7
+ u32 pid;
8
+ u64 timestamp;
9
+ u32 event_type;
10
+
11
+ /* See RelFileNode - Oid is u32 */
12
+ u32 tablespace;
13
+ u32 database;
14
+ u32 relation;
15
+
16
+ /* LockTupleMode */
17
+ u8 locktuplemode;
18
+
19
+ /* LockWaitPolicy */
20
+ u8 lockwaitpolicy;
21
+
22
+ /* Locked tuple */
23
+ u32 blockid;
24
+ u16 offset;
25
+
26
+ /* TM_Result */
27
+ int lockresult;
28
+ } RowLockEvent;
29
+
30
+ BPF_PERF_OUTPUT(lockevents);
31
+
32
+ static void fill_and_submit(struct pt_regs *ctx, RowLockEvent *event) {
33
+ event->pid = bpf_get_current_pid_tgid();
34
+ event->timestamp = bpf_ktime_get_ns();
35
+
36
+ // sudo cat /sys/kernel/debug/tracing/trace_pipe
37
+ // bpf_trace_printk("LW lock event for trance: %s\\n", tranche);
38
+
39
+ lockevents.perf_submit(ctx, event, sizeof(RowLockEvent));
40
+ }
41
+
42
+ /*
43
+ * Acquire a tuple lock
44
+ *
45
+ * Arguments:
46
+ * 1. Relation relation (1st member RelFileNode)
47
+ * 2. ItemPointer tid
48
+ * 3. Snapshot snapshot,
49
+ * 4. TupleTableSlot *slot,
50
+ * 5. CommandId cid,
51
+ * 6. LockTupleMode mode,
52
+ * 7. LockWaitPolicy wait_policy,
53
+ * 8. uint8 flags,
54
+ * 9. TM_FailureData *tmfd
55
+ *
56
+ */
57
+ int heapam_tuple_lock(struct pt_regs *ctx) {
58
+ RowLockEvent event = {.event_type = EVENT_LOCK_TUPLE};
59
+
60
+ /*
61
+ * (gdb) ptype /o RelFileNode
62
+ * 0 | 4 Oid spcNode;
63
+ * 4 | 4 Oid dbNode;
64
+ * 8 | 4 Oid relNode;
65
+ */
66
+
67
+ char buffer_relation[12];
68
+ bpf_probe_read_user(buffer_relation, sizeof(buffer_relation),
69
+ (void *)PT_REGS_PARM1(ctx));
70
+ bpf_probe_read_kernel(&(event.tablespace), sizeof(event.tablespace),
71
+ &(buffer_relation[0]));
72
+ bpf_probe_read_kernel(&(event.database), sizeof(event.database),
73
+ &(buffer_relation[4]));
74
+ bpf_probe_read_kernel(&(event.relation), sizeof(event.relation),
75
+ &(buffer_relation[8]));
76
+
77
+ /* Locked tuple */
78
+ char buffer_item_pointer[6];
79
+ u16 bi_hi;
80
+ u16 bi_lo;
81
+
82
+ bpf_probe_read_user(buffer_item_pointer, sizeof(buffer_item_pointer),
83
+ (void *)PT_REGS_PARM2(ctx));
84
+ bpf_probe_read_kernel(&(bi_hi), sizeof(bi_hi), &(buffer_item_pointer[0]));
85
+ bpf_probe_read_kernel(&(bi_lo), sizeof(bi_lo), &(buffer_item_pointer[2]));
86
+ bpf_probe_read_kernel(&(event.offset), sizeof(event.offset),
87
+ &(buffer_item_pointer[4]));
88
+
89
+ /* See #define BlockIdGetBlockNumber(blockId) */
90
+ event.blockid = (bi_hi) << 16 | bi_lo;
91
+
92
+ /* Locking options */
93
+ bpf_probe_read_kernel(&(event.locktuplemode), sizeof(event.locktuplemode),
94
+ &(PT_REGS_PARM6(ctx)));
95
+
96
+ /* Only the first six function parameters are passed via register. All
97
+ * remaining parameters are stored on the stack.
98
+ *
99
+ * See: System V Application Binary Interface—AMD64 Architecture Processor
100
+ * Supplement.
101
+ */
102
+ void *ptr = 0;
103
+ bpf_probe_read(&ptr, sizeof(ptr), (void *)(PT_REGS_SP(ctx) + (1 * 8)));
104
+ bpf_probe_read_kernel(&(event.lockwaitpolicy), sizeof(event.lockwaitpolicy),
105
+ &ptr);
106
+
107
+ fill_and_submit(ctx, &event);
108
+ return 0;
109
+ }
110
+
111
+ /*
112
+ * Acquire a tuple lock - Function done
113
+ */
114
+ int heapam_tuple_lock_end(struct pt_regs *ctx) {
115
+ RowLockEvent event = {.event_type = EVENT_LOCK_TUPLE_END};
116
+
117
+ event.lockresult = PT_REGS_RC(ctx);
118
+
119
+ fill_and_submit(ctx, &event);
120
+ return 0;
121
+ }
@@ -6,9 +6,10 @@ import os
6
6
 
7
7
  from pathlib import Path
8
8
 
9
+ from bcc import BPF
9
10
 
10
- class PostgreSQLLockHelper:
11
11
 
12
+ class PostgreSQLLockHelper:
12
13
  """
13
14
  # Defines taken from: src/include/storage/lockdefs.h
14
15
  #
@@ -91,6 +92,9 @@ class PostgreSQLLockHelper:
91
92
 
92
93
 
93
94
  class BPFHelper:
95
+ # The size of the kernel ring buffer
96
+ page_cnt = 2048
97
+
94
98
  @staticmethod
95
99
  def enum_to_defines(enum_instance, prefix):
96
100
  """
@@ -115,3 +119,54 @@ class BPFHelper:
115
119
 
116
120
  with program_file.open("r") as bpf_program:
117
121
  return bpf_program.read()
122
+
123
+ @staticmethod
124
+ def check_pid_exe(pids, executable):
125
+ """
126
+ Do the given PIDs belong to the executable
127
+ """
128
+ if not pids:
129
+ return
130
+
131
+ for pid in pids:
132
+ if not os.path.isdir(f"/proc/{pid}"):
133
+ raise ValueError(
134
+ f"/proc entry for pid {pid} not found, does the process exist?"
135
+ )
136
+
137
+ binary = os.readlink(f"/proc/{pid}/exe")
138
+
139
+ if binary != executable:
140
+ raise ValueError(
141
+ f"Pid {pid} does not belong to binary {executable}. Executable is {binary}"
142
+ )
143
+
144
+ @staticmethod
145
+ def register_ebpf_probe(
146
+ path, bpf_instance, function_regex, bpf_fn_name, verbose, probe_on_enter=True
147
+ ):
148
+ """
149
+ Register a BPF probe
150
+ """
151
+ addresses = set()
152
+ func_and_addr = BPF.get_user_functions_and_addresses(path, function_regex)
153
+
154
+ if not func_and_addr:
155
+ raise ValueError(f"Unable to locate function {function_regex}")
156
+
157
+ # Handle address duplicates
158
+ for function, address in func_and_addr:
159
+ if address in addresses:
160
+ continue
161
+ addresses.add(address)
162
+
163
+ if probe_on_enter:
164
+ bpf_instance.attach_uprobe(name=path, sym=function, fn_name=bpf_fn_name)
165
+ if verbose:
166
+ print(f"Attaching to {function} at address {address} on enter")
167
+ else:
168
+ bpf_instance.attach_uretprobe(
169
+ name=path, sym=function, fn_name=bpf_fn_name
170
+ )
171
+ if verbose:
172
+ print(f"Attaching to {function} at address {address} on return")
@@ -1,4 +1,5 @@
1
1
  """Resolve PostgreSQL OIDs to names and cache the result"""
2
+
2
3
  import sys
3
4
 
4
5
  from urllib.parse import urlparse