Skip to content

Commit 21e1a31

Browse files
authored
Optimize PDOIntegration::parseDsn() (#3430)
* Optimize PDOIntegration::parseDsn() * Support INI dsn * Multiline DSN, adjust comment
1 parent 990fa3a commit 21e1a31

File tree

1 file changed

+51
-36
lines changed

1 file changed

+51
-36
lines changed

src/DDTrace/Integrations/PDO/PDOIntegration.php

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)