Skip to content

Commit 7a54147

Browse files
committed
feat(agent): handle additional args for newrelic_notice_error
1 parent 687e42d commit 7a54147

File tree

9 files changed

+375
-9
lines changed

9 files changed

+375
-9
lines changed

agent/php_api.c

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,16 @@ PHP_FUNCTION(newrelic_notice_error) {
7171
const char* errclass = "NoticedError";
7272
char* errormsgstr = NULL;
7373
nr_string_len_t errormsglen = 0;
74-
zend_long ignore1 = 0;
75-
char* ignore2 = 0;
76-
nr_string_len_t ignore3 = 0;
77-
zend_long ignore4 = 0;
74+
zend_long error_number = 0;
75+
char* error_file = NULL;
76+
nr_string_len_t error_file_len = 0;
77+
zend_long error_line = 0;
7878
zval* exc = NULL;
79-
zval* ignore5 = NULL;
79+
nr_string_len_t error_context_len = 0;
80+
char* error_context = NULL;
8081
int priority = 0;
8182
zval* ignore = NULL;
83+
bool determine = false;
8284

8385
NR_UNUSED_RETURN_VALUE;
8486
NR_UNUSED_RETURN_VALUE_PTR;
@@ -144,12 +146,14 @@ PHP_FUNCTION(newrelic_notice_error) {
144146
case 5:
145147
if (FAILURE
146148
== zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
147-
ZEND_NUM_ARGS() TSRMLS_CC, "lsslz!",
148-
&ignore1, &errormsgstr, &errormsglen,
149-
&ignore2, &ignore3, &ignore4, &ignore5)) {
149+
ZEND_NUM_ARGS() TSRMLS_CC, "lssls!",
150+
&error_number, &errormsgstr, &errormsglen,
151+
&error_file, &error_file_len, &error_line,
152+
&error_context, &error_context_len)) {
150153
nrl_debug(NRL_API, "newrelic_notice_error: invalid five arguments");
151154
RETURN_NULL();
152155
}
156+
determine = true;
153157
break;
154158

155159
default:
@@ -168,7 +172,7 @@ PHP_FUNCTION(newrelic_notice_error) {
168172
}
169173
}
170174

171-
{
175+
if (!determine) {
172176
char* buf = nr_strndup(errormsgstr, errormsglen);
173177
char* stack_json = nr_php_backtrace_to_json(NULL TSRMLS_CC);
174178

@@ -177,6 +181,23 @@ PHP_FUNCTION(newrelic_notice_error) {
177181
nr_free(buf);
178182
nr_free(stack_json);
179183

184+
RETURN_TRUE;
185+
}
186+
if (determine) {
187+
char* buf1 = nr_strndup(errormsgstr, errormsglen);
188+
char* buf2 = nr_strndup(error_file, error_file_len);
189+
char* buf3 = nr_strndup(error_context, error_context_len);
190+
char* stack_json = nr_php_backtrace_to_json(NULL TSRMLS_CC);
191+
192+
nr_txn_record_error_with_additional_attributes(
193+
NRPRG(txn), priority, true, buf1, errclass, buf2,
194+
error_line, buf3, error_number, stack_json);
195+
196+
nr_free(buf1);
197+
nr_free(buf2);
198+
nr_free(buf3);
199+
nr_free(stack_json);
200+
180201
RETURN_TRUE;
181202
}
182203
}

axiom/nr_errors.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,51 @@ nr_error_t* nr_error_create(int priority,
3838
error->message = nr_strdup(message);
3939
error->klass = nr_strdup(klass);
4040
error->stacktrace_json = nr_strdup(stacktrace_json);
41+
error->option = 0;
4142

4243
if (NULL != span_id) {
4344
error->span_id = nr_strdup(span_id);
4445
}
4546
return error;
4647
}
4748

49+
nr_error_t* nr_error_create_additional_params(int priority,
50+
const char* message,
51+
const char* klass,
52+
const char* error_file,
53+
int error_line,
54+
const char* error_context,
55+
int error_no,
56+
const char* stacktrace_json,
57+
const char* span_id,
58+
nrtime_t when) {
59+
nr_error_t* error;
60+
61+
if (0 == message || 0 == klass || 0 == error_file || 0 == error_context
62+
|| 0 == stacktrace_json) {
63+
return 0;
64+
}
65+
66+
error = (nr_error_t*)nr_zalloc(sizeof(nr_error_t));
67+
error->priority = priority;
68+
error->when = when;
69+
error->message = nr_strdup(message);
70+
error->klass = nr_strdup(klass);
71+
error->error_file = nr_strdup(error_file);
72+
error->error_line = error_line;
73+
error->error_context = nr_strdup(error_context);
74+
error->error_no = error_no;
75+
76+
error->stacktrace_json = nr_strdup(stacktrace_json);
77+
78+
if (NULL != span_id) {
79+
error->span_id = nr_strdup(span_id);
80+
}
81+
82+
error->option = 1;
83+
return error;
84+
}
85+
4886
const char* nr_error_get_message(const nr_error_t* error) {
4987
if (NULL == error) {
5088
return NULL;
@@ -59,6 +97,41 @@ const char* nr_error_get_klass(const nr_error_t* error) {
5997
return error->klass;
6098
}
6199

100+
const char* nr_error_get_file(const nr_error_t* error) {
101+
if (NULL == error) {
102+
return NULL;
103+
}
104+
return error->error_file;
105+
}
106+
107+
int nr_error_get_line(const nr_error_t* error) {
108+
if (NULL == error) {
109+
return 0;
110+
}
111+
return error->error_line;
112+
}
113+
114+
const char* nr_error_get_context(const nr_error_t* error) {
115+
if (NULL == error) {
116+
return NULL;
117+
}
118+
return error->error_context;
119+
}
120+
121+
int nr_error_get_no(const nr_error_t* error) {
122+
if (NULL == error) {
123+
return 0;
124+
}
125+
return error->error_no;
126+
}
127+
128+
int nr_error_get_option(const nr_error_t* error) {
129+
if (NULL == error) {
130+
return 0;
131+
}
132+
return error->option;
133+
}
134+
62135
nrtime_t nr_error_get_time(const nr_error_t* error) {
63136
if (NULL == error) {
64137
return 0;
@@ -97,6 +170,25 @@ void nr_error_destroy(nr_error_t** error_ptr) {
97170
nr_realfree((void**)error_ptr);
98171
}
99172

173+
void nr_error_destroy_additional_params(nr_error_t** error_ptr) {
174+
nr_error_t* error;
175+
176+
if (0 == error_ptr) {
177+
return;
178+
}
179+
error = *error_ptr;
180+
if (0 == error) {
181+
return;
182+
}
183+
nr_free(error->message);
184+
nr_free(error->klass);
185+
nr_free(error->error_file);
186+
nr_free(error->error_context);
187+
nr_free(error->span_id);
188+
nr_free(error->stacktrace_json);
189+
nr_realfree((void**)error_ptr);
190+
}
191+
100192
static nrobj_t* nr_error_params_to_object(const char* stacktrace_json,
101193
const nrobj_t* agent_attributes,
102194
const nrobj_t* user_attributes,

axiom/nr_errors.h

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,38 @@ extern nr_error_t* nr_error_create(int priority,
3838
const char* span_id,
3939
nrtime_t when);
4040

41+
/*
42+
* Purpose : Create a new error for the use case where additional parameters are
43+
* passed in.
44+
*
45+
* Params : 1. The importance of the error. Higher number is more important.
46+
* 2. Message string.
47+
* 3. Class string. This string is used to aggregate errors in RPM.
48+
* RPM does not expect strings from a specific namespace.
49+
* The PHP agent uses PHP's predefined error constant names.
50+
* Examples are "E_ERROR" and "E_WARNING".
51+
* 4. Error file provided by user.
52+
* 5. Error line provided by user.
53+
* 6. Error context provided by user.
54+
* 7. Error number provided by user.
55+
* 8. String containing stack trace in JSON format.
56+
* 9. Span ID
57+
* 10. When the error occurred.
58+
*
59+
* Returns : A newly allocated error, or 0 on failure.
60+
*/
61+
extern nr_error_t* nr_error_create_additional_params(
62+
int priority,
63+
const char* message,
64+
const char* klass,
65+
const char* error_file,
66+
int error_line,
67+
const char* error_context,
68+
int error_no,
69+
const char* stacktrace_json,
70+
const char* span_id,
71+
nrtime_t when);
72+
4173
/*
4274
* Purpose : Retrieve error fields for the purpose of creating attributes.
4375
*/
@@ -54,6 +86,43 @@ extern const char* nr_error_get_message(const nr_error_t* error);
5486
* Returns : The klass of the error or NULL on failure.
5587
*/
5688
extern const char* nr_error_get_klass(const nr_error_t* error);
89+
90+
/*
91+
* Purpose : Get the error file of an error.
92+
*
93+
* Returns : The error file of the error or NULL on failure.
94+
*/
95+
extern const char* nr_error_get_file(const nr_error_t* error);
96+
97+
/*
98+
* Purpose : Get the error line of an error.
99+
*
100+
* Returns : The error line of the error or 0 on failure.
101+
*/
102+
extern int nr_error_get_line(const nr_error_t* error);
103+
104+
/*
105+
* Purpose : Get the error context of an error.
106+
*
107+
* Returns : The error context of the error or NULL on failure.
108+
*/
109+
extern const char* nr_error_get_context(const nr_error_t* error);
110+
111+
/*
112+
* Purpose : Get the error number of an error.
113+
*
114+
* Returns : The error number of the error or 0 on failure.
115+
*/
116+
extern int nr_error_get_no(const nr_error_t* error);
117+
118+
/*
119+
* Purpose : Determine if the option is 0 or 1. If 1, then this means the error
120+
* has additional arguments.
121+
*
122+
* Returns : Either 0 or 1
123+
*/
124+
extern int nr_error_get_option(const nr_error_t* error);
125+
57126
/*
58127
* Purpose : Get the span_id of an error.
59128
*
@@ -80,6 +149,11 @@ extern int nr_error_priority(const nr_error_t* error);
80149
*/
81150
extern void nr_error_destroy(nr_error_t** error_ptr);
82151

152+
/*
153+
* Purpose : Destroys an error with extra parameters, freeing all of its associated memory.
154+
*/
155+
extern void nr_error_destroy_additional_params(nr_error_t** error_ptr);
156+
83157
/*
84158
* Purpose : Turn an error into the JSON format expected by the 'error_v1'
85159
* command. Returns NULL if an error occurs.

axiom/nr_errors_private.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ struct _nr_error_t {
2525
int priority; /* Error priority - lowest to highest */
2626
char* message; /* Error message */
2727
char* klass; /* Error class */
28+
char* error_file; /* Error file */
29+
int error_line; /* Error line */
30+
char* error_context; /* Error context */
31+
int error_no; /* Error number */
32+
int option; /* Error option */
2833
char* stacktrace_json; /* Stack trace in JSON format */
2934
char* span_id; /* ID of the current executing span at the time the error
3035
occurred */

axiom/nr_segment.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,37 @@ void nr_segment_set_error(nr_segment_t* segment,
11891189
segment->error->error_class = error_class ? nr_strdup(error_class) : NULL;
11901190
}
11911191

1192+
void nr_segment_set_error_with_additional_params(nr_segment_t* segment,
1193+
const char* error_message,
1194+
const char* error_class,
1195+
const char* error_file,
1196+
int error_line,
1197+
char* error_context,
1198+
int error_no) {
1199+
if ((NULL == segment) || (NULL == error_message) || (NULL == error_class)
1200+
|| NULL == error_file || (NULL == error_context)) {
1201+
return;
1202+
}
1203+
1204+
if (NULL == segment->error) {
1205+
segment->error = nr_zalloc(sizeof(nr_segment_error_t));
1206+
}
1207+
1208+
nr_free(segment->error->error_message);
1209+
nr_free(segment->error->error_class);
1210+
nr_free(segment->error->error_file);
1211+
nr_free(segment->error->error_context);
1212+
1213+
segment->error->error_message
1214+
= error_message ? nr_strdup(error_message) : NULL;
1215+
segment->error->error_class = error_class ? nr_strdup(error_class) : NULL;
1216+
segment->error->error_file = error_file ? nr_strdup(error_file) : NULL;
1217+
segment->error->error_line = error_line ? error_line : 0;
1218+
segment->error->error_context
1219+
= error_context ? nr_strdup(error_context) : NULL;
1220+
segment->error->error_no = error_no ? error_no : 0;
1221+
}
1222+
11921223
bool nr_segment_attributes_user_add(nr_segment_t* segment,
11931224
uint32_t destination,
11941225
const char* name,

axiom/nr_segment.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ typedef struct _nr_segment_metric_t {
117117
typedef struct _nr_segment_error_t {
118118
char* error_message; /* The error message that will appear on a span event. */
119119
char* error_class; /* The error class that will appear on a span event. */
120+
char* error_file;
121+
int error_line;
122+
char* error_context;
123+
int error_no;
120124
} nr_segment_error_t;
121125

122126
/*
@@ -649,6 +653,26 @@ extern void nr_segment_record_exception(nr_segment_t* segment,
649653
const char* error_message,
650654
const char* error_class);
651655

656+
/*
657+
* Purpose : Set the error attributes on a segment.
658+
*
659+
* Params : 1. The pointer to the segment.
660+
* 2. The error message that will be added.
661+
* 3. The error class that will be added.
662+
* 4. The error file that will be added.
663+
* 5. The error line that will be added.
664+
* 6. The error context that will be added.
665+
* 7. The error number that will be added.
666+
*/
667+
extern void nr_segment_set_error_with_additional_params(
668+
nr_segment_t* segment,
669+
const char* error_message,
670+
const char* error_class,
671+
const char* errfile,
672+
int errline,
673+
char* errcontext,
674+
int error_no);
675+
652676
/*
653677
* Purpose : Gets the child_ix of a segment.
654678
*

axiom/nr_segment_private.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,5 +87,7 @@ void nr_segment_error_destroy_fields(nr_segment_error_t* segment_error) {
8787

8888
nr_free(segment_error->error_message);
8989
nr_free(segment_error->error_class);
90+
nr_free(segment_error->error_file);
91+
nr_free(segment_error->error_context);
9092
nr_free(segment_error);
9193
}

0 commit comments

Comments
 (0)