in agent/php/ElasticApm/Impl/AutoInstrument/MySQLiAutoInstrumentation.php [123:258]
private function interceptMySQLiConstructConnect(RegistrationContextInterface $ctx): void
{
/**
* @param ?string $className
* @param string $funcName
* @param ?object $interceptedCallThis
* @param array $interceptedCallArgs
*
* @return null|callable(int, bool, mixed): void
*/
$preHook = function (
?string $className,
string $funcName,
?object $interceptedCallThis,
array $interceptedCallArgs
): ?callable {
// function mysqli_connect(
// $host = null, // <- $interceptedCallArgs[0]
// $username = null, // <- $interceptedCallArgs[1]
// $password = null, // <- $interceptedCallArgs[2]
// $database = null, // <- $interceptedCallArgs[3]
// $port = null, // <- $interceptedCallArgs[4]
// $socket = null // <- $interceptedCallArgs[5]
// );
//
// public function __construct (
// $host = null, // <- $interceptedCallArgs[0]
// $username = null, // <- $interceptedCallArgs[1]
// $passwd = null, // <- $interceptedCallArgs[2]
// $database = null, // <- $interceptedCallArgs[3]
// $port = null, // <- $interceptedCallArgs[4]
// $socket = null // <- $interceptedCallArgs[5]
// );
/** @var ?mysqli $mysqliObj */
$mysqliObj = null;
if ($interceptedCallThis !== null) {
if (!$this->util->verifyInstanceOf(mysqli::class, $interceptedCallThis)) {
return null;
}
/** @var mysqli $interceptedCallThis */
$mysqliObj = $interceptedCallThis;
}
/** @var ?string $dbName */
$dbName = null;
if (count($interceptedCallArgs) >= 4) {
$fourthArg = $interceptedCallArgs[3];
if ($fourthArg !== null) {
if (is_string($fourthArg)) {
$dbName = $fourthArg;
} else {
($loggerProxy = $this->logger->ifErrorLevelEnabled(__LINE__, __FUNCTION__))
&& $loggerProxy->log(
'Expected 4th argument to be database name but it is not a string.',
[
'className' => $className,
'funcName' => $funcName,
'4th argument type' => DbgUtil::getType($fourthArg),
'4th argument' => $this->logger->possiblySecuritySensitive($fourthArg),
'interceptedCallArgs' => $this->logger->possiblySecuritySensitive($interceptedCallArgs),
]
);
}
}
}
return AutoInstrumentationUtil::createInternalFuncPostHookFromEndSpan(
self::beginSpan($className, $funcName, $dbName, /* statement: */ null),
/**
* doBeforeSpanEnd
*
* @param bool $hasExitedByException
* @param mixed $returnValueOrThrown
*/
function (bool $hasExitedByException, $returnValueOrThrown) use ($mysqliObj, $dbName): void {
if ($hasExitedByException) {
return;
}
if ($mysqliObj == null) {
if (!$this->util->verifyInstanceOf(mysqli::class, $returnValueOrThrown)) {
return;
}
/** @var mysqli $returnValueOrThrown */
$mysqliObj = $returnValueOrThrown;
}
$this->mapPerObject->set(
$mysqliObj,
DbAutoInstrumentationUtil::PER_OBJECT_KEY_DB_NAME,
$dbName
);
}
);
};
$funcName = 'mysqli_connect';
$ctx->interceptCallsToInternalFunction(
$funcName,
/**
* @param mixed[] $interceptedCallArgs
*
* @return null|callable(int, bool, mixed): mixed
*/
function (array $interceptedCallArgs) use ($preHook, $funcName): ?callable {
return $preHook(
null /* <- className */,
$funcName,
null /* <- interceptedCallThis */,
$interceptedCallArgs
);
}
);
$className = self::MYSQLI_CLASS_NAME;
$methodName = '__construct';
$ctx->interceptCallsToInternalMethod(
$className,
$methodName,
function (
?object $interceptedCallThis,
array $interceptedCallArgs
) use (
$preHook,
$className,
$methodName
): ?callable {
return $preHook(
$className,
$methodName,
$interceptedCallThis,
$interceptedCallArgs
);
}
);
}