Save PDO exceptions. (#24)
diff --git a/config.m4 b/config.m4
index 056b5a4..b4f9560 100644
--- a/config.m4
+++ b/config.m4
@@ -52,6 +52,8 @@
cat >>Makefile.objects<< EOF
all: cargo_build
+clean: cargo_clean
+
cargo_build:
PHP_CONFIG=$PHP_PHP_CONFIG cargo build $CARGO_MODE_FLAGS
if [[ -f ./target/$CARGO_MODE_DIR/libskywalking_agent.dylib ]] ; then \\
@@ -59,7 +61,10 @@
if [[ -f ./target/$CARGO_MODE_DIR/libskywalking_agent.so ]] ; then \\
cp ./target/$CARGO_MODE_DIR/libskywalking_agent.so ./modules/skywalking_agent.so ; fi
-.PHONY: cargo_build
+cargo_clean:
+ cargo clean
+
+.PHONY: cargo_build cargo_clean
EOF
AC_CONFIG_LINKS([ \
diff --git a/src/channel.rs b/src/channel.rs
index 2172d23..eaf7097 100644
--- a/src/channel.rs
+++ b/src/channel.rs
@@ -33,7 +33,7 @@
pub fn init_channel() -> anyhow::Result<()> {
let (sender, receiver) = StdUnixStream::pair()?;
- sender.set_nonblocking(true)?;
+ sender.set_nonblocking(false)?;
receiver.set_nonblocking(true)?;
if SENDER.set(Mutex::new(sender)).is_err() {
diff --git a/src/exception_frame.rs b/src/exception_frame.rs
new file mode 100644
index 0000000..612a98c
--- /dev/null
+++ b/src/exception_frame.rs
@@ -0,0 +1,40 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use phper::sys;
+use std::marker;
+
+pub struct ExceptionFrame {
+ phantom: marker::PhantomData<isize>,
+}
+
+impl ExceptionFrame {
+ pub fn new() -> Self {
+ unsafe {
+ sys::zend_exception_save();
+ }
+ ExceptionFrame {
+ phantom: marker::PhantomData,
+ }
+ }
+}
+
+impl Drop for ExceptionFrame {
+ fn drop(&mut self) {
+ unsafe {
+ sys::zend_exception_restore();
+ }
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 4ffa85a..dd97960 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -20,6 +20,7 @@
mod channel;
mod component;
mod context;
+mod exception_frame;
mod execute;
mod module;
mod plugin;
diff --git a/src/plugin/plugin_pdo.rs b/src/plugin/plugin_pdo.rs
index cc43906..21205c9 100644
--- a/src/plugin/plugin_pdo.rs
+++ b/src/plugin/plugin_pdo.rs
@@ -17,6 +17,7 @@
use crate::{
component::COMPONENT_PHP_PDO_ID,
context::RequestContext,
+ exception_frame::ExceptionFrame,
execute::{get_this_mut, validate_num_args, AfterExecuteHook, BeforeExecuteHook, Noop},
};
use anyhow::Context;
@@ -206,6 +207,7 @@
}
fn after_hook_when_false(this: &mut ZObj, span: &mut Span) -> anyhow::Result<()> {
+ let _e = ExceptionFrame::new();
let info = this.call("errorInfo", [])?;
let info = info.as_z_arr().context("errorInfo isn't array")?;
diff --git a/tests/data/expected_context.yaml b/tests/data/expected_context.yaml
index 31910be..a05679e 100644
--- a/tests/data/expected_context.yaml
+++ b/tests/data/expected_context.yaml
@@ -390,6 +390,53 @@
key: db.statement,
value: "SELECT * FROM `mysql`.`user` WHERE `User` = :user",
}
+ - operationName: PDO->prepare
+ parentSpanId: 0
+ spanId: 8
+ spanLayer: Database
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 8003
+ isError: false
+ spanType: Exit
+ peer: 127.0.0.1:3306
+ skipAnalysis: false
+ tags:
+ - { key: db.type, value: mysql }
+ - {
+ key: db.data_source,
+ value: "dbname=skywalking;host=127.0.0.1;port=3306",
+ }
+ - {
+ key: db.statement,
+ value: "SELECT * FROM not_exist",
+ }
+ - operationName: PDOStatement->execute
+ parentSpanId: 0
+ spanId: 9
+ spanLayer: Database
+ startTime: gt 0
+ endTime: gt 0
+ componentId: 8003
+ isError: true
+ spanType: Exit
+ peer: 127.0.0.1:3306
+ skipAnalysis: false
+ tags:
+ - { key: db.type, value: mysql }
+ - {
+ key: db.data_source,
+ value: "dbname=skywalking;host=127.0.0.1;port=3306",
+ }
+ - {
+ key: db.statement,
+ value: "SELECT * FROM not_exist",
+ }
+ logs:
+ - logEvent:
+ - { key: SQLSTATE, value: 42S02 }
+ - { key: Error Code, value: '1146' }
+ - { key: Error, value: "Table 'skywalking.not_exist' doesn't exist" }
- operationName: GET:/pdo.php
parentSpanId: -1
spanId: 0
diff --git a/tests/php/fpm/pdo.php b/tests/php/fpm/pdo.php
index d73d5c4..ac2ebe1 100644
--- a/tests/php/fpm/pdo.php
+++ b/tests/php/fpm/pdo.php
@@ -41,4 +41,13 @@
Assert::same(count($rs), 0);
}
+{
+ Assert::throws(function () {
+ $pdo = new PDO("mysql:dbname=skywalking;host=127.0.0.1;port=3306", "root", "password");
+ $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+ $sth = $pdo->prepare("SELECT * FROM not_exist");
+ $sth->execute();
+ }, PDOException::class);
+}
+
echo "ok";