-
Notifications
You must be signed in to change notification settings - Fork 66
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix PDO instrumentation in PHP 8.4 (#993)
PHP 8.4 includes implementation of PDO driver specific sub-classes RFC (see https://wiki.php.net/rfc/pdo_driver_specific_subclasses). This means that when database access code uses new factory method `PDO::connect` to create PDO object, an instance of driver specific sub-class of `PDO` is returned instead of an instance of generic `PDO` class. This means that instrumentation of generic `PDO` class is not enough to provide instrumentation of datastores. Add wrappers for driver specific subclasses of `PDO` supported by the agent: `Pdo\Firebird`, `Pdo\Mysql`, `Pdo\Odbc`, `Pdo\Pgsql`, `Pdo\Sqlite`.
- Loading branch information
Showing
110 changed files
with
5,810 additions
and
225 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
157 changes: 157 additions & 0 deletions
157
tests/integration/pdo/mysql/base-class/test_instance_reporting_port.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
<?php | ||
/* | ||
* Copyright 2020 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
/*DESCRIPTION | ||
When PDO base class constructor is used to create connection object | ||
to a database on a remote host via a TCP port, | ||
and database instance reporting is enabled, the agent should | ||
- not generate errors | ||
- record datastore metrics | ||
- record a datastore instance metric | ||
- record a datastore span event with instance information | ||
Moreover, when the query execution time exceeds the explain threshold, | ||
the agent should record a slow sql trace with database instance information. | ||
*/ | ||
|
||
/*SKIPIF | ||
<?php require(realpath (dirname ( __FILE__ )) . '/../../skipif_mysql.inc'); | ||
*/ | ||
|
||
/*ENVIRONMENT | ||
DATASTORE_PRODUCT=MySQL | ||
DATASTORE_COLLECTION=test | ||
MYSQL_PORT=3306 | ||
*/ | ||
|
||
/*INI | ||
;comment=Set explain_threshold to 0 to ensure that the slow query is recorded. | ||
newrelic.transaction_tracer.explain_threshold = 0 | ||
*/ | ||
|
||
/*EXPECT_ERROR_EVENTS null*/ | ||
|
||
/*EXPECT | ||
ok - create table | ||
ok - drop table | ||
*/ | ||
|
||
/*EXPECT_METRICS_EXIST | ||
Datastore/all, 2 | ||
Datastore/allOther, 2 | ||
Datastore/instance/ENV[DATASTORE_PRODUCT]/ENV[MYSQL_HOST]/ENV[MYSQL_PORT], 2 | ||
Datastore/ENV[DATASTORE_PRODUCT]/all, 2 | ||
Datastore/ENV[DATASTORE_PRODUCT]/allOther, 2 | ||
Datastore/operation/ENV[DATASTORE_PRODUCT]/create, 1 | ||
Datastore/statement/ENV[DATASTORE_PRODUCT]/ENV[DATASTORE_COLLECTION]/create, 1 | ||
Datastore/operation/ENV[DATASTORE_PRODUCT]/drop, 1 | ||
Datastore/statement/ENV[DATASTORE_PRODUCT]/ENV[DATASTORE_COLLECTION]/drop, 1 | ||
Supportability/TxnData/SlowSQL, 1 | ||
*/ | ||
|
||
/*EXPECT_SLOW_SQLS | ||
[ | ||
[ | ||
[ | ||
"OtherTransaction/php__FILE__", | ||
"<unknown>", | ||
"?? SQL id", | ||
"DROP TABLE ENV[DATASTORE_COLLECTION];", | ||
"Datastore/statement/ENV[DATASTORE_PRODUCT]/ENV[DATASTORE_COLLECTION]/drop", | ||
1, | ||
"?? total time", | ||
"?? min time", | ||
"?? max time", | ||
{ | ||
"backtrace": [ | ||
"/ in PDO::exec called at .*\/", | ||
" in test_instance_reporting called at __FILE__ (??)" | ||
], | ||
"host": "ENV[MYSQL_HOST]", | ||
"port_path_or_id": "ENV[MYSQL_PORT]", | ||
"database_name": "ENV[MYSQL_DB]" | ||
} | ||
], | ||
[ | ||
"OtherTransaction/php__FILE__", | ||
"<unknown>", | ||
"?? SQL id", | ||
"CREATE TABLE ENV[DATASTORE_COLLECTION] (id INT, description VARCHAR(?));", | ||
"Datastore/statement/ENV[DATASTORE_PRODUCT]/ENV[DATASTORE_COLLECTION]/create", | ||
1, | ||
"?? total time", | ||
"?? min time", | ||
"?? max time", | ||
{ | ||
"backtrace": [ | ||
"/ in PDO::exec called at .*\/", | ||
" in test_instance_reporting called at __FILE__ (??)" | ||
], | ||
"host": "ENV[MYSQL_HOST]", | ||
"port_path_or_id": "ENV[MYSQL_PORT]", | ||
"database_name": "ENV[MYSQL_DB]" | ||
} | ||
] | ||
] | ||
] | ||
*/ | ||
|
||
/*EXPECT_SPAN_EVENTS_LIKE | ||
[ | ||
[ | ||
{ | ||
"category": "datastore", | ||
"type": "Span", | ||
"guid": "??", | ||
"traceId": "??", | ||
"transactionId": "??", | ||
"name": "Datastore/statement/ENV[DATASTORE_PRODUCT]/ENV[DATASTORE_COLLECTION]/create", | ||
"timestamp": "??", | ||
"duration": "??", | ||
"priority": "??", | ||
"sampled": true, | ||
"parentId": "??", | ||
"span.kind": "client", | ||
"component": "ENV[DATASTORE_PRODUCT]" | ||
}, | ||
{}, | ||
{ | ||
"peer.hostname": "ENV[MYSQL_HOST]", | ||
"peer.address": "ENV[MYSQL_HOST]:ENV[MYSQL_PORT]", | ||
"db.instance": "ENV[MYSQL_DB]", | ||
"db.statement": "CREATE TABLE ENV[DATASTORE_COLLECTION] (id INT, description VARCHAR(?));" | ||
} | ||
], | ||
[ | ||
{ | ||
"category": "datastore", | ||
"type": "Span", | ||
"guid": "??", | ||
"traceId": "??", | ||
"transactionId": "??", | ||
"name": "Datastore/statement/ENV[DATASTORE_PRODUCT]/ENV[DATASTORE_COLLECTION]/drop", | ||
"timestamp": "??", | ||
"duration": "??", | ||
"priority": "??", | ||
"sampled": true, | ||
"parentId": "??", | ||
"span.kind": "client", | ||
"component": "ENV[DATASTORE_PRODUCT]" | ||
}, | ||
{}, | ||
{ | ||
"peer.hostname": "ENV[MYSQL_HOST]", | ||
"peer.address": "ENV[MYSQL_HOST]:ENV[MYSQL_PORT]", | ||
"db.instance": "ENV[MYSQL_DB]", | ||
"db.statement": "DROP TABLE ENV[DATASTORE_COLLECTION];" | ||
} | ||
] | ||
] | ||
*/ | ||
|
||
require_once(realpath (dirname ( __FILE__ )) . '/../../test_instance_reporting.inc'); | ||
require_once(realpath (dirname ( __FILE__ )) . '/../../../../include/config.php'); | ||
|
||
test_instance_reporting(new PDO($PDO_MYSQL_DSN, $MYSQL_USER, $MYSQL_PASSWD), 0); |
160 changes: 160 additions & 0 deletions
160
tests/integration/pdo/mysql/base-class/test_instance_reporting_socket.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
<?php | ||
/* | ||
* Copyright 2020 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
/*DESCRIPTION | ||
When PDO base class constructor is used to create connection object | ||
to a database on a localhost via a unix socket, | ||
and database instance reporting is enabled, the agent should | ||
- not generate errors | ||
- record datastore metrics | ||
- record a datastore instance metric | ||
- record a datastore span event with instance information | ||
Moreover, when the query execution time exceeds the explain threshold, | ||
the agent should record a slow sql trace with database instance information. | ||
*/ | ||
|
||
/*SKIPIF | ||
<?php require(realpath (dirname ( __FILE__ )) . '/../../skipif_mysql.inc'); | ||
*/ | ||
|
||
/*ENVIRONMENT | ||
DATASTORE_PRODUCT=MySQL | ||
DATASTORE_COLLECTION=test | ||
*/ | ||
|
||
/*INI | ||
;comment=Set explain_threshold to 0 to ensure that the slow query is recorded. | ||
newrelic.transaction_tracer.explain_threshold = 0 | ||
*/ | ||
|
||
/*EXPECT_ERROR_EVENTS null*/ | ||
|
||
/*EXPECT | ||
ok - create table | ||
ok - drop table | ||
*/ | ||
|
||
/*EXPECT_METRICS_EXIST | ||
Datastore/all, 2 | ||
Datastore/allOther, 2 | ||
Datastore/instance/ENV[DATASTORE_PRODUCT]/__HOST__/ENV[MYSQL_SOCKET], 2 | ||
Datastore/ENV[DATASTORE_PRODUCT]/all, 2 | ||
Datastore/ENV[DATASTORE_PRODUCT]/allOther, 2 | ||
Datastore/operation/ENV[DATASTORE_PRODUCT]/create, 1 | ||
Datastore/statement/ENV[DATASTORE_PRODUCT]/ENV[DATASTORE_COLLECTION]/create, 1 | ||
Datastore/operation/ENV[DATASTORE_PRODUCT]/drop, 1 | ||
Datastore/statement/ENV[DATASTORE_PRODUCT]/ENV[DATASTORE_COLLECTION]/drop, 1 | ||
Supportability/TxnData/SlowSQL, 1 | ||
*/ | ||
|
||
/*EXPECT_SLOW_SQLS | ||
[ | ||
[ | ||
[ | ||
"OtherTransaction/php__FILE__", | ||
"<unknown>", | ||
"?? SQL id", | ||
"DROP TABLE ENV[DATASTORE_COLLECTION];", | ||
"Datastore/statement/ENV[DATASTORE_PRODUCT]/ENV[DATASTORE_COLLECTION]/drop", | ||
1, | ||
"?? total time", | ||
"?? min time", | ||
"?? max time", | ||
{ | ||
"backtrace": [ | ||
"/ in PDO::exec called at .*\/", | ||
" in test_instance_reporting called at __FILE__ (??)" | ||
], | ||
"host": "__HOST__", | ||
"port_path_or_id": "ENV[MYSQL_SOCKET]", | ||
"database_name": "ENV[MYSQL_DB]" | ||
} | ||
], | ||
[ | ||
"OtherTransaction/php__FILE__", | ||
"<unknown>", | ||
"?? SQL id", | ||
"CREATE TABLE ENV[DATASTORE_COLLECTION] (id INT, description VARCHAR(?));", | ||
"Datastore/statement/ENV[DATASTORE_PRODUCT]/ENV[DATASTORE_COLLECTION]/create", | ||
1, | ||
"?? total time", | ||
"?? min time", | ||
"?? max time", | ||
{ | ||
"backtrace": [ | ||
"/ in PDO::exec called at .*\/", | ||
" in test_instance_reporting called at __FILE__ (??)" | ||
], | ||
"host": "__HOST__", | ||
"port_path_or_id": "ENV[MYSQL_SOCKET]", | ||
"database_name": "ENV[MYSQL_DB]" | ||
} | ||
] | ||
] | ||
] | ||
*/ | ||
|
||
/*EXPECT_SPAN_EVENTS_LIKE | ||
[ | ||
[ | ||
{ | ||
"category": "datastore", | ||
"type": "Span", | ||
"guid": "??", | ||
"traceId": "??", | ||
"transactionId": "??", | ||
"name": "Datastore/statement/ENV[DATASTORE_PRODUCT]/ENV[DATASTORE_COLLECTION]/create", | ||
"timestamp": "??", | ||
"duration": "??", | ||
"priority": "??", | ||
"sampled": true, | ||
"parentId": "??", | ||
"span.kind": "client", | ||
"component": "ENV[DATASTORE_PRODUCT]" | ||
}, | ||
{}, | ||
{ | ||
"peer.hostname": "__HOST__", | ||
"peer.address": "__HOST__:ENV[MYSQL_SOCKET]", | ||
"db.instance": "ENV[MYSQL_DB]", | ||
"db.statement": "CREATE TABLE ENV[DATASTORE_COLLECTION] (id INT, description VARCHAR(?));" | ||
} | ||
], | ||
[ | ||
{ | ||
"category": "datastore", | ||
"type": "Span", | ||
"guid": "??", | ||
"traceId": "??", | ||
"transactionId": "??", | ||
"name": "Datastore/statement/ENV[DATASTORE_PRODUCT]/ENV[DATASTORE_COLLECTION]/drop", | ||
"timestamp": "??", | ||
"duration": "??", | ||
"priority": "??", | ||
"sampled": true, | ||
"parentId": "??", | ||
"span.kind": "client", | ||
"component": "ENV[DATASTORE_PRODUCT]" | ||
}, | ||
{}, | ||
{ | ||
"peer.hostname": "__HOST__", | ||
"peer.address": "__HOST__:ENV[MYSQL_SOCKET]", | ||
"db.instance": "ENV[MYSQL_DB]", | ||
"db.statement": "DROP TABLE ENV[DATASTORE_COLLECTION];" | ||
} | ||
] | ||
] | ||
*/ | ||
|
||
require_once(realpath (dirname ( __FILE__ )) . '/../../test_instance_reporting.inc'); | ||
require_once(realpath (dirname ( __FILE__ )) . '/../../../../include/config.php'); | ||
|
||
$DSN = 'mysql:'; | ||
$DSN .= 'unix_socket=' . $MYSQL_SOCKET . ';'; | ||
$DSN .= 'dbname=' . $MYSQL_DB . ';'; | ||
|
||
test_instance_reporting(new PDO($DSN, $MYSQL_USER, $MYSQL_PASSWD), 0); |
Oops, something went wrong.