@@ -206,43 +206,62 @@ public static function detectError($pdoOrStatement, SpanData $span)
206206 $ span ->meta [Tag::ERROR_TYPE ] = get_class ($ pdoOrStatement ) . ' error ' ;
207207 }
208208
209+ const DSN_REGEX = <<<'REGEX'
210+ (\A
211+ (?<engine>[^:]++):
212+ (?:
213+ (?:
214+ (?:server|unix_socket|host(?:name)?)=(?<host>(?:[^;]*+(?:;;)?)++)
215+ |port=(?<port>(?&host))
216+ |charset=(?<charset>(?&host))
217+ |(?:database|dbname)=(?<db>(?&host))
218+ |driver=(?<driver>(?&host))
219+ |(?&host) # host can actually be empty, supporting repeated or trailing semicolons
220+ )
221+ (?:;|\Z)
222+ )++
223+ )xi
224+ REGEX;
225+
209226 private static function parseDsn ($ dsn )
210227 {
211- $ engine = substr ($ dsn , 0 , strpos ($ dsn , ': ' ));
212- $ tags = ['db.engine ' => $ engine ];
213- $ dbSystem = self ::DB_DRIVER_TO_SYSTEM [$ engine ] ?? 'other_sql ' ;
214- $ tags [Tag::DB_SYSTEM ] = $ dbSystem ;
215- $ tags [Tag::DB_TYPE ] = $ dbSystem ; // db.type is DD equivalent to db.system in OpenTelemetry, used for SQL spans obfuscation
216- $ valStrings = explode ('; ' , substr ($ dsn , strlen ($ engine ) + 1 ));
217- foreach ($ valStrings as $ valString ) {
218- if (!strpos ($ valString , '= ' )) {
219- continue ;
228+ if (\preg_match (self ::DSN_REGEX , $ dsn , $ m )) {
229+ $ engine = $ m ['engine ' ]; // If uri: is used we'll also land here, but it's deprecated and we don't support it
230+ $ db = $ m ['db ' ] ?? "" ;
231+ $ charset = $ m ['charset ' ] ?? "" ;
232+ $ host = $ m ['host ' ] ?? "" ;
233+ $ port = $ m ['port ' ] ?? "" ;
234+ $ driver = $ m ['driver ' ] ?? "" ;
235+
236+ $ dbSystem = self ::DB_DRIVER_TO_SYSTEM [$ engine ] ?? 'other_sql ' ;
237+ $ tags = ['db.engine ' => $ engine ];
238+ $ tags [Tag::DB_SYSTEM ] = $ dbSystem ;
239+ $ tags [Tag::DB_TYPE ] = $ dbSystem ; // db.type is DD equivalent to db.system in OpenTelemetry, used for SQL spans obfuscation
240+
241+ if ($ db !== "" ) {
242+ $ tags [Tag::DB_NAME ] = $ db ;
243+ }
244+ if ($ charset !== "" ) {
245+ $ tags [Tag::DB_CHARSET ] = $ charset ;
246+ }
247+ if ($ host !== "" ) {
248+ $ tags [Tag::TARGET_HOST ] = $ host ;
249+ }
250+ if ($ port !== "" ) {
251+ $ tags [Tag::TARGET_PORT ] = $ port ;
220252 }
221- list ($ key , $ value ) = explode ('= ' , $ valString );
222- switch (strtolower ($ key )) {
223- case 'charset ' :
224- $ tags [Tag::DB_CHARSET ] = $ value ;
225- break ;
226- case 'database ' :
227- case 'dbname ' :
228- $ tags [Tag::DB_NAME ] = $ value ;
229- break ;
230- case 'server ' :
231- case 'unix_socket ' :
232- case 'hostname ' :
233- case 'host ' :
234- $ tags [Tag::TARGET_HOST ] = $ value ;
235- break ;
236- case 'port ' :
237- $ tags [Tag::TARGET_PORT ] = $ value ;
238- break ;
239- case 'driver ' :
240- // This is more specific than just "odbc"
241- $ tags [Tag::DB_SYSTEM ] = strtolower ($ value );
242- break ;
253+ if ($ driver !== "" ) {
254+ $ tags [Tag::DB_SYSTEM ] = strtolower ($ driver );
243255 }
256+ } elseif ($ iniDsn = ini_get ("pdo.dsn. $ dsn " )) {
257+ $ tags = self ::parseDsn ($ iniDsn );
258+ } else {
259+ // If we cannot find the ini
260+ $ tags = [
261+ Tag::DB_SYSTEM => 'other_sql ' ,
262+ Tag::DB_TYPE => 'other_sql ' ,
263+ ];
244264 }
245-
246265 return $ tags ;
247266 }
248267
@@ -299,10 +318,6 @@ public static function setCommonSpanInfo($source, SpanData $span)
299318 foreach ($ storedConnectionInfo as $ tag => $ value ) {
300319 $ span ->meta [$ tag ] = $ value ;
301320 }
302-
303- if (\dd_trace_env_config ("DD_APPSEC_RASP_ENABLED " ) && function_exists ('datadog\appsec\push_addresses ' )
304- && !empty ($ span ->resource ) && !empty ($ storedConnectionInfo [Tag::DB_SYSTEM ])) {
305- }
306321 }
307322
308323 /**
0 commit comments