Skip to content

Commit

Permalink
feat: track dbname and other pdo attributes (#278)
Browse files Browse the repository at this point in the history
  • Loading branch information
cedricziel authored Jul 9, 2024
1 parent 0390c2f commit 5eee996
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 9 deletions.
4 changes: 3 additions & 1 deletion src/PDOInstrumentation.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ public static function register(): void
}
$span = Span::fromContext($scope->context());

$attributes = $pdoTracker->trackPdoAttributes($pdo);
$dsn = $params[0] ?? '';

$attributes = $pdoTracker->trackPdoAttributes($pdo, $dsn);
$span->setAttributes($attributes);

self::end($exception);
Expand Down
68 changes: 63 additions & 5 deletions src/PDOTracker.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,25 +59,34 @@ public function trackedAttributesForStatement(PDOStatement $statement): iterable

/**
* @param PDO $pdo
* @param string $dsn
* @return iterable<non-empty-string, bool|int|float|string|array|null>
*/
public function trackPdoAttributes(PDO $pdo): iterable
public function trackPdoAttributes(PDO $pdo, string $dsn): iterable
{
$attributes = [];
$attributes = self::extractAttributesFromDSN($dsn);

try {
/** @var string $dbSystem */
$dbSystem = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
/** @psalm-suppress PossiblyInvalidArgument */
/** @psalm-suppress InvalidArrayAssignment */
$attributes[TraceAttributes::DB_SYSTEM] = self::mapDriverNameToAttribute($dbSystem);
} catch (\Error) {
// if we catched an exception, the driver is likely not supporting the operation, default to "other"
/** @psalm-suppress PossiblyInvalidArrayAssignment */
$attributes[TraceAttributes::DB_SYSTEM] = 'other_sql';
}

return $this->pdoToAttributesMap[$pdo] = $attributes;
$this->pdoToAttributesMap[$pdo] = $attributes;

return $attributes;
}

public function trackedAttributesForPdo(PDO $pdo)
/**
* @param PDO $pdo
* @return iterable<non-empty-string, bool|int|float|string|array|null>
*/
public function trackedAttributesForPdo(PDO $pdo): iterable
{
return $this->pdoToAttributesMap[$pdo] ?? [];
}
Expand Down Expand Up @@ -106,4 +115,53 @@ private static function mapDriverNameToAttribute(?string $driverName): string
default => 'other_sql',
};
}

/**
* Extracts attributes from a DSN string
*
* @param string $dsn
* @return iterable<non-empty-string, bool|int|float|string|array|null>
*/
private static function extractAttributesFromDSN(string $dsn): iterable
{
$attributes = [];
if (str_starts_with($dsn, 'sqlite::memory:')) {
$attributes[TraceAttributes::DB_SYSTEM] = 'sqlite';
$attributes[TraceAttributes::DB_NAME] = 'memory';

return $attributes;
} elseif (str_starts_with($dsn, 'sqlite:')) {
$attributes[TraceAttributes::DB_SYSTEM] = 'sqlite';
$attributes[TraceAttributes::DB_NAME] = substr($dsn, 7);

return $attributes;
} elseif (str_starts_with($dsn, 'sqlite')) {
$attributes[TraceAttributes::DB_SYSTEM] = 'sqlite';
$attributes[TraceAttributes::DB_NAME] = $dsn;

return $attributes;
}

if (preg_match('/user=([^;]*)/', $dsn, $matches)) {
$user = $matches[1];
if ($user !== '') {
$attributes[TraceAttributes::DB_USER] = $user;
}
}
if (preg_match('/host=([^;]*)/', $dsn, $matches)) {
$host = $matches[1];
if ($host !== '') {
$attributes[TraceAttributes::NET_PEER_NAME] = $host;
$attributes[TraceAttributes::SERVER_ADDRESS] = $host;
}
}
if (preg_match('/dbname=([^;]*)/', $dsn, $matches)) {
$dbname = $matches[1];
if ($dbname !== '') {
$attributes[TraceAttributes::DB_NAME] = $dbname;
}
}

return $attributes;
}
}
12 changes: 9 additions & 3 deletions tests/Unit/PDOAttributeTrackerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,22 @@

class PDOAttributeTrackerTest extends TestCase
{
public function testPdoCanBeTracked()
public function testPdoCanBeTracked(): void
{
$pdo = new \PDO('sqlite::memory:');
$dsn = 'sqlite::memory:';
$pdo = new \PDO($dsn);

$objectMap = new PDOTracker();
$objectMap->trackPdoAttributes($pdo);
$objectMap->trackPdoAttributes($pdo, $dsn);
$attributes = $objectMap->trackedAttributesForPdo($pdo);
$span = Span::getInvalid();

/** @psalm-suppress InvalidArgument */
$this->assertContains(TraceAttributes::DB_SYSTEM, array_keys($attributes));
/** @psalm-suppress InvalidArgument */
$this->assertContains(TraceAttributes::DB_NAME, array_keys($attributes));
/** @psalm-suppress InvalidArrayAccess */
$this->assertSame('memory', $attributes[TraceAttributes::DB_NAME]);

$stmt = $pdo->prepare('SELECT NULL LIMIT 0;');
$objectMap->trackStatement($stmt, $pdo, $span->getContext());
Expand Down

0 comments on commit 5eee996

Please sign in to comment.