Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom build with agent disabled by default #1064

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
2 changes: 2 additions & 0 deletions .ci/shared.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export ELASTIC_APM_PHP_TESTS_APP_CODE_HOST_KINDS_SHORT_NAMES=("${ELASTIC_APM_PHP
export ELASTIC_APM_PHP_TESTS_LEAF_GROUPS_SHORT_NAMES=(no_ext_svc with_ext_svc)
export ELASTIC_APM_PHP_TESTS_GROUPS_SHORT_NAMES=("${ELASTIC_APM_PHP_TESTS_LEAF_GROUPS_SHORT_NAMES[@]}" smoke)

export ELASTIC_APM_PHP_TESTS_AGENT_ENABLED_CONFIG_DEFAULT=false

function ensureSyslogIsRunningImpl () {
if ps -ef | grep -v 'grep' | grep -q 'syslogd' ; then
echo 'Syslog is already started.'
Expand Down
8 changes: 7 additions & 1 deletion .ci/static-check-unit-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,14 @@ runPhpCoposerInstall
composer run-script static_check

# Run unit tests
composerCommandToRunUnitTests=(composer run-script --)
phpUnitConfigFile=$(php ./tests/ElasticApmTests/Util/runSelectPhpUnitConfigFile.php --tests-type=unit)
composer run-script -- run_unit_tests_custom_config -c "${phpUnitConfigFile}"
composerCommandToRunUnitTests=("${composerCommandToRunUnitTests[@]}" run_unit_tests_custom_config -c "${phpUnitConfigFile}")
if [ "${ELASTIC_APM_PHP_TESTS_AGENT_ENABLED_CONFIG_DEFAULT:?}" == "false" ]; then
composerCommandToRunUnitTests=("${composerCommandToRunUnitTests[@]}" --filter AgentEnabledConfigUnitTest)
fi
echo "composerCommandToRunUnitTests: ${composerCommandToRunUnitTests[@]}"
"${composerCommandToRunUnitTests[@]}"
ls -l ./build/unit-tests-phpunit-junit.xml

# Generate junit output for phpstan
Expand Down
16 changes: 10 additions & 6 deletions .ci/validate_agent_installation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,16 @@ function runComponentTests () {
phpUnitConfigFile=$(php ./tests/ElasticApmTests/Util/runSelectPhpUnitConfigFile.php --tests-type=component)
composerCommand=("${composerCommand[@]}" -c "${phpUnitConfigFile}")

if [ -n "${ELASTIC_APM_PHP_TESTS_GROUP}" ] ; then
composerCommand=("${composerCommand[@]}" --group "${ELASTIC_APM_PHP_TESTS_GROUP}")
fi

if [ -n "${ELASTIC_APM_PHP_TESTS_FILTER}" ] ; then
composerCommand=("${composerCommand[@]}" --filter "${ELASTIC_APM_PHP_TESTS_FILTER}")
if [ "${ELASTIC_APM_PHP_TESTS_AGENT_ENABLED_CONFIG_DEFAULT:?}" == "true" ]; then
if [ -n "${ELASTIC_APM_PHP_TESTS_GROUP}" ] ; then
composerCommand=("${composerCommand[@]}" --group "${ELASTIC_APM_PHP_TESTS_GROUP}")
fi

if [ -n "${ELASTIC_APM_PHP_TESTS_FILTER}" ] ; then
composerCommand=("${composerCommand[@]}" --filter "${ELASTIC_APM_PHP_TESTS_FILTER}")
fi
else
composerCommand=("${composerCommand[@]}" --filter AgentEnabledConfigComponentTest)
fi

local initialTimeoutInMinutes=30
Expand Down
2 changes: 1 addition & 1 deletion agent/native/ext/ConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1034,7 +1034,7 @@ static void initOptionsMetadata( OptionMetadata* optsMeta )
buildBoolOptionMetadata,
enabled,
ELASTIC_APM_CFG_OPT_NAME_ENABLED,
/* defaultValue: */ true );
/* defaultValue: */ false );

ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
Expand Down
23 changes: 21 additions & 2 deletions agent/native/ext/lifecycle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,22 @@ static void unregisterErrorAndExceptionHooks() {

}

void logImportantAgentInfo( const ConfigSnapshot* config, String calledFromFunc )
{
ELASTIC_APM_LOG_INFO(
"Custom build based on version: %s"
"; Custom changes:"
" * agent is disabled by default (enabled: false)"
"; config->enabled: %s."
"; SAPI module name: %s"
"; Called from: %s"
, PHP_ELASTIC_APM_VERSION
, boolToString( config->enabled )
, getPhpSapiModuleName()
, calledFromFunc
);
}

void elasticApmModuleInit( int moduleType, int moduleNumber )
{
ELASTIC_APM_LOG_DIRECT_DEBUG( "%s entered: moduleType: %d, moduleNumber: %d, parent PID: %d", __FUNCTION__, moduleType, moduleNumber, (int)(getParentProcessId()) );
Expand All @@ -526,10 +542,11 @@ void elasticApmModuleInit( int moduleType, int moduleNumber )
ELASTIC_APM_CALL_IF_FAILED_GOTO( ensureLoggerInitialConfigIsLatest( tracer ) );
ELASTIC_APM_CALL_IF_FAILED_GOTO( ensureAllComponentsHaveLatestConfig( tracer ) );

logSupportabilityInfo( logLevel_debug );

config = getTracerCurrentConfigSnapshot( tracer );

logImportantAgentInfo( config, __FUNCTION__ );
logSupportabilityInfo( logLevel_debug );

if ( ! config->enabled )
{
resultCode = resultSuccess;
Expand Down Expand Up @@ -580,6 +597,8 @@ void elasticApmModuleShutdown( int moduleType, int moduleNumber )
Tracer* const tracer = getGlobalTracer();
const ConfigSnapshot* const config = getTracerCurrentConfigSnapshot( tracer );

logImportantAgentInfo( config, __FUNCTION__ );

if ( ! config->enabled )
{
resultCode = resultSuccess;
Expand Down
8 changes: 5 additions & 3 deletions agent/native/ext/tests/config_defaults.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ elasticApmAssertSame("getenv('ELASTIC_APM_ENABLED')", getenv('ELASTIC_APM_ENABLE

elasticApmAssertEqual("ini_get('elastic_apm.enabled')", ini_get('elastic_apm.enabled'), false);

elasticApmAssertSame("elastic_apm_is_enabled()", elastic_apm_is_enabled(), true);

elasticApmAssertSame("elastic_apm_get_config_option_by_name('enabled')", elastic_apm_get_config_option_by_name('enabled'), true);
if (($agentEnabledConfigDefaultEnvVar = getenv('ELASTIC_APM_PHP_TESTS_AGENT_ENABLED_CONFIG_DEFAULT')) !== false) {
$agentEnabledConfigDefault = json_decode($agentEnabledConfigDefaultEnvVar);
elasticApmAssertSame("elastic_apm_is_enabled()", elastic_apm_is_enabled(), $agentEnabledConfigDefault);
elasticApmAssertSame("elastic_apm_get_config_option_by_name('enabled')", elastic_apm_get_config_option_by_name('enabled'), $agentEnabledConfigDefault);
}

//////////////////////////////////////////////
/////////////// log_file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ require __DIR__ . '/../tests_util/tests_util.php';

elasticApmAssertSame("getenv('ELASTIC_APM_ENABLED')", getenv('ELASTIC_APM_ENABLED'), 'not_valid_boolean_value');

elasticApmAssertSame("elastic_apm_is_enabled()", elastic_apm_is_enabled(), true);

elasticApmAssertSame("elastic_apm_get_config_option_by_name('enabled')", elastic_apm_get_config_option_by_name('enabled'), true);
if (($agentEnabledConfigDefaultEnvVar = getenv('ELASTIC_APM_PHP_TESTS_AGENT_ENABLED_CONFIG_DEFAULT')) !== false) {
$agentEnabledConfigDefault = json_decode($agentEnabledConfigDefaultEnvVar);
elasticApmAssertSame("elastic_apm_is_enabled()", elastic_apm_is_enabled(), $agentEnabledConfigDefault);
elasticApmAssertSame("elastic_apm_get_config_option_by_name('enabled')", elastic_apm_get_config_option_by_name('enabled'), $agentEnabledConfigDefault);
}

//////////////////////////////////////////////
/////////////// assert_level
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ require __DIR__ . '/../tests_util/tests_util.php';

elasticApmAssertEqual("ini_get('elastic_apm.enabled')", ini_get('elastic_apm.enabled'), 'not valid boolean value');

elasticApmAssertSame("elastic_apm_get_config_option_by_name('enabled')", elastic_apm_get_config_option_by_name('enabled'), true);

elasticApmAssertSame("elastic_apm_is_enabled()", elastic_apm_is_enabled(), true);
if (($agentEnabledConfigDefaultEnvVar = getenv('ELASTIC_APM_PHP_TESTS_AGENT_ENABLED_CONFIG_DEFAULT')) !== false) {
$agentEnabledConfigDefault = json_decode($agentEnabledConfigDefaultEnvVar);
elasticApmAssertSame("elastic_apm_is_enabled()", elastic_apm_is_enabled(), $agentEnabledConfigDefault);
elasticApmAssertSame("elastic_apm_get_config_option_by_name('enabled')", elastic_apm_get_config_option_by_name('enabled'), $agentEnabledConfigDefault);
}

//////////////////////////////////////////////
/////////////// assert_level
Expand Down
5 changes: 5 additions & 0 deletions agent/native/ext/util_for_PHP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,11 @@ ResultCode callPhpFunctionRetZval( StringView phpFunctionName, uint32_t argsCoun
return callPhpFunction( phpFunctionName, argsCount, args, consumeZvalRetVal, retVal );
}

String getPhpSapiModuleName()
{
return sapi_module.name;
}

bool isPhpRunningAsCliScript()
{
return strcmp( sapi_module.name, "cli" ) == 0;
Expand Down
1 change: 1 addition & 0 deletions agent/native/ext/util_for_PHP.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ ResultCode callPhpFunctionRetZval( StringView phpFunctionName, uint32_t argsCoun

void getArgsFromZendExecuteData( zend_execute_data *execute_data, size_t dstArraySize, zval dstArray[], uint32_t* argsCount );

String getPhpSapiModuleName();
bool isPhpRunningAsCliScript();
bool detectOpcachePreload();
bool isScriptRestricedByOpcacheAPI();
Expand Down
2 changes: 1 addition & 1 deletion agent/php/ElasticApm/Impl/Config/AllOptionsMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public static function get(): array
OptionNames::DEV_INTERNAL => new NullableWildcardListOptionMetadata(),
OptionNames::DISABLE_INSTRUMENTATIONS => new NullableWildcardListOptionMetadata(),
OptionNames::DISABLE_SEND => new BoolOptionMetadata(/* default */ false),
OptionNames::ENABLED => new BoolOptionMetadata(/* default */ true),
OptionNames::ENABLED => new BoolOptionMetadata(/* default */ false),
OptionNames::ENVIRONMENT => new NullableStringOptionMetadata(),
OptionNames::GLOBAL_LABELS => new NullableLabelsOptionMetadata(),
OptionNames::HOSTNAME => new NullableStringOptionMetadata(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php

/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. 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.
*/

declare(strict_types=1);

namespace ElasticApmTests\ComponentTests;

use Elastic\Apm\Impl\Config\OptionNames;
use ElasticApmTests\ComponentTests\Util\AmbientContextForTests;
use ElasticApmTests\ComponentTests\Util\AppCodeHostParams;
use ElasticApmTests\ComponentTests\Util\AppCodeRequestParams;
use ElasticApmTests\ComponentTests\Util\AppCodeTarget;
use ElasticApmTests\ComponentTests\Util\ComponentTestCaseBase;
use ElasticApmTests\Util\AssertMessageStack;
use ElasticApmTests\Util\DataProviderForTestBuilder;
use ElasticApmTests\Util\MixedMap;

/**
* @group smoke
* @group does_not_require_external_services
*/
final class AgentEnabledConfigComponentTest extends ComponentTestCaseBase
{
public static function appCodeForTestAgentEnabledConfig(MixedMap $appCodeArgs): void
{
$agentEnabledExpected = $appCodeArgs->getBool(OptionNames::ENABLED);

/**
* elastic_apm_* functions are provided by the elastic_apm extension
*
* @noinspection PhpFullyQualifiedNameUsageInspection, PhpUndefinedFunctionInspection
* @phpstan-ignore-next-line
*/
$agentEnabledAsSeenByNativePart = \elastic_apm_is_enabled();
self::assertSame($agentEnabledExpected, $agentEnabledAsSeenByNativePart);
}

/**
* @return iterable<string, array{MixedMap}>
*/
public static function dataProviderForTestAgentEnabledConfig(): iterable
{
$result = (new DataProviderForTestBuilder())
->addKeyedDimensionAllValuesCombinable(OptionNames::ENABLED, [null, true, false])
->build();

return DataProviderForTestBuilder::convertEachDataSetToMixedMap($result);
}

/**
* @dataProvider dataProviderForTestAgentEnabledConfig
*/
public function testAgentEnabledConfig(MixedMap $testArgs): void
{
AssertMessageStack::newScope(/* out */ $dbgCtx, AssertMessageStack::funcArgs());

$testCaseHandle = $this->getTestCaseHandle();
$appCodeHost = $testCaseHandle->ensureMainAppCodeHost(
function (AppCodeHostParams $appCodeParams) use ($testArgs): void {
self::setConfigIfNotNull($testArgs, OptionNames::ENABLED, $appCodeParams);
}
);

$agentEnabledTestArg = $testArgs->getNullableBool(OptionNames::ENABLED);
$agentEnabledActual = $appCodeHost->appCodeHostParams->getEffectiveAgentConfig()->enabled();
if (($agentEnabledExpected = $agentEnabledTestArg ?? AmbientContextForTests::testConfig()->agentEnabledConfigDefault) !== null) {
self::assertSame($agentEnabledExpected, $agentEnabledActual);
}

$appCodeHost->sendRequest(
AppCodeTarget::asRouted([__CLASS__, 'appCodeForTestAgentEnabledConfig']),
function (AppCodeRequestParams $appCodeRequestParams) use ($agentEnabledActual): void {
$appCodeRequestParams->setAppCodeArgs([OptionNames::ENABLED => $agentEnabledActual]);
}
);

if ($agentEnabledActual) {
$dataFromAgent = $this->waitForOneEmptyTransaction($testCaseHandle);
self::assertCount(1, $dataFromAgent->idToTransaction);
self::assertCount(1, $dataFromAgent->metadatas);
} else {
$logger = self::getLoggerStatic(__NAMESPACE__, __CLASS__, __FILE__);
$waitTimeSeconds = 5;
($loggerProxy = $logger->ifInfoLevelEnabled(__LINE__, __FUNCTION__))
&& $loggerProxy->log('Sleeping ' . $waitTimeSeconds . ' seconds to give agent enough time to send data (which it should not since it is disabled)...');
sleep($waitTimeSeconds);
$dataFromAgent = $testCaseHandle->getDataFromAgentWithoutWaiting();
self::assertCount(0, $dataFromAgent->idToTransaction);
self::assertCount(0, $dataFromAgent->metadatas);
}
self::assertCount(0, $dataFromAgent->idToSpan);
self::assertCount(0, $dataFromAgent->idToError);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -567,8 +567,10 @@ protected static function disableTimingDependentFeatures(AppCodeHostParams $appC

protected static function setConfigIfNotNull(MixedMap $testArgs, string $optName, AppCodeHostParams $appCodeParams): void
{
$optVal = $testArgs->getNullableString($optName);
$optVal = $testArgs->get($optName);
if ($optVal !== null) {
self::assertTrue(is_string($optVal) || is_int($optVal) || is_float($optVal) || is_bool($optVal));
/** @var string|int|float|bool $optVal */
$appCodeParams->setAgentOption($optName, $optVal);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ final class ConfigSnapshotForTests implements LoggableInterface
/** @var bool */
public $deleteTempPhpIni;

/** @var ?bool */
public $agentEnabledConfigDefault = null;

/** @var ?WildcardListMatcher */
public $envVarsToPassThrough;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public function __construct()
{
$this->perDataKind = [];
$this->errors(0);
$this->setValueForKind(ApmDataKind::metadata(), 1);
$this->metadatas(1);
$this->metricSets(0);
$this->spans(0);
$this->transactions(1);
Expand All @@ -65,6 +65,11 @@ private function setValueForKind(ApmDataKind $apmDataKind, ?int $count): self
return $this;
}

public function metadatas(int $count): self
{
return $this->setValueForKind(ApmDataKind::metadata(), $count);
}

public function errors(int $count): self
{
return $this->setValueForKind(ApmDataKind::error(), $count);
Expand Down
7 changes: 7 additions & 0 deletions tests/ElasticApmTests/ComponentTests/Util/TestCaseHandle.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ function (HttpAppCodeHostParams $appCodeHostParams) use ($setParamsFunc): void {
return $this->additionalHttpAppCodeHost;
}

public function getDataFromAgentWithoutWaiting(): DataFromAgentPlusRaw
{
$dataFromAgentAccumulator = new DataFromAgentPlusRawAccumulator();
$dataFromAgentAccumulator->addReceiverEvents($this->mockApmServer->fetchNewData(/* shouldWait */ false));
return $dataFromAgentAccumulator->getAccumulatedData();
}

public function waitForDataFromAgent(ExpectedEventCounts $expectedEventCounts, bool $shouldValidate = true): DataFromAgentPlusRaw
{
TestCaseBase::assertNotEmpty($this->appCodeInvocations);
Expand Down
45 changes: 45 additions & 0 deletions tests/ElasticApmTests/UnitTests/AgentEnabledConfigUnitTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. 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.
*/

/** @noinspection PhpUnhandledExceptionInspection */

declare(strict_types=1);

namespace ElasticApmTests\UnitTests;

use Elastic\Apm\Impl\Config\AllOptionsMetadata;
use Elastic\Apm\Impl\Config\OptionNames;
use Elastic\Apm\Impl\Log\NoopLoggerFactory;
use ElasticApmTests\ComponentTests\Util\ConfigUtilForTests;
use ElasticApmTests\Util\TestCaseBase;

final class AgentEnabledConfigUnitTest extends TestCaseBase
{
public function testDefaultAsSeenByPhpPart(): void
{
$configForTests = ConfigUtilForTests::read(/* additionalConfigSource */ null, NoopLoggerFactory::singletonInstance());
if ($configForTests->agentEnabledConfigDefault === null) {
self::dummyAssert();
return;
}
self::assertSame($configForTests->agentEnabledConfigDefault, AllOptionsMetadata::get()[OptionNames::ENABLED]->defaultValue());
}
}
Loading