Skip to content

Commit 10836dc

Browse files
committed
Initial HTTP(S) driver.
1 parent 846ff27 commit 10836dc

File tree

7 files changed

+280
-3
lines changed

7 files changed

+280
-3
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ It doesn't require any modification to your application's code and let's you col
1616
1. `$ git clone https://github.com/patrickallaert/php-apm.git`
1717
2. `$ cd php-apm`
1818
3. `$ phpize`
19-
4. Configure the extension, by default, **sqlite3**, **MariaDB/MySQL**, **[StatsD](https://github.com/etsy/statsd/)** and **Socket** support are enabled:
19+
4. Configure the extension, by default, **sqlite3**, **MariaDB/MySQL**, **[StatsD](https://github.com/etsy/statsd/)**, **HTTP**, and **Socket** support are enabled:
2020

2121
```
22-
$ ./configure [--with-sqlite3[=DIR]] [--with-mysql[=DIR]] [--enable-statsd] [--enable-socket] [--with-debugfile[=FILE]]
22+
$ ./configure [--with-sqlite3[=DIR]] [--with-mysql[=DIR]] [--enable-statsd] [--enable-socket] [--enable-http] [--with-debugfile[=FILE]]
2323
```
2424
To disable the support of a `--with-*` switch, use: `--without-*`, example: `$ ./configure --without-sqlite3`
2525
To disable the support of a `--enable-*` switch, use: `--disable-*`, example: `$ ./configure --disable-socket`

apm.c

+25
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@
5353
#ifdef APM_DRIVER_SOCKET
5454
# include "driver_socket.h"
5555
#endif
56+
#ifdef APM_DRIVER_HTTP
57+
#include "driver_http.h"
58+
#endif
5659

5760
ZEND_DECLARE_MODULE_GLOBALS(apm);
5861
static PHP_GINIT_FUNCTION(apm);
@@ -240,6 +243,25 @@ PHP_INI_BEGIN()
240243
/* process silenced events? */
241244
STD_PHP_INI_BOOLEAN("apm.socket_process_silenced_events", "1", PHP_INI_PERDIR, OnUpdateBool, socket_process_silenced_events, zend_apm_globals, apm_globals)
242245
#endif
246+
247+
#ifdef APM_DRIVER_HTTP
248+
/* Boolean controlling whether the driver is active or not */
249+
STD_PHP_INI_BOOLEAN("apm.http_enabled", "1", PHP_INI_ALL, OnUpdateBool, http_enabled, zend_apm_globals, apm_globals)
250+
/* Boolean controlling the collection of stats */
251+
STD_PHP_INI_BOOLEAN("apm.http_stats_enabled", "1", PHP_INI_ALL, OnUpdateBool, http_stats_enabled, zend_apm_globals, apm_globals)
252+
/* Control which exceptions to collect (0: none exceptions collected, 1: collect uncaught exceptions (default), 2: collect ALL exceptions) */
253+
STD_PHP_INI_ENTRY("apm.http_exception_mode","1", PHP_INI_PERDIR, OnUpdateLongGEZero, http_exception_mode, zend_apm_globals, apm_globals)
254+
/* error_reporting of the driver */
255+
STD_PHP_INI_ENTRY("apm.http_error_reporting", NULL, PHP_INI_ALL, OnUpdateAPMhttpErrorReporting, http_error_reporting, zend_apm_globals, apm_globals)
256+
/* process silenced events? */
257+
STD_PHP_INI_BOOLEAN("apm.http_process_silenced_events", "1", PHP_INI_PERDIR, OnUpdateBool, http_process_silenced_events, zend_apm_globals, apm_globals)
258+
STD_PHP_INI_ENTRY("apm.http_request_timeout", "1000", PHP_INI_ALL, OnUpdateLong, http_request_timeout, zend_apm_globals, apm_globals)
259+
STD_PHP_INI_ENTRY("apm.http_server", "http://localhost", PHP_INI_ALL, OnUpdateString, http_server, zend_apm_globals, apm_globals)
260+
STD_PHP_INI_ENTRY("apm.http_client_certificate", NULL, PHP_INI_ALL, OnUpdateString, http_client_certificate, zend_apm_globals, apm_globals)
261+
STD_PHP_INI_ENTRY("apm.http_client_key", NULL, PHP_INI_ALL, OnUpdateString, http_client_key, zend_apm_globals, apm_globals)
262+
STD_PHP_INI_ENTRY("apm.http_certificate_authorities", NULL, PHP_INI_ALL, OnUpdateString, http_certificate_authorities, zend_apm_globals, apm_globals)
263+
STD_PHP_INI_ENTRY("apm.http_max_backtrace_length", "0", PHP_INI_ALL, OnUpdateLong, http_max_backtrace_length, zend_apm_globals, apm_globals)
264+
#endif
243265
PHP_INI_END()
244266

245267
static PHP_GINIT_FUNCTION(apm)
@@ -272,6 +294,9 @@ static PHP_GINIT_FUNCTION(apm)
272294
*next = apm_driver_socket_create();
273295
next = &(*next)->next;
274296
#endif
297+
#ifdef APM_DRIVER_HTTP
298+
*next = apm_driver_http_create();
299+
#endif
275300
}
276301

277302
static void recursive_free_driver(apm_driver_entry **driver)

apm.ini

+23
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,26 @@ extension=apm.so
9797
; Socket path (accept multiple entries, separated by "|", prefixed with "file:" or "tcp:")
9898
; Example: apm.socket_path=file:/var/tmp/apm.sock|tcp:localhost:1234
9999
; apm.socket_path=file:/tmp/apm.sock
100+
101+
; HTTP configuration
102+
; Whether to enable the HTTP driver
103+
; apm.http_enabled=On
104+
; Whether to collect stats for the HTTP driver
105+
; apm.http_stats_enabled=On
106+
; Error reporting level specific to the HTTP driver
107+
; apm.http_error_reporting=E_ALL|E_STRICT
108+
; Control which exceptions to collect (0: none exceptions collected, 1: collect uncaught exceptions (default), 2: collect ALL exceptions)
109+
; apm.http_exception_mode=1
110+
; Stores silenced events
111+
; apm.http_process_silenced_events = On
112+
; Server for POSTing events
113+
; apm.http_server=http://localhost
114+
; Client and certificate authority for making the server connection
115+
; apm.http_certificate_authorities=""
116+
; apm.http_client_certificate=""
117+
; apm.http_client_key=""
118+
; Maximum number of characters to include in backtrace (0=unlimited)
119+
; apm.http_max_backtrace_length=0
120+
; Timeout (in ms) for POSTing events
121+
; apm.http_request_timeout=1000
122+

config.m4

+36-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ PHP_ARG_ENABLE(statsd, enable support for statsd,
3535
[ --enable-statsd Enable statsd support], yes, no)
3636
PHP_ARG_ENABLE(socket, enable support for socket,
3737
[ --enable-socket Enable socket support], yes, no)
38+
PHP_ARG_ENABLE(http, enable support for http,
39+
[ --enable-http Enable HTTP support], yes, no)
3840
PHP_ARG_WITH(debugfile, enable the debug file,
3941
[ --with-debugfile=[FILE] Location of debugging file (/tmp/apm.debug by default)], no, no)
4042
PHP_ARG_WITH(defaultdb, set default sqlite3 default DB path,
@@ -199,6 +201,39 @@ if test "$PHP_APM" != "no"; then
199201
AC_DEFINE(APM_DRIVER_SOCKET, 1, [activate socket driver])
200202
fi
201203

202-
PHP_NEW_EXTENSION(apm, apm.c backtrace.c $sqlite3_driver $mysql_driver $statsd_driver $socket_driver, $ext_shared)
204+
if test "$PHP_HTTP" != "no"; then
205+
http_driver="driver_http.c"
206+
AC_DEFINE(APM_DRIVER_HTTP, 1, [activate HTTP sending driver])
207+
AC_DEFINE(HAVE_HTTP, 1, [HTTP found and included])
208+
209+
if test -r $PHP_CURL/include/curl/easy.h; then
210+
CURL_DIR=$PHP_CURL
211+
else
212+
AC_MSG_CHECKING(for cURL in default path)
213+
for i in /usr/local /usr; do
214+
if test -r $i/include/curl/easy.h; then
215+
CURL_DIR=$i
216+
AC_MSG_RESULT(found in $i)
217+
break
218+
fi
219+
done
220+
fi
221+
222+
PHP_ADD_INCLUDE($CURL_DIR/include)
223+
PHP_EVAL_LIBLINE($CURL_LIBS, APM_SHARED_LIBADD)
224+
PHP_ADD_LIBRARY_WITH_PATH(curl, $CURL_DIR/$PHP_LIBDIR, APM_SHARED_LIBADD)
225+
226+
PHP_CHECK_LIBRARY(curl,curl_easy_perform,
227+
[
228+
AC_DEFINE(HAVE_CURL,1,[ ])
229+
],[
230+
AC_MSG_ERROR(There is something wrong. Please check config.log for more information.)
231+
],[
232+
$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR
233+
])
234+
235+
fi
236+
237+
PHP_NEW_EXTENSION(apm, apm.c backtrace.c $sqlite3_driver $mysql_driver $statsd_driver $socket_driver $http_driver, $ext_shared)
203238
PHP_SUBST(APM_SHARED_LIBADD)
204239
fi

driver_http.c

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| APM stands for Alternative PHP Monitor |
4+
+----------------------------------------------------------------------+
5+
| Copyright (c) 2011-2016 David Strauss |
6+
+----------------------------------------------------------------------+
7+
| This source file is subject to version 3.01 of the PHP license, |
8+
| that is bundled with this package in the file LICENSE, and is |
9+
| available through the world-wide-web at the following url: |
10+
| http://www.php.net/license/3_01.txt |
11+
| If you did not receive a copy of the PHP license and are unable to |
12+
| obtain it through the world-wide-web, please send a note to |
13+
| [email protected] so we can mail you a copy immediately. |
14+
+----------------------------------------------------------------------+
15+
| Authors: David Strauss <[email protected]> |
16+
+----------------------------------------------------------------------+
17+
*/
18+
19+
#include <stdio.h>
20+
#include <curl/curl.h>
21+
#include "php_apm.h"
22+
#include "php_ini.h"
23+
24+
#include "driver_http.h"
25+
26+
ZEND_EXTERN_MODULE_GLOBALS(apm)
27+
28+
APM_DRIVER_CREATE(http)
29+
30+
char *truncate_data(char *input_str, size_t max_len)
31+
{
32+
char *truncated;
33+
input_str = input_str ? input_str : NULL;
34+
if (max_len == 0)
35+
return strdup(input_str);
36+
truncated = strndup(input_str, max_len);
37+
return truncated;
38+
}
39+
40+
/* Insert an event in the backend */
41+
void apm_driver_http_process_event(PROCESS_EVENT_ARGS)
42+
{
43+
CURL *curl;
44+
CURLcode res;
45+
46+
curl_global_init(CURL_GLOBAL_ALL);
47+
curl = curl_easy_init();
48+
if(curl) {
49+
struct curl_httppost *formpost = NULL;
50+
struct curl_httppost *lastptr = NULL;
51+
struct curl_slist *headerlist = NULL;
52+
static const char buf[] = "Expect:";
53+
char int2string[64];
54+
char *trace_to_send;
55+
size_t max_len = 0;
56+
57+
if (APM_G(http_max_backtrace_length) >= 0)
58+
max_len = APM_G(http_max_backtrace_length);
59+
60+
trace_to_send = truncate_data(trace, max_len);
61+
62+
sprintf(int2string, "%d", type);
63+
curl_formadd(&formpost,
64+
&lastptr,
65+
CURLFORM_COPYNAME, "type",
66+
CURLFORM_COPYCONTENTS, int2string,
67+
CURLFORM_END);
68+
69+
curl_formadd(&formpost,
70+
&lastptr,
71+
CURLFORM_COPYNAME, "file",
72+
CURLFORM_COPYCONTENTS, error_filename ? error_filename : "",
73+
CURLFORM_END);
74+
75+
sprintf(int2string, "%d", error_lineno);
76+
curl_formadd(&formpost,
77+
&lastptr,
78+
CURLFORM_COPYNAME, "line",
79+
CURLFORM_COPYCONTENTS, int2string,
80+
CURLFORM_END);
81+
82+
curl_formadd(&formpost,
83+
&lastptr,
84+
CURLFORM_COPYNAME, "message",
85+
CURLFORM_COPYCONTENTS, msg ? msg : "",
86+
CURLFORM_END);
87+
88+
curl_formadd(&formpost,
89+
&lastptr,
90+
CURLFORM_COPYNAME, "backtrace",
91+
CURLFORM_COPYCONTENTS, trace_to_send,
92+
CURLFORM_END);
93+
94+
headerlist = curl_slist_append(headerlist, buf);
95+
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
96+
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
97+
98+
curl_easy_setopt(curl, CURLOPT_URL, APM_G(http_server));
99+
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, APM_G(http_request_timeout));
100+
if (APM_G(http_client_certificate) != NULL) {
101+
curl_easy_setopt(curl, CURLOPT_SSLCERT, APM_G(http_client_certificate));
102+
}
103+
if (APM_G(http_client_key) != NULL) {
104+
curl_easy_setopt(curl, CURLOPT_SSLKEY, APM_G(http_client_key));
105+
}
106+
if (APM_G(http_certificate_authorities) != NULL) {
107+
curl_easy_setopt(curl, CURLOPT_CAINFO, APM_G(http_certificate_authorities));
108+
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
109+
}
110+
111+
res = curl_easy_perform(curl);
112+
113+
APM_DEBUG("[HTTP driver] Result: %s\n", curl_easy_strerror(res));
114+
115+
/* Always clean up. */
116+
curl_easy_cleanup(curl);
117+
free(trace_to_send);
118+
}
119+
}
120+
121+
int apm_driver_http_minit(int module_number)
122+
{
123+
return SUCCESS;
124+
}
125+
126+
int apm_driver_http_rinit()
127+
{
128+
return SUCCESS;
129+
}
130+
131+
int apm_driver_http_mshutdown()
132+
{
133+
return SUCCESS;
134+
}
135+
136+
int apm_driver_http_rshutdown()
137+
{
138+
return SUCCESS;
139+
}
140+
141+
void apm_driver_http_process_stats(TSRMLS_D)
142+
{
143+
}

driver_http.h

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| APM stands for Alternative PHP Monitor |
4+
+----------------------------------------------------------------------+
5+
| Copyright (c) 2011-2016 David Strauss |
6+
+----------------------------------------------------------------------+
7+
| This source file is subject to version 3.01 of the PHP license, |
8+
| that is bundled with this package in the file LICENSE, and is |
9+
| available through the world-wide-web at the following url: |
10+
| http://www.php.net/license/3_01.txt |
11+
| If you did not receive a copy of the PHP license and are unable to |
12+
| obtain it through the world-wide-web, please send a note to |
13+
| [email protected] so we can mail you a copy immediately. |
14+
+----------------------------------------------------------------------+
15+
| Authors: David Strauss <[email protected]> |
16+
+----------------------------------------------------------------------+
17+
*/
18+
19+
#ifndef DRIVER_HTTP_H
20+
#define DRIVER_HTTP_H
21+
22+
#include "zend_API.h"
23+
24+
#define APM_E_http APM_E_ALL
25+
26+
apm_driver_entry * apm_driver_http_create();
27+
28+
PHP_INI_MH(OnUpdateAPMhttpErrorReporting);
29+
30+
#endif

php_apm.h

+21
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,27 @@ ZEND_BEGIN_MODULE_GLOBALS(apm)
339339
apm_event_entry *socket_events;
340340
apm_event_entry **socket_last_event;
341341
#endif
342+
343+
#ifdef APM_DRIVER_HTTP
344+
/* Boolean controlling whether the driver is active or not */
345+
zend_bool http_enabled;
346+
/* Boolean controlling the collection of stats */
347+
zend_bool http_stats_enabled;
348+
/* (unused for HTTP) */
349+
long http_exception_mode;
350+
/* (unused for HTTP) */
351+
int http_error_reporting;
352+
/* Option to process silenced events */
353+
zend_bool http_process_silenced_events;
354+
355+
long http_request_timeout;
356+
char *http_server;
357+
char *http_client_certificate;
358+
char *http_client_key;
359+
char *http_certificate_authorities;
360+
long http_max_backtrace_length;
361+
#endif
362+
342363
ZEND_END_MODULE_GLOBALS(apm)
343364

344365
#ifdef ZTS

0 commit comments

Comments
 (0)