Skip to content

Commit 1cab5b0

Browse files
committed
Merge branch 'main' into 918_modernbuild_draft_centos_merge
2 parents 072c941 + ab84deb commit 1cab5b0

File tree

76 files changed

+2380
-339
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+2380
-339
lines changed

CHANGELOG.asciidoc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,21 @@ endif::[]
2020
2121
// Using the template above, release notes go here.
2222
// CHANGELOG_AUTOMATION_KEYWORD
23+
[[release-notes-v1.9.0]]
24+
=== v1.9.0 - 2023/06/22
25+
[float]
26+
==== Features
27+
* Added container ID detection {pull}966[#966]
28+
* Extended span compression support to spans without service target {pull}944[#944]
29+
* Added auto-instrumentation for capturing WordPress filters/actions callbacks and the active theme {pull}948[#948]
30+
* Added configuration option STACK_TRACE_LIMIT {pull}995[#995]
31+
* Added SPAN_STACK_TRACE_MIN_DURATION configuration option {pull}996[#996]
32+
* Implemented backoff on failure in communication to APM Server {pull}999[#999]
33+
34+
==== Bug fixes
35+
* Fixed not cleaning up connection data in sync backend comm. mode {pull}957[#957]
36+
* Fixed crash when https://www.php.net/manual/en/function.opcache-reset.php[`opcache_reset()`] is used {pull}1000[#1000]
37+
2338
[[release-notes-v1.8.4]]
2439
=== v1.8.4 - 2023/05/17
2540
[float]

agent/native/ext/ConfigManager.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,8 @@ ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, serviceVersion )
807807
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( boolValue, spanCompressionEnabled )
808808
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, spanCompressionExactMatchMaxDuration )
809809
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, spanCompressionSameKindMaxDuration )
810+
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, spanStackTraceMinDuration )
811+
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, stackTraceLimit )
810812
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, transactionIgnoreUrls )
811813
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, transactionMaxSpans )
812814
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, transactionSampleRate )
@@ -1145,6 +1147,18 @@ static void initOptionsMetadata( OptionMetadata* optsMeta )
11451147
ELASTIC_APM_CFG_OPT_NAME_SPAN_COMPRESSION_SAME_KIND_MAX_DURATION,
11461148
/* defaultValue: */ NULL );
11471149

1150+
ELASTIC_APM_INIT_METADATA(
1151+
buildStringOptionMetadata,
1152+
spanStackTraceMinDuration,
1153+
ELASTIC_APM_CFG_OPT_NAME_SPAN_STACK_TRACE_MIN_DURATION,
1154+
/* defaultValue: */ NULL );
1155+
1156+
ELASTIC_APM_INIT_METADATA(
1157+
buildStringOptionMetadata,
1158+
stackTraceLimit,
1159+
ELASTIC_APM_CFG_OPT_NAME_STACK_TRACE_LIMIT,
1160+
/* defaultValue: */ NULL );
1161+
11481162
ELASTIC_APM_INIT_METADATA(
11491163
buildStringOptionMetadata,
11501164
transactionIgnoreUrls,

agent/native/ext/ConfigManager.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ enum OptionId
109109
optionId_spanCompressionEnabled,
110110
optionId_spanCompressionExactMatchMaxDuration,
111111
optionId_spanCompressionSameKindMaxDuration,
112+
optionId_spanStackTraceMinDuration,
113+
optionId_stackTraceLimit,
112114
optionId_transactionIgnoreUrls,
113115
optionId_transactionMaxSpans,
114116
optionId_transactionSampleRate,
@@ -316,6 +318,8 @@ const ConfigSnapshot* getGlobalCurrentConfigSnapshot();
316318
#define ELASTIC_APM_CFG_OPT_NAME_SPAN_COMPRESSION_ENABLED "span_compression_enabled"
317319
#define ELASTIC_APM_CFG_OPT_NAME_SPAN_COMPRESSION_EXACT_MATCH_MAX_DURATION "span_compression_exact_match_max_duration"
318320
#define ELASTIC_APM_CFG_OPT_NAME_SPAN_COMPRESSION_SAME_KIND_MAX_DURATION "span_compression_same_kind_max_duration"
321+
#define ELASTIC_APM_CFG_OPT_NAME_SPAN_STACK_TRACE_MIN_DURATION "span_stack_trace_min_duration"
322+
#define ELASTIC_APM_CFG_OPT_NAME_STACK_TRACE_LIMIT "stack_trace_limit"
319323
#define ELASTIC_APM_CFG_OPT_NAME_TRANSACTION_IGNORE_URLS "transaction_ignore_urls"
320324
#define ELASTIC_APM_CFG_OPT_NAME_TRANSACTION_MAX_SPANS "transaction_max_spans"
321325
#define ELASTIC_APM_CFG_OPT_NAME_TRANSACTION_SAMPLE_RATE "transaction_sample_rate"

agent/native/ext/ConfigSnapshot.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ struct ConfigSnapshot
8080
bool spanCompressionEnabled;
8181
String spanCompressionExactMatchMaxDuration;
8282
String spanCompressionSameKindMaxDuration;
83+
String spanStackTraceMinDuration;
84+
String stackTraceLimit;
8385
String transactionIgnoreUrls;
8486
String transactionMaxSpans;
8587
String transactionSampleRate;

agent/native/ext/backend_comm.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "util.h"
3131
#include "util_for_PHP.h"
3232
#include "basic_macros.h"
33+
#include "backend_comm_backoff.h"
3334

3435
#define ELASTIC_APM_CURRENT_LOG_CATEGORY ELASTIC_APM_LOG_CATEGORY_BACKEND_COMM
3536

@@ -190,9 +191,10 @@ struct ConnectionData
190191
{
191192
CURL* curlHandle;
192193
struct curl_slist* requestHeaders;
194+
BackendCommBackoff backoff;
193195
};
194196
typedef struct ConnectionData ConnectionData;
195-
ConnectionData g_connectionData = { .curlHandle = NULL, .requestHeaders = NULL };
197+
ConnectionData g_connectionData = { .curlHandle = NULL, .requestHeaders = NULL, .backoff = ELASTIC_APM_DEFAULT_BACKEND_COMM_BACKOFF };
196198

197199
void cleanupConnectionData( ConnectionData* connectionData )
198200
{
@@ -465,11 +467,16 @@ ResultCode syncSendEventsToApmServerWithConn( const ConfigSnapshot* config, Conn
465467
ELASTIC_APM_SET_RESULT_CODE_AND_GOTO_FAILURE();
466468
}
467469

468-
long responseCode;
470+
long responseCode = 0;
469471
curl_easy_getinfo( connectionData->curlHandle, CURLINFO_RESPONSE_CODE, &responseCode );
470-
ELASTIC_APM_LOG_DEBUG( "Sent events to APM Server. Response HTTP code: %ld. URL: `%s'.", responseCode, url );
471-
472-
resultCode = resultSuccess;
472+
/**
473+
* If the HTTP response status code isn’t 2xx or if a request is prematurely closed (either on the TCP or HTTP level) the request MUST be considered failed.
474+
*
475+
* @see https://github.com/elastic/apm/blob/d8cb5607dbfffea819ab5efc9b0743044772fb23/specs/agents/transport.md#transport-errors
476+
*/
477+
bool isFailed = ( responseCode / 100 ) != 2;
478+
ELASTIC_APM_LOG_WITH_LEVEL( isFailed ? logLevel_error : logLevel_debug, "Sent events to APM Server. Response HTTP code: %ld. URL: `%s'.", responseCode, url );
479+
resultCode = isFailed ? resultFailure : resultSuccess;
473480
finally:
474481
ELASTIC_APM_LOG_DEBUG_RESULT_CODE_FUNCTION_EXIT();
475482
return resultCode;
@@ -505,19 +512,27 @@ ResultCode syncSendEventsToApmServer( const ConfigSnapshot* config, StringView u
505512
ELASTIC_APM_SET_RESULT_CODE_TO_SUCCESS_AND_GOTO_FINALLY();
506513
}
507514

515+
if ( backendCommBackoff_shouldWait( &connectionData->backoff ) )
516+
{
517+
ELASTIC_APM_LOG_DEBUG( "Backoff wait time has not elapsed yet - discarding events instead of sending" );
518+
ELASTIC_APM_SET_RESULT_CODE_TO_SUCCESS_AND_GOTO_FINALLY();
519+
}
520+
508521
if ( connectionData->curlHandle == NULL )
509522
{
510523
ELASTIC_APM_CALL_IF_FAILED_GOTO( initConnectionData( config, connectionData, userAgentHttpHeader ) );
511524
}
512525

513526
ELASTIC_APM_CALL_IF_FAILED_GOTO( syncSendEventsToApmServerWithConn( config, connectionData, serializedEvents ) );
527+
backendCommBackoff_onSuccess( &connectionData->backoff );
514528

515529
resultCode = resultSuccess;
516530
finally:
517531
ELASTIC_APM_LOG_DEBUG_RESULT_CODE_FUNCTION_EXIT();
518532
return resultCode;
519533

520534
failure:
535+
backendCommBackoff_onError( &connectionData->backoff );
521536
cleanupConnectionData( connectionData );
522537
goto finally;
523538
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#include "backend_comm_backoff.h"
21+
#include <stdlib.h>
22+
#include <math.h>
23+
#include "basic_macros.h"
24+
#include "log.h"
25+
#include "time_util.h"
26+
27+
#define ELASTIC_APM_CURRENT_LOG_CATEGORY ELASTIC_APM_LOG_CATEGORY_BACKEND_COMM
28+
29+
/**
30+
* Algorithm is based on Elastic APM agent spec's "Transport errors" section
31+
*
32+
* @see https://github.com/elastic/apm/blob/d8cb5607dbfffea819ab5efc9b0743044772fb23/specs/agents/transport.md#transport-errors
33+
*/
34+
35+
void backendCommBackoff_onSuccess( BackendCommBackoff* thisObj )
36+
{
37+
ELASTIC_APM_ASSERT_VALID_PTR( thisObj );
38+
39+
thisObj->errorCount = 0;
40+
thisObj->waitEndTime = (TimeSpec){ 0 };
41+
}
42+
43+
bool backendCommBackoff_getCurrentTime( BackendCommBackoff* thisObj, /* out */ TimeSpec* currentTime )
44+
{
45+
ResultCode resultCode;
46+
ELASTIC_APM_CALL_IF_FAILED_GOTO( getClockTimeSpec( /* isRealTime */ false, /* out */ currentTime ) );
47+
48+
resultCode = resultSuccess;
49+
finally:
50+
ELASTIC_APM_LOG_DEBUG_RESULT_CODE_FUNCTION_EXIT();
51+
return resultCode == resultSuccess;
52+
53+
failure:
54+
ELASTIC_APM_LOG_ERROR( "Failed to get current time" );
55+
goto finally;
56+
}
57+
58+
void backendCommBackoff_onError( BackendCommBackoff* thisObj )
59+
{
60+
ELASTIC_APM_ASSERT_VALID_PTR( thisObj );
61+
62+
ELASTIC_APM_LOG_DEBUG_FUNCTION_ENTRY();
63+
64+
/**
65+
* The grace period should be calculated in seconds using the algorithm min(reconnectCount++, 6) ** 2 ± 10%
66+
*
67+
* @see https://github.com/elastic/apm/blob/d8cb5607dbfffea819ab5efc9b0743044772fb23/specs/agents/transport.md#transport-errors
68+
*/
69+
enum { maxSequentialErrorsCount = 7 };
70+
71+
if ( thisObj->errorCount < maxSequentialErrorsCount )
72+
{
73+
++thisObj->errorCount;
74+
}
75+
76+
if ( ! backendCommBackoff_getCurrentTime( thisObj, /* out */ &thisObj->waitEndTime ) )
77+
{
78+
// If we cannot get current time we just reset the state to that of no errors
79+
backendCommBackoff_onSuccess( thisObj );
80+
return;
81+
}
82+
addDelayToAbsTimeSpec( /* in, out */ &thisObj->waitEndTime, /* delayInNanoseconds */ (long)backendCommBackoff_getTimeToWaitInSeconds( thisObj ) * ELASTIC_APM_NUMBER_OF_NANOSECONDS_IN_SECOND );
83+
}
84+
85+
int backendCommBackoff_convertRandomUIntToJitter( UInt randomVal, UInt jitterHalfRange )
86+
{
87+
double diff = randomVal - ( RAND_MAX / 2.0 );
88+
return ( diff >= 0 ? 1 : -1 ) * ( (int) floor( ( jitterHalfRange * fabs( diff ) ) / ( RAND_MAX / 2.0 ) ) );
89+
}
90+
91+
UInt backendCommBackoff_getTimeToWaitInSeconds( const BackendCommBackoff* thisObj )
92+
{
93+
ELASTIC_APM_ASSERT_VALID_PTR( thisObj );
94+
95+
if ( thisObj->errorCount == 0 )
96+
{
97+
return 0;
98+
}
99+
100+
UInt reconnectCount = ( thisObj->errorCount - 1);
101+
double timeToWaitWithoutJitter = pow( reconnectCount, 2 );
102+
double jitterHalfRange = timeToWaitWithoutJitter * 0.1;
103+
UInt jitter = jitterHalfRange < 1 ? 0 : backendCommBackoff_convertRandomUIntToJitter( thisObj->generateRandomUInt( thisObj->generateRandomUIntCtx ), (UInt) floor( jitterHalfRange ) );
104+
105+
return (int)( round( timeToWaitWithoutJitter ) ) + jitter;
106+
}
107+
108+
#pragma clang diagnostic push
109+
#pragma ide diagnostic ignored "UnusedParameter"
110+
UInt backendCommBackoff_defaultGenerateRandomUInt( void* ctx )
111+
#pragma clang diagnostic pop
112+
{
113+
return (UInt) rand(); // NOLINT(cert-msc50-cpp)
114+
}
115+
116+
bool backendCommBackoff_shouldWait( BackendCommBackoff* thisObj )
117+
{
118+
if ( thisObj->errorCount == 0 )
119+
{
120+
return false;
121+
}
122+
123+
TimeSpec currentTime;
124+
if ( ! backendCommBackoff_getCurrentTime( thisObj, /* out */ &currentTime ) )
125+
{
126+
// If we cannot get current time we just reset the state to that of no errors
127+
backendCommBackoff_onSuccess( thisObj );
128+
return false;
129+
}
130+
131+
if ( compareAbsTimeSpecs( &thisObj->waitEndTime, &currentTime ) <= 0 )
132+
{
133+
return false;
134+
}
135+
136+
char txtOutStreamBuf[ ELASTIC_APM_TEXT_OUTPUT_STREAM_ON_STACK_BUFFER_SIZE ];
137+
TextOutputStream txtOutStream = ELASTIC_APM_TEXT_OUTPUT_STREAM_FROM_STATIC_BUFFER( txtOutStreamBuf );
138+
ELASTIC_APM_LOG_TRACE( "Left to wait: %s, errorCount: %u", streamTimeSpecDiff( &currentTime, &thisObj->waitEndTime, &txtOutStream ), thisObj->errorCount );
139+
return true;
140+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#pragma once
21+
22+
#include "basic_types.h"
23+
#include "time_util.h"
24+
25+
typedef UInt (* GenerateRandomUInt )( void* ctx );
26+
27+
struct BackendCommBackoff
28+
{
29+
GenerateRandomUInt generateRandomUInt;
30+
void* generateRandomUIntCtx;
31+
UInt errorCount;
32+
TimeSpec waitEndTime;
33+
};
34+
typedef struct BackendCommBackoff BackendCommBackoff;
35+
36+
void backendCommBackoff_onSuccess( BackendCommBackoff* thisObj );
37+
void backendCommBackoff_onError( BackendCommBackoff* thisObj );
38+
bool backendCommBackoff_shouldWait( BackendCommBackoff* thisObj );
39+
40+
UInt backendCommBackoff_getTimeToWaitInSeconds( const BackendCommBackoff* thisObj );
41+
int backendCommBackoff_convertRandomUIntToJitter( UInt randomVal, UInt jitterHalfRange );
42+
UInt backendCommBackoff_defaultGenerateRandomUInt( void* ctx );
43+
44+
#define ELASTIC_APM_DEFAULT_BACKEND_COMM_BACKOFF \
45+
((BackendCommBackoff) \
46+
{ \
47+
.generateRandomUInt = &backendCommBackoff_defaultGenerateRandomUInt, \
48+
.generateRandomUIntCtx = NULL, \
49+
.errorCount = 0, \
50+
.waitEndTime = { 0 } \
51+
}) \
52+
/**/

agent/native/ext/config.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ if test "$PHP_ELASTIC_APM" != "no"; then
8282
AST_debug.c \
8383
AST_instrumentation.c \
8484
backend_comm.c \
85+
backend_comm_backoff.c \
8586
ConfigManager.c \
8687
elastic_apm.c \
8788
elastic_apm_API.c \

agent/native/ext/config.w32

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ if (PHP_ELASTIC_APM != 'no') {
1616
"AST_debug.c" + " " +
1717
"AST_instrumentation.c" + " " +
1818
"backend_comm.c" + " " +
19+
"backend_comm_backoff.c" + " " +
1920
"ConfigManager.c" + " " +
2021
"elastic_apm.c" + " " +
2122
"elastic_apm_API.c" + " " +

agent/native/ext/elastic_apm.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ PHP_INI_BEGIN()
184184
ELASTIC_APM_INI_ENTRY( ELASTIC_APM_CFG_OPT_NAME_SPAN_COMPRESSION_ENABLED )
185185
ELASTIC_APM_INI_ENTRY( ELASTIC_APM_CFG_OPT_NAME_SPAN_COMPRESSION_EXACT_MATCH_MAX_DURATION )
186186
ELASTIC_APM_INI_ENTRY( ELASTIC_APM_CFG_OPT_NAME_SPAN_COMPRESSION_SAME_KIND_MAX_DURATION )
187+
ELASTIC_APM_INI_ENTRY( ELASTIC_APM_CFG_OPT_NAME_SPAN_STACK_TRACE_MIN_DURATION )
188+
ELASTIC_APM_INI_ENTRY( ELASTIC_APM_CFG_OPT_NAME_STACK_TRACE_LIMIT )
187189
ELASTIC_APM_INI_ENTRY( ELASTIC_APM_CFG_OPT_NAME_TRANSACTION_IGNORE_URLS )
188190
ELASTIC_APM_INI_ENTRY( ELASTIC_APM_CFG_OPT_NAME_TRANSACTION_MAX_SPANS )
189191
ELASTIC_APM_INI_ENTRY( ELASTIC_APM_CFG_OPT_NAME_TRANSACTION_SAMPLE_RATE )

0 commit comments

Comments
 (0)