44
55namespace OpenTelemetry \Contrib \Instrumentation \Doctrine ;
66
7+ use Doctrine \DBAL \Driver \Result as ResultInterface ;
8+ use Doctrine \DBAL \Driver \Statement ;
79use OpenTelemetry \API \Instrumentation \CachedInstrumentation ;
810use OpenTelemetry \API \Trace \Span ;
911use OpenTelemetry \API \Trace \SpanBuilderInterface ;
1012use OpenTelemetry \API \Trace \SpanKind ;
1113use OpenTelemetry \API \Trace \StatusCode ;
1214use OpenTelemetry \Context \Context ;
13-
1415use function OpenTelemetry \Instrumentation \hook ;
15-
1616use OpenTelemetry \SemConv \TraceAttributes ;
1717use Throwable ;
1818
@@ -23,18 +23,19 @@ class DoctrineInstrumentation
2323 public static function register (): void
2424 {
2525 $ instrumentation = new CachedInstrumentation ('io.opentelemetry.contrib.php.doctrine ' );
26+ $ tracker = new DoctrineTracker ();
2627
2728 hook (
2829 \Doctrine \DBAL \Driver::class,
2930 'connect ' ,
3031 pre: static function (\Doctrine \DBAL \Driver $ driver , array $ params , string $ class , string $ function , ?string $ filename , ?int $ lineno ) use ($ instrumentation ) {
3132 /** @psalm-suppress ArgumentTypeCoercion */
3233 $ builder = self ::makeBuilder ($ instrumentation , 'Doctrine\DBAL\Driver::connect ' , $ function , $ class , $ filename , $ lineno )
33- ->setSpanKind (SpanKind::KIND_CLIENT )
34- ->setAttribute (TraceAttributes::SERVER_ADDRESS , AttributesResolver::get (TraceAttributes::SERVER_ADDRESS , func_get_args ()))
35- ->setAttribute (TraceAttributes::SERVER_PORT , AttributesResolver::get (TraceAttributes::SERVER_PORT , func_get_args ()))
36- ->setAttribute (TraceAttributes::DB_SYSTEM_NAME , AttributesResolver::get (TraceAttributes::DB_SYSTEM_NAME , func_get_args ()))
37- ->setAttribute (TraceAttributes::DB_NAMESPACE , AttributesResolver::get (TraceAttributes::DB_NAMESPACE , func_get_args ()));
34+ ->setSpanKind (SpanKind::KIND_CLIENT )
35+ ->setAttribute (TraceAttributes::SERVER_ADDRESS , AttributesResolver::get (TraceAttributes::SERVER_ADDRESS , func_get_args ()))
36+ ->setAttribute (TraceAttributes::SERVER_PORT , AttributesResolver::get (TraceAttributes::SERVER_PORT , func_get_args ()))
37+ ->setAttribute (TraceAttributes::DB_SYSTEM_NAME , AttributesResolver::get (TraceAttributes::DB_SYSTEM_NAME , func_get_args ()))
38+ ->setAttribute (TraceAttributes::DB_NAMESPACE , AttributesResolver::get (TraceAttributes::DB_NAMESPACE , func_get_args ()));
3839 $ parent = Context::getCurrent ();
3940 $ span = $ builder ->startSpan ();
4041 Context::storage ()->attach ($ span ->storeInContext ($ parent ));
@@ -52,6 +53,8 @@ public static function register(): void
5253 $ builder = self ::makeBuilder ($ instrumentation , AttributesResolver::getDbQuerySummary ($ params ), $ function , $ class , $ filename , $ lineno )
5354 ->setSpanKind (SpanKind::KIND_CLIENT );
5455 $ builder ->setAttribute (TraceAttributes::DB_QUERY_TEXT , AttributesResolver::get (TraceAttributes::DB_QUERY_TEXT , func_get_args ()));
56+ $ builder ->setAttribute (TraceAttributes::DB_OPERATION_NAME , AttributesResolver::getDbOperationName ($ params ));
57+ $ builder ->setAttribute (TraceAttributes::DB_COLLECTION_NAME , AttributesResolver::getTarget ($ params ));
5558 $ parent = Context::getCurrent ();
5659 $ span = $ builder ->startSpan ();
5760 Context::storage ()->attach ($ span ->storeInContext ($ parent ));
@@ -68,7 +71,9 @@ public static function register(): void
6871 /** @psalm-suppress ArgumentTypeCoercion */
6972 $ builder = self ::makeBuilder ($ instrumentation , AttributesResolver::getDbQuerySummary ($ params ), $ function , $ class , $ filename , $ lineno )
7073 ->setSpanKind (SpanKind::KIND_CLIENT )
71- ->setAttribute (TraceAttributes::DB_QUERY_TEXT , AttributesResolver::get (TraceAttributes::DB_QUERY_TEXT , func_get_args ()));
74+ ->setAttribute (TraceAttributes::DB_QUERY_TEXT , AttributesResolver::get (TraceAttributes::DB_QUERY_TEXT , func_get_args ()))
75+ ->setAttribute (TraceAttributes::DB_OPERATION_NAME , AttributesResolver::getDbOperationName ($ params ))
76+ ->setAttribute (TraceAttributes::DB_COLLECTION_NAME , AttributesResolver::getTarget ($ params ));
7277 $ parent = Context::getCurrent ();
7378 $ span = $ builder ->startSpan ();
7479
@@ -86,13 +91,22 @@ public static function register(): void
8691 /** @psalm-suppress ArgumentTypeCoercion */
8792 $ builder = self ::makeBuilder ($ instrumentation , AttributesResolver::getDbQuerySummary ($ params ), $ function , $ class , $ filename , $ lineno )
8893 ->setSpanKind (SpanKind::KIND_CLIENT )
89- ->setAttribute (TraceAttributes::DB_QUERY_TEXT , AttributesResolver::get (TraceAttributes::DB_QUERY_TEXT , func_get_args ()));
94+ ->setAttribute (TraceAttributes::DB_QUERY_TEXT , AttributesResolver::get (TraceAttributes::DB_QUERY_TEXT , func_get_args ()))
95+ ->setAttribute (TraceAttributes::DB_OPERATION_NAME , 'prepare ' );
9096 $ parent = Context::getCurrent ();
9197 $ span = $ builder ->startSpan ();
9298
9399 Context::storage ()->attach ($ span ->storeInContext ($ parent ));
94100 },
95- post: static function (\Doctrine \DBAL \Driver \Connection $ connection , array $ params , mixed $ statement , ?Throwable $ exception ) {
101+ post: static function (\Doctrine \DBAL \Driver \Connection $ connection , array $ params , ?Statement $ statement , ?Throwable $ exception ) use ($ tracker ) {
102+ if ($ statement ) {
103+ $ scope = Context::storage ()->scope ();
104+ $ context = $ scope ?->context();
105+ if ($ context ) {
106+ $ span = Span::fromContext ($ context );
107+ $ tracker ->trackStatement ($ statement , $ span ->getContext ());
108+ }
109+ }
96110 self ::end ($ exception );
97111 }
98112 );
@@ -102,8 +116,9 @@ public static function register(): void
102116 'beginTransaction ' ,
103117 pre: static function (\Doctrine \DBAL \Driver \Connection $ connection , array $ params , string $ class , string $ function , ?string $ filename , ?int $ lineno ) use ($ instrumentation ) {
104118 /** @psalm-suppress ArgumentTypeCoercion */
105- $ builder = self ::makeBuilder ($ instrumentation , 'Doctrine\DBAL\Driver\Connection::beginTransaction ' , $ function , $ class , $ filename , $ lineno )
106- ->setSpanKind (SpanKind::KIND_CLIENT );
119+ $ builder = self ::makeBuilder ($ instrumentation , 'Doctrine::beginTransaction ' , $ function , $ class , $ filename , $ lineno )
120+ ->setSpanKind (SpanKind::KIND_CLIENT )
121+ ->setAttribute (TraceAttributes::DB_OPERATION_NAME , 'begin ' );
107122 $ parent = Context::getCurrent ();
108123 $ span = $ builder ->startSpan ();
109124
@@ -119,8 +134,9 @@ public static function register(): void
119134 'commit ' ,
120135 pre: static function (\Doctrine \DBAL \Driver \Connection $ connection , array $ params , string $ class , string $ function , ?string $ filename , ?int $ lineno ) use ($ instrumentation ) {
121136 /** @psalm-suppress ArgumentTypeCoercion */
122- $ builder = self ::makeBuilder ($ instrumentation , 'Doctrine\DBAL\Driver\Connection::commit ' , $ function , $ class , $ filename , $ lineno )
123- ->setSpanKind (SpanKind::KIND_CLIENT );
137+ $ builder = self ::makeBuilder ($ instrumentation , 'Doctrine::commit ' , $ function , $ class , $ filename , $ lineno )
138+ ->setSpanKind (SpanKind::KIND_CLIENT )
139+ ->setAttribute (TraceAttributes::DB_OPERATION_NAME , 'commit ' );
124140 $ parent = Context::getCurrent ();
125141 $ span = $ builder ->startSpan ();
126142
@@ -136,8 +152,9 @@ public static function register(): void
136152 'rollBack ' ,
137153 pre: static function (\Doctrine \DBAL \Driver \Connection $ connection , array $ params , string $ class , string $ function , ?string $ filename , ?int $ lineno ) use ($ instrumentation ) {
138154 /** @psalm-suppress ArgumentTypeCoercion */
139- $ builder = self ::makeBuilder ($ instrumentation , 'Doctrine\DBAL\Driver\Connection::rollBack ' , $ function , $ class , $ filename , $ lineno )
140- ->setSpanKind (SpanKind::KIND_CLIENT );
155+ $ builder = self ::makeBuilder ($ instrumentation , 'Doctrine::rollBack ' , $ function , $ class , $ filename , $ lineno )
156+ ->setSpanKind (SpanKind::KIND_CLIENT )
157+ ->setAttribute (TraceAttributes::DB_OPERATION_NAME , 'rollback ' );
141158 $ parent = Context::getCurrent ();
142159 $ span = $ builder ->startSpan ();
143160 Context::storage ()->attach ($ span ->storeInContext ($ parent ));
@@ -146,7 +163,29 @@ public static function register(): void
146163 self ::end ($ exception );
147164 }
148165 );
166+
167+ hook (
168+ \Doctrine \DBAL \Driver \Statement::class,
169+ 'execute ' ,
170+ pre: static function (\Doctrine \DBAL \Driver \Statement $ statement , array $ params , string $ class , string $ function , ?string $ filename , ?int $ lineno ) use ($ instrumentation , $ tracker ) {
171+ /** @psalm-suppress ArgumentTypeCoercion */
172+ $ builder = self ::makeBuilder ($ instrumentation , 'Doctrine::execute ' , $ function , $ class , $ filename , $ lineno )
173+ ->setSpanKind (SpanKind::KIND_CLIENT )
174+ ->setAttribute (TraceAttributes::DB_OPERATION_NAME , 'execute ' );
175+ if ($ ctx = $ tracker ->getSpanContextForStatement ($ statement )) {
176+ $ builder ->addLink ($ ctx );
177+ }
178+ $ parent = Context::getCurrent ();
179+ $ span = $ builder ->startSpan ();
180+
181+ Context::storage ()->attach ($ span ->storeInContext ($ parent ));
182+ },
183+ post: static function (\Doctrine \DBAL \Driver \Statement $ statement , array $ params , ResultInterface $ result , ?Throwable $ exception ) {
184+ self ::end ($ exception );
185+ }
186+ );
149187 }
188+
150189 private static function makeBuilder (
151190 CachedInstrumentation $ instrumentation ,
152191 string $ name ,
0 commit comments