Skip to content

Commit

Permalink
Added support for returning query executed from PDOStatement->execute()
Browse files Browse the repository at this point in the history
  • Loading branch information
asgrim committed Oct 31, 2019
1 parent fbd7d4e commit 17cc779
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 19 deletions.
9 changes: 8 additions & 1 deletion CMakeLists.txt
@@ -1,7 +1,14 @@
cmake_minimum_required(VERSION 3.9)
project(scoutapm C)

set(SOURCE_FILES zend_scoutapm.c scout_curl_wrapper.c scout_file_wrapper.c scout_extern.h zend_scoutapm.h)
set(SOURCE_FILES
zend_scoutapm.c
scout_curl_wrapper.c
scout_file_wrapper.c
scout_pdo_wrapper.c
scout_extern.h
zend_scoutapm.h
)

execute_process(
COMMAND php-config --include-dir
Expand Down
3 changes: 1 addition & 2 deletions config.m4
Expand Up @@ -57,8 +57,7 @@ if test "$PHP_SCOUTAPM" != "no"; then

PHP_SCOUTAPM_CFLAGS="$STD_CFLAGS $MAINTAINER_CFLAGS"

PHP_NEW_EXTENSION(scoutapm,
zend_scoutapm.c scout_curl_wrapper.c scout_file_wrapper.c,
PHP_NEW_EXTENSION(scoutapm, zend_scoutapm.c scout_curl_wrapper.c scout_file_wrapper.c scout_pdo_wrapper.c,
$ext_shared,,$PHP_SCOUTAPM_CFLAGS,,yes)
fi

Expand Down
3 changes: 2 additions & 1 deletion package.xml
Expand Up @@ -48,6 +48,7 @@
<file name="zend_scoutapm.c" role="src" />
<file name="scout_curl_wrapper.c" role="src" />
<file name="scout_file_wrapper.c" role="src" />
<file name="scout_pdo_wrapper.c" role="src" />
<file name="scout_extern.h" role="src" />
<file name="zend_scoutapm.h" role="src" />
<file name="README.md" role="doc" />
Expand All @@ -69,7 +70,7 @@
<file name="010-fwrite-fread-tmpfile.phpt" role="test" />
<file name="011-pdo-exec.phpt" role="test" />
<file name="011-pdo-query.phpt" role="test" />
<file name="011-pdostatement-execute.phpt" role="test" />
<file name="011-pdostatement-execute-pdo-prepare.phpt" role="test" />
<file name="012-file_put_contents.phpt" role="test" />
<file name="013-fix-memory-leak-when-scoutapm_get_calls-not-called.phpt" role="test" />
</dir>
Expand Down
64 changes: 64 additions & 0 deletions scout_pdo_wrapper.c
@@ -0,0 +1,64 @@
/*
* Scout APM extension for PHP
*
* Copyright (C) 2019-
* For license information, please see the LICENSE file.
*/

#include "zend_scoutapm.h"
#include "scout_extern.h"

const char *unique_pdo_statement_id(zval *pdo_statement_instance)
{
// @todo make unique...
return "pdo";
}

ZEND_NAMED_FUNCTION(scoutapm_pdo_prepare_handler)
{
zval *statement;

ZEND_PARSE_PARAMETERS_START(1, 10)
Z_PARAM_ZVAL(statement)
ZEND_PARSE_PARAMETERS_END();

SCOUT_INTERNAL_FUNCTION_PASSTHRU();

record_arguments_for_call(unique_pdo_statement_id(return_value), 1, statement);
}

ZEND_NAMED_FUNCTION(scoutapm_pdostatement_execute_handler)
{
int handler_index;
double entered = scoutapm_microtime();
const char *called_function;
zend_long recorded_arguments_index;

called_function = determine_function_name(execute_data);

handler_index = handler_index_for_function(called_function);

/* Practically speaking, this shouldn't happen as long as we defined the handlers properly */
if (handler_index < 0) {
zend_throw_exception(NULL, "ScoutAPM overwrote a handler for a function it didn't define a handler for", 0);
return;
}

recorded_arguments_index = find_index_for_recorded_arguments(unique_pdo_statement_id(getThis()));

if (recorded_arguments_index < 0) {
scoutapm_default_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
return;
}

// @todo segfault happens here if handler_index too high - https://github.com/scoutapp/scout-apm-php-ext/issues/41
original_handlers[handler_index](INTERNAL_FUNCTION_PARAM_PASSTHRU);

record_observed_stack_frame(
called_function,
entered,
scoutapm_microtime(),
SCOUTAPM_G(disconnected_call_argument_store)[recorded_arguments_index].argc,
SCOUTAPM_G(disconnected_call_argument_store)[recorded_arguments_index].argv
);
}
2 changes: 1 addition & 1 deletion tests/010-fwrite-fread-fopen.phpt
@@ -1,5 +1,5 @@
--TEST--
Calls to fwrite and fread are logged
Calls to fwrite and fread are logged with handle from fopen()
--SKIPIF--
<?php if (!extension_loaded("scoutapm")) die("skip scoutapm extension required."); ?>
--FILE--
Expand Down
2 changes: 1 addition & 1 deletion tests/010-fwrite-fread-tmpfile.phpt
@@ -1,5 +1,5 @@
--TEST--
Calls to fwrite and fread are logged
Calls to fwrite and fread are logged with handle from tmpfile()
--SKIPIF--
<?php if (!extension_loaded("scoutapm")) die("skip scoutapm extension required."); ?>
--FILE--
Expand Down
@@ -1,5 +1,5 @@
--TEST--
Calls to PDOStatement::execute are logged
Calls to PDOStatement::execute are logged when created from PDO->prepare()
--SKIPIF--
<?php if (!extension_loaded("scoutapm")) die("skip scoutapm extension required."); ?>
<?php if (!extension_loaded("PDO")) die("skip PDO extension required."); ?>
Expand All @@ -13,10 +13,15 @@ var_dump($stmt->fetch(PDO::FETCH_ASSOC));

$calls = scoutapm_get_calls();
var_dump($calls[0]['function']);
var_dump($calls[0]['argv']);
?>
--EXPECTF--
array(1) {
["1 + 2"]=>
string(1) "3"
}
string(21) "PDOStatement->execute"
array(1) {
[0]=>
string(%d) "SELECT 1 + 2"
}
28 changes: 16 additions & 12 deletions zend_scoutapm.c
Expand Up @@ -24,23 +24,26 @@ extern ZEND_NAMED_FUNCTION(scoutapm_curl_exec_handler);
extern ZEND_NAMED_FUNCTION(scoutapm_fopen_handler);
extern ZEND_NAMED_FUNCTION(scoutapm_fread_handler);
extern ZEND_NAMED_FUNCTION(scoutapm_fwrite_handler);
extern ZEND_NAMED_FUNCTION(scoutapm_pdo_prepare_handler);
extern ZEND_NAMED_FUNCTION(scoutapm_pdostatement_execute_handler);

/* This is simply a map of function names to an index in original_handlers */
indexed_handler_lookup handler_lookup[] = {
/* define each function we want to overload, which maps to an index in the `original_handlers` array */
{0, "file_get_contents"},
{1, "file_put_contents"},
{2, "curl_setopt"},
{3, "curl_exec"},
{4, "fopen"},
{5, "fread"},
{6, "fwrite"},
{7, "pdo->exec"},
{8, "pdo->query"},
{9, "pdostatement->execute"},
{ 0, "file_get_contents"},
{ 1, "file_put_contents"},
{ 2, "curl_setopt"},
{ 3, "curl_exec"},
{ 4, "fopen"},
{ 5, "fread"},
{ 6, "fwrite"},
{ 7, "pdo->exec"},
{ 8, "pdo->query"},
{ 9, "pdo->prepare"},
{10, "pdostatement->execute"},
};
/* handlers count needs to be the number of handler lookups defined above. */
zif_handler original_handlers[10];
zif_handler original_handlers[11];

ZEND_DECLARE_MODULE_GLOBALS(scoutapm)

Expand Down Expand Up @@ -173,7 +176,8 @@ static PHP_RINIT_FUNCTION(scoutapm)
SCOUT_OVERLOAD_FUNCTION("fread", scoutapm_fread_handler)
SCOUT_OVERLOAD_METHOD("pdo", "exec", scoutapm_default_handler)
SCOUT_OVERLOAD_METHOD("pdo", "query", scoutapm_default_handler)
SCOUT_OVERLOAD_METHOD("pdostatement", "execute", scoutapm_default_handler) // @todo better argument handling
SCOUT_OVERLOAD_METHOD("pdo", "prepare", scoutapm_pdo_prepare_handler)
SCOUT_OVERLOAD_METHOD("pdostatement", "execute", scoutapm_pdostatement_execute_handler)

SCOUTAPM_G(handlers_set) = 1;
} else {
Expand Down

0 comments on commit 17cc779

Please sign in to comment.