Skip to content

Commit b31ed7a

Browse files
kirsarielvalentin
andauthored
feat: Instrument PG connect (#1763)
Instrument PG connect Co-authored-by: Ariel Valentin <[email protected]>
1 parent e58ec51 commit b31ed7a

File tree

4 files changed

+262
-95
lines changed

4 files changed

+262
-95
lines changed

instrumentation/pg/lib/opentelemetry/instrumentation/pg/constants.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ module Constants
9494
async_exec_prepared
9595
sync_exec_prepared
9696
].freeze
97+
98+
CONNECTION_METHODS = %i[
99+
connect
100+
open
101+
async_connect
102+
].freeze
97103
end
98104
end
99105
end

instrumentation/pg/lib/opentelemetry/instrumentation/pg/instrumentation.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def require_dependencies
4040

4141
def patch_client
4242
::PG::Connection.prepend(Patches::Connection)
43+
::PG::Connection.singleton_class.prepend(Patches::Connect)
4344
end
4445
end
4546
end

instrumentation/pg/lib/opentelemetry/instrumentation/pg/patches/connection.rb

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,65 @@ module OpenTelemetry
1212
module Instrumentation
1313
module PG
1414
module Patches
15+
# Utility methods for setting connection attributes from Connect module
16+
module ConnectionHelper
17+
module_function
18+
19+
def set_connection_attributes(span, conn, config)
20+
attributes = {
21+
'db.system' => 'postgresql',
22+
'db.name' => conn.db,
23+
'db.user' => conn.user
24+
}
25+
attributes['peer.service'] = config[:peer_service] if config[:peer_service]
26+
27+
h = conn.host
28+
if h&.start_with?('/')
29+
attributes['net.sock.family'] = 'unix'
30+
attributes['net.peer.name'] = h
31+
else
32+
attributes['net.transport'] = 'ip_tcp'
33+
attributes['net.peer.name'] = h
34+
attributes['net.peer.port'] = conn.port if defined?(::PG::DEF_PGPORT)
35+
end
36+
37+
attributes.merge!(OpenTelemetry::Instrumentation::PG.attributes)
38+
attributes.compact!
39+
40+
span.add_attributes(attributes)
41+
end
42+
end
43+
44+
# Module to prepend to PG::Connection singleton class for connection initialization
45+
# We override `new` instead of `initialize` because PG::Connection.new is implemented
46+
# as a Ruby method that calls the C-level connect_start, bypassing initialize.
47+
# We also need to override the aliases (open, connect, async_connect) because they
48+
# were aliased before our prepend, so they point to the original method.
49+
# See: https://github.com/ged/ruby-pg/blob/master/lib/pg/connection.rb#L870
50+
module Connect
51+
def new(...)
52+
tracer = OpenTelemetry::Instrumentation::PG::Instrumentation.instance.tracer
53+
config = OpenTelemetry::Instrumentation::PG::Instrumentation.instance.config
54+
55+
tracer.in_span('connect', kind: :client) do |span|
56+
if block_given?
57+
super do |conn|
58+
ConnectionHelper.set_connection_attributes(span, conn, config)
59+
yield conn
60+
end
61+
else
62+
conn = super
63+
ConnectionHelper.set_connection_attributes(span, conn, config)
64+
conn
65+
end
66+
end
67+
end
68+
69+
PG::Constants::CONNECTION_METHODS.each do |method|
70+
alias_method method, :new
71+
end
72+
end
73+
1574
# Module to prepend to PG::Connection for instrumentation
1675
module Connection # rubocop:disable Metrics/ModuleLength
1776
# Capture the first word (including letters, digits, underscores, & '.', ) that follows common table commands

0 commit comments

Comments
 (0)