Skip to content

PHPC-1076: Expose result document for failed commands via CommandFailedEvent #840

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions php_phongo.c
Original file line number Diff line number Diff line change
Expand Up @@ -2220,11 +2220,13 @@ static void php_phongo_command_failed(const mongoc_apm_command_failed_t* event)
p_event->operation_id = mongoc_apm_command_failed_get_operation_id(event);
p_event->request_id = mongoc_apm_command_failed_get_request_id(event);
p_event->duration_micros = mongoc_apm_command_failed_get_duration(event);
p_event->reply = bson_copy(mongoc_apm_command_failed_get_reply(event));

/* We need to process and convert the error right here, otherwise
* debug_info will turn into a recursive loop, and with the wrong trace
* locations */
mongoc_apm_command_failed_get_error(event, &tmp_error);

{
#if PHP_VERSION_ID < 70000
MAKE_STD_ZVAL(p_event->z_error);
Expand Down
1 change: 1 addition & 0 deletions php_phongo_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ typedef struct {
uint64_t operation_id;
uint64_t request_id;
uint64_t duration_micros;
bson_t* reply;
PHONGO_STRUCT_ZVAL z_error;
PHONGO_ZEND_OBJECT_POST
} php_phongo_commandfailedevent_t;
Expand Down
36 changes: 36 additions & 0 deletions src/MongoDB/Monitoring/CommandFailedEvent.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,29 @@ PHP_METHOD(CommandFailedEvent, getOperationId)
PHONGO_RETVAL_STRING(int_as_string);
} /* }}} */

/* {{{ proto stdClass CommandFailedEvent::getReply()
Returns the reply document associated with the event */
PHP_METHOD(CommandFailedEvent, getReply)
{
php_phongo_commandfailedevent_t* intern;
php_phongo_bson_state state = PHONGO_BSON_STATE_INITIALIZER;
SUPPRESS_UNUSED_WARNING(return_value_ptr)
SUPPRESS_UNUSED_WARNING(return_value_used)

intern = Z_COMMANDFAILEDEVENT_OBJ_P(getThis());

if (zend_parse_parameters_none() == FAILURE) {
return;
}

php_phongo_bson_to_zval_ex(bson_get_data(intern->reply), intern->reply->len, &state);
#if PHP_VERSION_ID >= 70000
RETURN_ZVAL(&state.zchild, 0, 1);
#else
RETURN_ZVAL(state.zchild, 0, 1);
#endif
} /* }}} */

/* {{{ proto string CommandFailedEvent::getRequestId()
Returns the event's request ID */
PHP_METHOD(CommandFailedEvent, getRequestId)
Expand Down Expand Up @@ -153,6 +176,7 @@ static zend_function_entry php_phongo_commandfailedevent_me[] = {
PHP_ME(CommandFailedEvent, getError, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(CommandFailedEvent, getDurationMicros, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(CommandFailedEvent, getOperationId, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(CommandFailedEvent, getReply, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(CommandFailedEvent, getRequestId, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(CommandFailedEvent, getServer, ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_CommandFailedEvent_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
Expand All @@ -174,6 +198,10 @@ static void php_phongo_commandfailedevent_free_object(phongo_free_object_arg* ob
zval_ptr_dtor(&intern->z_error);
}

if (intern->reply) {
bson_destroy(intern->reply);
}

if (intern->command_name) {
efree(intern->command_name);
}
Expand Down Expand Up @@ -212,6 +240,7 @@ static HashTable* php_phongo_commandfailedevent_get_debug_info(zval* object, int
php_phongo_commandfailedevent_t* intern;
zval retval = ZVAL_STATIC_INIT;
char operation_id[20], request_id[20];
php_phongo_bson_state reply_state = PHONGO_BSON_STATE_INITIALIZER;

intern = Z_COMMANDFAILEDEVENT_OBJ_P(object);
*is_temp = 1;
Expand All @@ -231,6 +260,13 @@ static HashTable* php_phongo_commandfailedevent_get_debug_info(zval* object, int
sprintf(operation_id, "%" PRIu64, intern->operation_id);
ADD_ASSOC_STRING(&retval, "operationId", operation_id);

php_phongo_bson_to_zval_ex(bson_get_data(intern->reply), intern->reply->len, &reply_state);
#if PHP_VERSION_ID >= 70000
ADD_ASSOC_ZVAL(&retval, "reply", &reply_state.zchild);
#else
ADD_ASSOC_ZVAL(&retval, "reply", reply_state.zchild);
#endif

sprintf(request_id, "%" PRIu64, intern->request_id);
ADD_ASSOC_STRING(&retval, "requestId", request_id);

Expand Down
60 changes: 60 additions & 0 deletions tests/apm/monitoring-commandFailed-003.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
--TEST--
MongoDB\Driver\Monitoring\CommandFailedEvent
--SKIPIF--
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
<?php skip_if_not_live(); ?>
<?php skip_if_server_version('<', '3.4'); ?>
--FILE--
<?php
require_once __DIR__ . "/../utils/basic.inc";

$manager = new MongoDB\Driver\Manager(URI);

class MySubscriber implements MongoDB\Driver\Monitoring\CommandSubscriber
{
public function commandStarted( \MongoDB\Driver\Monitoring\CommandStartedEvent $event )
{
echo "started: ", $event->getCommandName(), "\n";
}

public function commandSucceeded( \MongoDB\Driver\Monitoring\CommandSucceededEvent $event )
{
var_dump($event);
}

public function commandFailed( \MongoDB\Driver\Monitoring\CommandFailedEvent $event )
{
echo "failed: ", $event->getCommandName(), "\n";
var_dump($event->getReply());
}
}

$subscriber = new MySubscriber;

MongoDB\Driver\Monitoring\addSubscriber( $subscriber );

$command = new MongoDB\Driver\Command([
'findAndModify' => COLLECTION_NAME,
'query' => ['_id' => 'foo'],
'upsert' => true,
'new' => true,
]);

try {
$manager->executeWriteCommand(DATABASE_NAME, $command);
} catch (MongoDB\Driver\Exception\CommandException $e) {}

?>
--EXPECTF--
started: findAndModify
failed: findAndModify
object(stdClass)#%d (%d) {
["ok"]=>
float(0)
["errmsg"]=>
string(49) "Either an update or remove=true must be specified"
["code"]=>
int(9)
["codeName"]=>
string(13) "FailedToParse"%A
}
9 changes: 9 additions & 0 deletions tests/apm/overview.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,15 @@ object(MongoDB\Driver\Monitoring\CommandFailedEvent)#%d (%d) {
}
["operationId"]=>
string(%d) "%s"
["reply"]=>
object(stdClass)#%d (%d) {
["ok"]=>
float(0)
["errmsg"]=>
string(12) "ns not found"
["code"]=>
int(26)%A
}
["requestId"]=>
string(%d) "%s"
["server"]=>
Expand Down