diff --git a/ext/hook/uhook.stub.php b/ext/hook/uhook.stub.php index 39c8850775..a7143d52eb 100644 --- a/ext/hook/uhook.stub.php +++ b/ext/hook/uhook.stub.php @@ -2,157 +2,158 @@ /** @generate-class-entries */ -namespace DDTrace; +namespace DDTrace { + + class HookData { + /** + * Arbitrary data to be passed from a begin-hook to an end-hook + */ + public mixed $data; + + /** + * The hook id, which triggered that particular hook + */ + public int $id; + + /** + * A zero-indexed array of all arguments. + * On file inclusions, this will be an array with a single element containing the filename. + */ + public array $args; + + /** + * The returned value. This may be a reference, if the value was returned by reference. + * Uninitialized in a begin hook. + */ + public mixed $returned; + + /** + * The possible thrown exception within that function. + * Uninitialized in a begin hook. + */ + public ?\Throwable $exception; + + /** + * Creates a span if none exists yet, otherwise returns the span attached to the current function call. + * If called outside the pre-hook and no span is attached yet, it will return an empty span object. + * + * @param SpanStack|SpanData|null $parent May be specified to start a span on a specific stack. + * As an example, when instrumenting closures, it might conceptually make + * sense to attach the Closure to the current executing function instead of + * where it ends up called. In that case the initial call to span() needs to + * provide the proper stack. + * @return SpanData The new or existing span. + */ + public function span(SpanStack|SpanData|null $parent = null): SpanData {} + + /** + * Works similarly to self::spqn(), but always pushes the span onto the active span stack, even if running in + * limited mode. + * + * @param SpanStack|SpanData|null $parent See self::span(). + * @return SpanData The new or existing span. + */ + public function unlimitedSpan(SpanStack|SpanData|null $parent = null): SpanData {} + + /** + * Replaces the arguments of a function call. Must be called within a pre-hook. + * It is not allowed to pass more arguments to a function that currently on the stack or total number or arguments, + * whichever is greater. + * + * @param array $arguments An array of arguments, which will replace the hooked functions arguments. + * @return bool 'true' on success, otherwise 'false' + */ + public function overrideArguments(array $arguments): bool {} + + /** + * Replaces the return value of a function call. Must be called within a post-hook. + * Note that the return value is not checked. + * + * @prefer-ref $value + * @param mixed $value A value which will replace the original return value. + * @return bool 'true' on success, otherwise 'false' + */ + public function overrideReturnValue(mixed $value): bool {} + + /** + * Replaces the exception thrown by a function call. Must be called within a post-hook. + * + * @param \Throwable|null $exception An exception which will replace the original exception. + * @return bool 'true' on success, otherwise 'false' + */ + public function overrideException(\Throwable|null $exception): bool {} + + /** + * Disables inlining of this method. + * @return bool true iif we have a user function + */ + public function disableJitInlining(): bool {} + + /** + * Suppresses the call to the hooked function. Must be called within a pre-hook. + * The method disableJitInlining() should be called unconditionally in hooks using this method. + * @return bool always 'true' + */ + public function suppressCall(): bool {} + + /** + * By default, hooks are not called if the hooked function is called from the hook. + * This method can be used to override this behavior. The next recursive call will trigger the hook. + * @return bool 'true' if called from the hook, which should always be the case + */ + public function allowNestedHook(): bool {} + + /** + * The name of the file where the function/method call was made from. + * + * @return string The file name, or an empty string if the file name is not available. + */ + public function getSourceFile(): string {} + } -class HookData { /** - * Arbitrary data to be passed from a begin-hook to an end-hook + * @var string */ - public mixed $data; + const HOOK_ALL_FILES = ""; /** - * The hook id, which triggered that particular hook - */ - public int $id; - - /** - * A zero-indexed array of all arguments. - * On file inclusions, this will be an array with a single element containing the filename. - */ - public array $args; - - /** - * The returned value. This may be a reference, if the value was returned by reference. - * Uninitialized in a begin hook. - */ - public mixed $returned; - - /** - * The possible thrown exception within that function. - * Uninitialized in a begin hook. - */ - public ?\Throwable $exception; - - /** - * Creates a span if none exists yet, otherwise returns the span attached to the current function call. - * If called outside the pre-hook and no span is attached yet, it will return an empty span object. + * Only hooks the specific instance of the Closure, i.e. independent instantiations of the same Closure are not hooked. * - * @param SpanStack|SpanData|null $parent May be specified to start a span on a specific stack. - * As an example, when instrumenting closures, it might conceptually make - * sense to attach the Closure to the current executing function instead of - * where it ends up called. In that case the initial call to span() needs to - * provide the proper stack. - * @return SpanData The new or existing span. + * @var int + * @cvalue HOOK_INSTANCE */ - public function span(SpanStack|SpanData|null $parent = null): SpanData; + const HOOK_INSTANCE = UNKNOWN; /** - * Works similarly to self::spqn(), but always pushes the span onto the active span stack, even if running in - * limited mode. - * - * @param SpanStack|SpanData|null $parent See self::span(). - * @return SpanData The new or existing span. + * @param string|\Closure|\Generator $target The function to hook. + * If a string is passed, it must be either a function name or referencing + * a method in "Classname::methodname" format. Alternatively it may be a file + * name or the DDTrace\HOOK_ALL_FILES constant. Can be a relative path + * starting with ./ or ../ too. + * If a Closure is passed, the hook only applies to the current instance + * of that Closure. + * If a Generator is passed, the active function name or Closure is extracted + * and the hook applied to that. + * @param null|\Closure(\DDTrace\HookData) $begin Called before the hooked function is invoked. + * @param null|\Closure(\DDTrace\HookData) $end Called after the hooked function is invoked. + * @param int $flags The only accepted flag currently is DDTrace\HOOK_INSTANCE. + * @return int An integer which can be used to remove a hook via DDTrace\remove_hook. */ - public function unlimitedSpan(SpanStack|SpanData|null $parent = null): SpanData; + function install_hook( + string|callable|\Closure|\Generator $target, + ?\Closure $begin = null, + ?\Closure $end = null, + int $flags = 0 + ): int {} /** - * Replaces the arguments of a function call. Must be called within a pre-hook. - * It is not allowed to pass more arguments to a function that currently on the stack or total number or arguments, - * whichever is greater. + * Removes an installed hook by its id, as returned by install_hook or HookData->id. * - * @param array $arguments An array of arguments, which will replace the hooked functions arguments. - * @return bool 'true' on success, otherwise 'false' + * @param int $id The id to remove. + * @param string $location A class name (which inherits this hook through inheritance), which to specifically remove + * this hook from. + * @return void no return, not formally declared void because of a buggy debug assertion in PHP 7.1 + * ("return value must be of type void, null returned") */ - public function overrideArguments(array $arguments): bool; - - /** - * Replaces the return value of a function call. Must be called within a post-hook. - * Note that the return value is not checked. - * - * @prefer-ref $value - * @param mixed $value A value which will replace the original return value. - * @return bool 'true' on success, otherwise 'false' - */ - public function overrideReturnValue(mixed $value): bool; - - /** - * Replaces the exception thrown by a function call. Must be called within a post-hook. - * - * @param \Throwable|null $exception An exception which will replace the original exception. - * @return bool 'true' on success, otherwise 'false' - */ - public function overrideException(\Throwable|null $exception): bool; - - /** - * Disables inlining of this method. - * @return bool true iif we have a user function - */ - public function disableJitInlining(): bool; - - /** - * Suppresses the call to the hooked function. Must be called within a pre-hook. - * The method disableJitInlining() should be called unconditionally in hooks using this method. - * @return bool always 'true' - */ - public function suppressCall(): bool; - - /** - * By default, hooks are not called if the hooked function is called from the hook. - * This method can be used to override this behavior. The next recursive call will trigger the hook. - * @return bool 'true' if called from the hook, which should always be the case - */ - public function allowNestedHook(): bool; - - /** - * The name of the file where the function/method call was made from. - * - * @return string The file name, or an empty string if the file name is not available. - */ - public function getSourceFile(): string; + function remove_hook(int $id, string $location = "") {} } - -/** - * @var string - */ -const HOOK_ALL_FILES = ""; - -/** - * Only hooks the specific instance of the Closure, i.e. independent instantiations of the same Closure are not hooked. - * - * @var int - * @cvalue HOOK_INSTANCE - */ -const HOOK_INSTANCE = UNKNOWN; - -/** - * @param string|\Closure|\Generator $target The function to hook. - * If a string is passed, it must be either a function name or referencing - * a method in "Classname::methodname" format. Alternatively it may be a file - * name or the DDTrace\HOOK_ALL_FILES constant. Can be a relative path - * starting with ./ or ../ too. - * If a Closure is passed, the hook only applies to the current instance - * of that Closure. - * If a Generator is passed, the active function name or Closure is extracted - * and the hook applied to that. - * @param null|\Closure(\DDTrace\HookData) $begin Called before the hooked function is invoked. - * @param null|\Closure(\DDTrace\HookData) $end Called after the hooked function is invoked. - * @param int $flags The only accepted flag currently is DDTrace\HOOK_INSTANCE. - * @return int An integer which can be used to remove a hook via DDTrace\remove_hook. - */ -function install_hook( - string|callable|\Closure|\Generator $target, - ?\Closure $begin = null, - ?\Closure $end = null, - int $flags = 0 -): int {} - -/** - * Removes an installed hook by its id, as returned by install_hook or HookData->id. - * - * @param int $id The id to remove. - * @param string $location A class name (which inherits this hook through inheritance), which to specifically remove - * this hook from. - * @return void no return, not formally declared void because of a buggy debug assertion in PHP 7.1 - * ("return value must be of type void, null returned") - */ -function remove_hook(int $id, string $location = "") {} diff --git a/ext/hook/uhook_arginfo.h b/ext/hook/uhook_arginfo.h index 13b73c1e73..e0af7e161e 100644 --- a/ext/hook/uhook_arginfo.h +++ b/ext/hook/uhook_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: eccfac3f3ffe92ae1390f729e053a3e161bdab4b */ + * Stub hash: 4b2f667462bc9e7bed94b2c9a479b85f3086b521 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_DDTrace_install_hook, 0, 1, IS_LONG, 0) ZEND_ARG_OBJ_TYPE_MASK(0, target, Closure|Generator, MAY_BE_STRING|MAY_BE_CALLABLE, NULL) @@ -41,7 +41,6 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_DDTrace_HookData_getSourceFile, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() - ZEND_FUNCTION(DDTrace_install_hook); ZEND_FUNCTION(DDTrace_remove_hook); ZEND_METHOD(DDTrace_HookData, span); @@ -54,14 +53,12 @@ ZEND_METHOD(DDTrace_HookData, suppressCall); ZEND_METHOD(DDTrace_HookData, allowNestedHook); ZEND_METHOD(DDTrace_HookData, getSourceFile); - static const zend_function_entry ext_functions[] = { - ZEND_NS_FALIAS("DDTrace", install_hook, DDTrace_install_hook, arginfo_DDTrace_install_hook) - ZEND_NS_FALIAS("DDTrace", remove_hook, DDTrace_remove_hook, arginfo_DDTrace_remove_hook) + ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace", "install_hook"), zif_DDTrace_install_hook, arginfo_DDTrace_install_hook, 0, NULL, NULL) + ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace", "remove_hook"), zif_DDTrace_remove_hook, arginfo_DDTrace_remove_hook, 0, NULL, NULL) ZEND_FE_END }; - static const zend_function_entry class_DDTrace_HookData_methods[] = { ZEND_ME(DDTrace_HookData, span, arginfo_class_DDTrace_HookData_span, ZEND_ACC_PUBLIC) ZEND_ME(DDTrace_HookData, unlimitedSpan, arginfo_class_DDTrace_HookData_unlimitedSpan, ZEND_ACC_PUBLIC) diff --git a/ext/hook/uhook_attributes.stub.php b/ext/hook/uhook_attributes.stub.php index 9259ef2e14..e8e699acbf 100644 --- a/ext/hook/uhook_attributes.stub.php +++ b/ext/hook/uhook_attributes.stub.php @@ -2,40 +2,41 @@ /** @generate-class-entries */ -namespace DDTrace; +namespace DDTrace { -require "Zend/zend_attributes.stub.php"; + require "Zend/zend_attributes.stub.php"; -// phpcs:disable Squiz.Functions.MultiLineFunctionDeclaration.Indent + // phpcs:disable Squiz.Functions.MultiLineFunctionDeclaration.Indent -/** - * If specified, this attribute ensures that all calls to that function are traced. - */ -#[\Attribute(\Attribute::TARGET_FUNCTION | \Attribute::TARGET_METHOD)] -final class Trace { /** - * @param string $name The operation name to be assigned to the span. Defaults to the function name. - * @param string $resource The resource to be assigned to the span. - * @param string $type The type to be assigned to the span. - * @param string $service The service to be assigned to the span. Defaults to default or inherited service name. - * @param array $tags The tags to be assigned to the span. - * @param bool|array $saveArgs Whether arguments shall be saved as tags on the span. True to save them all. - False to save none. An array with parameter names to save only select ones. - * @param bool $saveReturn Whether to save return values (including yielded values on generators) on the span. - * @param bool $recurse Whether recursive calls shall be traced. - * @param bool $run_if_limited Whether the function shall be traced in limited mode. (E.g. when span limit exceeded) + * If specified, this attribute ensures that all calls to that function are traced. */ - public function __construct( - string $name = "", - string $resource = "", - string $type = "", - string $service = "", - array $tags = [], -/* disable for now, until final decision on the API is taken - bool|array $saveArgs = false, - bool $saveReturn = false, -*/ - bool $recurse = true, - bool $run_if_limited = false - ) {} + #[\Attribute(\Attribute::TARGET_FUNCTION | \Attribute::TARGET_METHOD)] + final class Trace { + /** + * @param string $name The operation name to be assigned to the span. Defaults to the function name. + * @param string $resource The resource to be assigned to the span. + * @param string $type The type to be assigned to the span. + * @param string $service The service to be assigned to the span. Defaults to default or inherited service name. + * @param array $tags The tags to be assigned to the span. + * @param bool|array $saveArgs Whether arguments shall be saved as tags on the span. True to save them all. + * False to save none. An array with parameter names to save only select ones. + * @param bool $saveReturn Whether to save return values (including yielded values on generators) on the span. + * @param bool $recurse Whether recursive calls shall be traced. + * @param bool $run_if_limited Whether the function shall be traced in limited mode. (E.g. when span limit exceeded) + */ + public function __construct( + string $name = "", + string $resource = "", + string $type = "", + string $service = "", + array $tags = [], + /* disable for now, until final decision on the API is taken + bool|array $saveArgs = false, + bool $saveReturn = false, + */ + bool $recurse = true, + bool $run_if_limited = false + ) {} + } } diff --git a/ext/hook/uhook_attributes_arginfo.h b/ext/hook/uhook_attributes_arginfo.h index 8d1410faa2..4c64d765a8 100644 --- a/ext/hook/uhook_attributes_arginfo.h +++ b/ext/hook/uhook_attributes_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 6e695ec08c44692b1b361afd99a4521067cfb6de */ + * Stub hash: 90919c9c350e86acd6fe3c8d06753918d5e0572b */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DDTrace_Trace___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, name, IS_STRING, 0, "\"\"") @@ -11,10 +11,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DDTrace_Trace___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, run_if_limited, _IS_BOOL, 0, "false") ZEND_END_ARG_INFO() - ZEND_METHOD(DDTrace_Trace, __construct); - static const zend_function_entry class_DDTrace_Trace_methods[] = { ZEND_ME(DDTrace_Trace, __construct, arginfo_class_DDTrace_Trace___construct, ZEND_ACC_PUBLIC) ZEND_FE_END @@ -28,12 +26,12 @@ static zend_class_entry *register_class_DDTrace_Trace(void) class_entry = zend_register_internal_class_ex(&ce, NULL); class_entry->ce_flags |= ZEND_ACC_FINAL; - zend_string *attribute_name_Attribute_class_DDTrace_Trace = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); - zend_attribute *attribute_Attribute_class_DDTrace_Trace = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_DDTrace_Trace, 1); - zend_string_release(attribute_name_Attribute_class_DDTrace_Trace); - zval attribute_Attribute_class_DDTrace_Trace_arg0; - ZVAL_LONG(&attribute_Attribute_class_DDTrace_Trace_arg0, ZEND_ATTRIBUTE_TARGET_FUNCTION | ZEND_ATTRIBUTE_TARGET_METHOD); - ZVAL_COPY_VALUE(&attribute_Attribute_class_DDTrace_Trace->args[0].value, &attribute_Attribute_class_DDTrace_Trace_arg0); + zend_string *attribute_name_Attribute_class_DDTrace_Trace_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_DDTrace_Trace_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_DDTrace_Trace_0, 1); + zend_string_release(attribute_name_Attribute_class_DDTrace_Trace_0); + zval attribute_Attribute_class_DDTrace_Trace_0_arg0; + ZVAL_LONG(&attribute_Attribute_class_DDTrace_Trace_0_arg0, ZEND_ATTRIBUTE_TARGET_FUNCTION | ZEND_ATTRIBUTE_TARGET_METHOD); + ZVAL_COPY_VALUE(&attribute_Attribute_class_DDTrace_Trace_0->args[0].value, &attribute_Attribute_class_DDTrace_Trace_0_arg0); return class_entry; }