agent/native/ext/ConfigManager.cpp (1,539 lines of code) (raw):
/*
* 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.
*/
#include "ConfigManager.h"
#include "ConfigSnapshot.h"
#ifdef ELASTIC_APM_MOCK_STDLIB
# include "mock_stdlib.h"
#else
# include <stdlib.h>
#endif
#ifndef ELASTIC_APM_MOCK_PHP_DEPS
# include <zend_ini.h>
#endif
#include "elastic_apm_assert.h"
#include "log.h"
#include "util.h"
#include "TextOutputStream.h"
#include "elastic_apm_alloc.h"
#include "time_util.h"
#define ELASTIC_APM_CURRENT_LOG_CATEGORY ELASTIC_APM_LOG_CATEGORY_CONFIG
enum ParsedOptionValueType
{
parsedOptionValueType_undefined = 0,
parsedOptionValueType_bool,
parsedOptionValueType_optionalBool,
parsedOptionValueType_string,
parsedOptionValueType_int,
parsedOptionValueType_duration,
parsedOptionValueType_size,
end_parsedOptionValueType
};
typedef enum ParsedOptionValueType ParsedOptionValueType;
#define ELASTIC_APM_ASSERT_VALID_PARSED_OPTION_VALUE_TYPE( valueType ) \
ELASTIC_APM_ASSERT_IN_END_EXCLUDED_RANGE_UINT64( parsedOptionValueType_undefined + 1, valueType, end_parsedOptionValueType )
/**/
struct ParsedOptionValue
{
ParsedOptionValue() { // TODO = delete
}
ParsedOptionValue(bool value) : type{parsedOptionValueType_bool}, u{value} {
}
ParsedOptionValue(OptionalBool value) : type{parsedOptionValueType_optionalBool}, u{value} {
}
ParsedOptionValue(String value) : type{parsedOptionValueType_string}, u{value} {
}
ParsedOptionValue(int value) : type{parsedOptionValueType_int}, u{value} {
}
ParsedOptionValue(Duration value) : type{parsedOptionValueType_duration}, u{value} {
}
ParsedOptionValue(Size value) : type{parsedOptionValueType_size}, u{value} {
}
ParsedOptionValueType type = ParsedOptionValueType::parsedOptionValueType_undefined;
union u
{
u() : boolValue(false) {} // TODO = delete;
u(bool value) : boolValue(value) {}
u(OptionalBool value) : optionalBoolValue(value) {}
u(String value) : stringValue(value) {}
u(int value) : intValue(value) {}
u(Duration value) : durationValue(value) {}
u(Size value) : sizeValue(value) {}
bool boolValue;
OptionalBool optionalBoolValue;
String stringValue;
int intValue;
Duration durationValue;
Size sizeValue;
} u;
};
typedef struct ParsedOptionValue ParsedOptionValue;
#define ELASTIC_APM_ASSERT_VALID_PARSED_OPTION_VALUE( parsedOptionValue ) \
ELASTIC_APM_ASSERT_VALID_PARSED_OPTION_VALUE_TYPE( (parsedOptionValue).type )
struct EnumOptionAdditionalMetadata
{
String* names = nullptr;
size_t enumElementsCount = 0;
bool isUniquePrefixEnough = false;
};
typedef struct EnumOptionAdditionalMetadata EnumOptionAdditionalMetadata;
struct DurationOptionAdditionalMetadata
{
DurationUnits defaultUnits = durationUnits_millisecond;
bool isNegativeValid = false;
};
typedef struct DurationOptionAdditionalMetadata DurationOptionAdditionalMetadata;
struct SizeOptionAdditionalMetadata
{
SizeUnits defaultUnits = sizeUnits_byte;
};
typedef struct SizeOptionAdditionalMetadata SizeOptionAdditionalMetadata;
union OptionAdditionalMetadata
{
EnumOptionAdditionalMetadata enumData;
DurationOptionAdditionalMetadata durationData;
SizeOptionAdditionalMetadata sizeData;
};
typedef union OptionAdditionalMetadata OptionAdditionalMetadata;
struct OptionMetadata;
typedef struct OptionMetadata OptionMetadata;
typedef String (* InterpretIniRawValueFunc )( String rawValue );
typedef ResultCode (* ParseRawValueFunc )( const OptionMetadata* optMeta, String rawValue, /* out */ ParsedOptionValue* parsedValue );
typedef String (* StreamParsedValueFunc )( const OptionMetadata* optMeta, ParsedOptionValue parsedValue, TextOutputStream* txtOutStream );
typedef void (* SetConfigSnapshotFieldFunc )( const OptionMetadata* optMeta, ParsedOptionValue parsedValue, ConfigSnapshot* dst );
typedef ParsedOptionValue (* GetConfigSnapshotFieldFunc )( const OptionMetadata* optMeta, const ConfigSnapshot* src );
typedef void (* ParsedOptionValueToZvalFunc )( const OptionMetadata* optMeta, ParsedOptionValue parsedValue, zval* return_value );
struct OptionMetadata
{
String name = nullptr;
StringView iniName = {nullptr, 0};
bool isSecret = false;
bool isDynamic = false;
bool isLoggingRelated = false;
ParsedOptionValue defaultValue;
InterpretIniRawValueFunc interpretIniRawValue = nullptr;
ParseRawValueFunc parseRawValue = nullptr;
StreamParsedValueFunc streamParsedValue = nullptr;
SetConfigSnapshotFieldFunc setField = nullptr;
GetConfigSnapshotFieldFunc getField = nullptr;
ParsedOptionValueToZvalFunc parsedValueToZval = nullptr;
OptionAdditionalMetadata additionalData = {};
};
struct RawConfigSnapshot
{
String original[ numberOfOptions ];
String interpreted[ numberOfOptions ];
};
typedef struct RawConfigSnapshot RawConfigSnapshot;
struct RawConfigSnapshotSource;
typedef struct RawConfigSnapshotSource RawConfigSnapshotSource;
typedef ResultCode (* GetRawOptionValueFunc )(
const ConfigManager* configManager,
OptionId optId,
String* originalRawValue,
String* interpretedRawValue );
struct RawConfigSnapshotSource
{
String description = nullptr;
GetRawOptionValueFunc getOptionValue = nullptr;
};
struct CombinedRawConfigSnapshot
{
String original[ numberOfOptions ];
String interpreted[ numberOfOptions ];
String sourceDescriptions[ numberOfOptions ];
};
typedef struct CombinedRawConfigSnapshot CombinedRawConfigSnapshot;
struct ConfigRawData
{
RawConfigSnapshot fromSources[ numberOfRawConfigSources ];
CombinedRawConfigSnapshot combined;
};
typedef struct ConfigRawData ConfigRawData;
struct ConfigMetadata
{
OptionMetadata optionsMeta[ numberOfOptions ];
String envVarNames[ numberOfOptions ] = { nullptr };
RawConfigSnapshotSource rawCfgSources[ numberOfRawConfigSources ];
};
typedef struct ConfigMetadata ConfigMetadata;
struct ConfigManagerCurrentState
{
ConfigRawData* rawData = nullptr;
ConfigSnapshot snapshot = {};
};
typedef struct ConfigManagerCurrentState ConfigManagerCurrentState;
struct ConfigManager
{
bool isLoggingRelatedOnly = false;
ConfigMetadata meta = {};
ConfigManagerCurrentState current = {};
};
#define ELASTIC_APM_ASSERT_VALID_OPTION_ID( optId ) \
ELASTIC_APM_ASSERT_IN_END_EXCLUDED_RANGE_UINT64( 0, optId, numberOfOptions )
String interpretStringIniRawValue( String rawValue )
{
return rawValue;
}
String interpretBoolIniRawValue( String rawValue )
{
// When PHP engine parses php.ini it automatically converts "true", "on" and "yes" to "1" (meaning true)
// and "false", "off", "no" and "none" to "" (empty string, meaning false)
// https://www.php.net/manual/en/function.parse-ini-file.php
if ( rawValue != NULL && isEmtpyString( rawValue ) ) return "false";
return rawValue;
}
String interpretOptionalBoolIniRawValue( String rawValue )
{
return interpretBoolIniRawValue( rawValue );
}
String interpretEmptyIniRawValueAsOff( String rawValue )
{
// When PHP engine parses php.ini it automatically converts "true", "on" and "yes" to "1" (meaning true)
// and "false", "off", "no" and "none" to "" (empty string, meaning false)
// https://www.php.net/manual/en/function.parse-ini-file.php
if ( rawValue != NULL && isEmtpyString( rawValue ) ) return "off";
return rawValue;
}
static ResultCode parseStringValue( const OptionMetadata* optMeta, String rawValue, /* out */ ParsedOptionValue* parsedValue )
{
ELASTIC_APM_ASSERT_VALID_PTR( optMeta );
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_string );
ELASTIC_APM_ASSERT_VALID_PTR( rawValue );
ELASTIC_APM_ASSERT_VALID_PTR( parsedValue );
ELASTIC_APM_ASSERT_EQ_UINT64( parsedValue->type, parsedOptionValueType_undefined );
ELASTIC_APM_ASSERT_PTR_IS_NULL( parsedValue->u.stringValue );
parsedValue->u.stringValue = rawValue;
parsedValue->type = optMeta->defaultValue.type;
return resultSuccess;
}
static String streamParsedString( const OptionMetadata* optMeta, ParsedOptionValue parsedValue, TextOutputStream* txtOutStream )
{
ELASTIC_APM_ASSERT_VALID_PTR( optMeta );
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_string );
ELASTIC_APM_ASSERT_VALID_PARSED_OPTION_VALUE( parsedValue );
ELASTIC_APM_ASSERT_EQ_UINT64( parsedValue.type, optMeta->defaultValue.type );
return streamUserString( parsedValue.u.stringValue, txtOutStream );
}
static void parsedStringValueToZval( const OptionMetadata* optMeta, ParsedOptionValue parsedValue, zval* return_value )
{
ELASTIC_APM_ASSERT_VALID_PTR( optMeta );
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_string );
ELASTIC_APM_ASSERT_VALID_PARSED_OPTION_VALUE( parsedValue );
ELASTIC_APM_ASSERT_EQ_UINT64( parsedValue.type, optMeta->defaultValue.type );
ELASTIC_APM_ASSERT_VALID_PTR( return_value );
if ( parsedValue.u.stringValue == NULL ) RETURN_NULL();
RETURN_STRING( parsedValue.u.stringValue );
}
static ResultCode parseBoolValueImpl( const OptionMetadata* optMeta, ParsedOptionValueType expectedType, String rawValue, /* out */ ParsedOptionValue* parsedValue )
{
ELASTIC_APM_ASSERT_VALID_PTR( optMeta );
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, expectedType );
ELASTIC_APM_ASSERT_VALID_PTR( rawValue );
ELASTIC_APM_ASSERT_VALID_PTR( parsedValue );
ELASTIC_APM_ASSERT_EQ_UINT64( parsedValue->type, parsedOptionValueType_undefined );
enum { valuesCount = 4 };
String trueValues[ valuesCount ] = { "true", "1", "yes", "on" };
String falseValues[ valuesCount ] = { "false", "0", "no", "off" };
ELASTIC_APM_FOR_EACH_INDEX( i, valuesCount )
{
if ( areStringsEqualIgnoringCase( rawValue, trueValues[ i ] ) )
{
parsedValue->u.boolValue = true;
parsedValue->type = parsedOptionValueType_bool;
return resultSuccess;
}
if ( areStringsEqualIgnoringCase( rawValue, falseValues[ i ] ) )
{
parsedValue->u.boolValue = false;
parsedValue->type = parsedOptionValueType_bool;
return resultSuccess;
}
}
return resultFailure;
}
static ResultCode parseBoolValue( const OptionMetadata* optMeta, String rawValue, /* out */ ParsedOptionValue* parsedValue )
{
return parseBoolValueImpl( optMeta, parsedOptionValueType_bool, rawValue, /* out */ parsedValue );
}
static String streamParsedBool( const OptionMetadata* optMeta, ParsedOptionValue parsedValue, TextOutputStream* txtOutStream )
{
ELASTIC_APM_ASSERT_VALID_PTR( optMeta );
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_bool );
ELASTIC_APM_ASSERT_VALID_PARSED_OPTION_VALUE( parsedValue );
ELASTIC_APM_ASSERT_EQ_UINT64( parsedValue.type, optMeta->defaultValue.type );
return streamBool( parsedValue.u.boolValue, txtOutStream );
}
static void parsedBoolValueToZval( const OptionMetadata* optMeta, ParsedOptionValue parsedValue, zval* return_value )
{
ELASTIC_APM_ASSERT_VALID_PTR( optMeta );
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_bool );
ELASTIC_APM_ASSERT_VALID_PARSED_OPTION_VALUE( parsedValue );
ELASTIC_APM_ASSERT_EQ_UINT64( parsedValue.type, optMeta->defaultValue.type );
ELASTIC_APM_ASSERT_VALID_PTR( return_value );
RETURN_BOOL( parsedValue.u.boolValue );
}
static ResultCode parseOptionalBoolValue( const OptionMetadata* optMeta, String rawValue, /* out */ ParsedOptionValue* parsedValue )
{
ParsedOptionValue tempParsedValue;
ResultCode resultCode = parseBoolValueImpl( optMeta, parsedOptionValueType_optionalBool, rawValue, /* out */ &tempParsedValue );
if ( resultCode == resultSuccess )
{
parsedValue->u.optionalBoolValue = makeSetOptionalBool( tempParsedValue.u.boolValue );
parsedValue->type = parsedOptionValueType_optionalBool;
}
return resultCode;
}
static String streamParsedOptionalBool( const OptionMetadata* optMeta, ParsedOptionValue parsedValue, TextOutputStream* txtOutStream )
{
ELASTIC_APM_ASSERT_VALID_PTR( optMeta );
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_optionalBool );
ELASTIC_APM_ASSERT_VALID_PARSED_OPTION_VALUE( parsedValue );
ELASTIC_APM_ASSERT_EQ_UINT64( parsedValue.type, optMeta->defaultValue.type );
return streamString( optionalBoolToString( parsedValue.u.optionalBoolValue ), txtOutStream );
}
static void parsedOptionalBoolValueToZval( const OptionMetadata* optMeta, ParsedOptionValue parsedValue, zval* return_value )
{
ELASTIC_APM_ASSERT_VALID_PTR( optMeta );
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_optionalBool );
ELASTIC_APM_ASSERT_VALID_PARSED_OPTION_VALUE( parsedValue );
ELASTIC_APM_ASSERT_EQ_UINT64( parsedValue.type, optMeta->defaultValue.type );
ELASTIC_APM_ASSERT_VALID_PTR( return_value );
RETURN_STRING( optionalBoolToString( parsedValue.u.optionalBoolValue ) );
}
static ResultCode parseDurationValue( const OptionMetadata* optMeta, String rawValue, /* out */ ParsedOptionValue* parsedValue )
{
ELASTIC_APM_ASSERT_VALID_PTR( optMeta );
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_duration );
ELASTIC_APM_ASSERT_VALID_PTR( rawValue );
ELASTIC_APM_ASSERT_VALID_PTR( parsedValue );
ELASTIC_APM_ASSERT_EQ_UINT64( parsedValue->type, parsedOptionValueType_undefined );
ResultCode parseResultCode = parseDuration( stringToView( rawValue )
, optMeta->additionalData.durationData.defaultUnits
, /* out */ &parsedValue->u.durationValue );
if ( parseResultCode == resultSuccess )
{
if ( parsedValue->u.durationValue.valueInUnits < 0 && ! optMeta->additionalData.durationData.isNegativeValid )
{
return resultParsingFailed;
}
parsedValue->type = parsedOptionValueType_duration;
}
return parseResultCode;
}
static String streamParsedDuration( const OptionMetadata* optMeta, ParsedOptionValue parsedValue, TextOutputStream* txtOutStream )
{
ELASTIC_APM_ASSERT_VALID_PTR( optMeta );
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_duration );
ELASTIC_APM_ASSERT_VALID_PARSED_OPTION_VALUE( parsedValue );
ELASTIC_APM_ASSERT_EQ_UINT64( parsedValue.type, optMeta->defaultValue.type );
return streamDuration( parsedValue.u.durationValue, txtOutStream );
}
static void parsedDurationValueToZval( const OptionMetadata* optMeta, ParsedOptionValue parsedValue, zval* return_value )
{
ELASTIC_APM_ASSERT_VALID_PTR( optMeta );
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_duration );
ELASTIC_APM_ASSERT_VALID_PARSED_OPTION_VALUE( parsedValue );
ELASTIC_APM_ASSERT_EQ_UINT64( parsedValue.type, optMeta->defaultValue.type );
ELASTIC_APM_ASSERT_VALID_PTR( return_value );
RETURN_DOUBLE( durationToMilliseconds( parsedValue.u.durationValue ) );
}
static ResultCode parseSizeValue( const OptionMetadata* optMeta, String rawValue, /* out */ ParsedOptionValue* parsedValue )
{
ELASTIC_APM_ASSERT_VALID_PTR( optMeta );
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_size );
ELASTIC_APM_ASSERT_VALID_PTR( rawValue );
ELASTIC_APM_ASSERT_VALID_PTR( parsedValue );
ELASTIC_APM_ASSERT_EQ_UINT64( parsedValue->type, parsedOptionValueType_undefined );
ResultCode parseResultCode = parseSize( stringToView( rawValue )
, optMeta->additionalData.sizeData.defaultUnits
, /* out */ &parsedValue->u.sizeValue );
if ( parseResultCode == resultSuccess ) parsedValue->type = parsedOptionValueType_size;
return parseResultCode;
}
static String streamParsedSize( const OptionMetadata* optMeta, ParsedOptionValue parsedValue, TextOutputStream* txtOutStream )
{
ELASTIC_APM_ASSERT_VALID_PTR( optMeta );
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_size );
ELASTIC_APM_ASSERT_VALID_PARSED_OPTION_VALUE( parsedValue );
ELASTIC_APM_ASSERT_EQ_UINT64( parsedValue.type, optMeta->defaultValue.type );
return streamSize( parsedValue.u.sizeValue, txtOutStream );
}
static void parsedSizeValueToZval( const OptionMetadata* optMeta, ParsedOptionValue parsedValue, zval* return_value )
{
ELASTIC_APM_ASSERT_VALID_PTR( optMeta );
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_size );
ELASTIC_APM_ASSERT_VALID_PARSED_OPTION_VALUE( parsedValue );
ELASTIC_APM_ASSERT_EQ_UINT64( parsedValue.type, optMeta->defaultValue.type );
ELASTIC_APM_ASSERT_VALID_PTR( return_value );
RETURN_DOUBLE( sizeToBytes( parsedValue.u.sizeValue ) );
}
static
ResultCode parseEnumValue( const OptionMetadata* optMeta, String rawValue, /* out */ ParsedOptionValue* parsedValue )
{
ELASTIC_APM_ASSERT_VALID_PTR( optMeta );
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_int );
ELASTIC_APM_ASSERT_VALID_PTR( rawValue );
ELASTIC_APM_ASSERT_VALID_PTR( parsedValue );
ELASTIC_APM_ASSERT_EQ_UINT64( parsedValue->type, parsedOptionValueType_undefined );
int foundMatch = -1;
StringView rawValueStrView = stringToView( rawValue );
ELASTIC_APM_FOR_EACH_INDEX( i, optMeta->additionalData.enumData.enumElementsCount )
{
StringView currentEnumName = stringToView( optMeta->additionalData.enumData.names[ i ] );
if ( ! isStringViewPrefixIgnoringCase( currentEnumName, rawValueStrView ) ) continue;
// If match is exact (i.e., not just prefix) then we return immediately
if ( currentEnumName.length == rawValueStrView.length )
{
foundMatch = (int)i;
break;
}
if ( optMeta->additionalData.enumData.isUniquePrefixEnough )
{
// If there's more than one enum name that raw value matches as a prefix
// then it's ambiguous, and we return failure
if ( foundMatch != -1 )
{
ELASTIC_APM_LOG_ERROR(
"Failed to parse enum configuration option - raw value matches more than one enum as a prefix."
" Option name: `%s'."
" Raw value: `%s'."
" At least the following enums match: `%s' and `%s'."
, optMeta->name
, rawValue
, optMeta->additionalData.enumData.names[ foundMatch ]
, optMeta->additionalData.enumData.names[ i ] );
return resultFailure;
}
foundMatch = (int)i;
}
}
if ( foundMatch == -1 ) return resultFailure;
parsedValue->u.intValue = foundMatch;
parsedValue->type = parsedOptionValueType_int;
return resultSuccess;
}
static void parsedEnumValueToZval( const OptionMetadata* optMeta, ParsedOptionValue parsedValue, zval* return_value )
{
ELASTIC_APM_ASSERT_VALID_PTR( optMeta );
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_int );
ELASTIC_APM_ASSERT_VALID_PARSED_OPTION_VALUE( parsedValue );
ELASTIC_APM_ASSERT_EQ_UINT64( parsedValue.type, optMeta->defaultValue.type );
ELASTIC_APM_ASSERT_VALID_PTR( return_value );
RETURN_LONG( (long)( parsedValue.u.intValue ) );
}
static String streamParsedLogLevel( const OptionMetadata* optMeta, ParsedOptionValue parsedValue, TextOutputStream* txtOutStream )
{
ELASTIC_APM_ASSERT_VALID_PTR( optMeta );
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_int );
ELASTIC_APM_ASSERT_VALID_PARSED_OPTION_VALUE( parsedValue );
ELASTIC_APM_ASSERT_EQ_UINT64( parsedValue.type, optMeta->defaultValue.type );
return streamLogLevel( (LogLevel) parsedValue.u.intValue, txtOutStream );
}
static OptionMetadata buildStringOptionMetadata(
String name
, StringView iniName
, bool isSecret
, bool isDynamic
, String defaultValue
, SetConfigSnapshotFieldFunc setFieldFunc
, GetConfigSnapshotFieldFunc getFieldFunc
)
{
return (OptionMetadata)
{
.name = name,
.iniName = iniName,
.isSecret = isSecret,
.isDynamic = isDynamic,
.isLoggingRelated = false,
.defaultValue = {defaultValue},
.interpretIniRawValue = &interpretStringIniRawValue,
.parseRawValue = &parseStringValue,
.streamParsedValue = &streamParsedString,
.setField = setFieldFunc,
.getField = getFieldFunc,
.parsedValueToZval = &parsedStringValueToZval,
.additionalData = {}
};
}
static OptionMetadata buildLoggingRelatedStringOptionMetadata(
String name
, StringView iniName
, bool isSecret
, bool isDynamic
, String defaultValue
, SetConfigSnapshotFieldFunc setFieldFunc
, GetConfigSnapshotFieldFunc getFieldFunc
)
{
return (OptionMetadata)
{
.name = name,
.iniName = iniName,
.isSecret = isSecret,
.isDynamic = isDynamic,
.isLoggingRelated = true,
.defaultValue = { defaultValue },
.interpretIniRawValue = &interpretStringIniRawValue,
.parseRawValue = &parseStringValue,
.streamParsedValue = &streamParsedString,
.setField = setFieldFunc,
.getField = getFieldFunc,
.parsedValueToZval = &parsedStringValueToZval,
.additionalData = {}
};
}
static OptionMetadata buildBoolOptionMetadata(
String name
, StringView iniName
, bool isSecret
, bool isDynamic
, bool defaultValue
, SetConfigSnapshotFieldFunc setFieldFunc
, GetConfigSnapshotFieldFunc getFieldFunc
)
{
return (OptionMetadata)
{
.name = name,
.iniName = iniName,
.isSecret = isSecret,
.isDynamic = isDynamic,
.isLoggingRelated = false,
.defaultValue = { defaultValue },
.interpretIniRawValue = &interpretBoolIniRawValue,
.parseRawValue = &parseBoolValue,
.streamParsedValue = &streamParsedBool,
.setField = setFieldFunc,
.getField = getFieldFunc,
.parsedValueToZval = &parsedBoolValueToZval,
.additionalData = {}
};
}
static OptionMetadata buildOptionalBoolOptionMetadata(
String name
, StringView iniName
, bool isSecret
, bool isDynamic
, OptionalBool defaultValue
, SetConfigSnapshotFieldFunc setFieldFunc
, GetConfigSnapshotFieldFunc getFieldFunc
)
{
return (OptionMetadata)
{
.name = name,
.iniName = iniName,
.isSecret = isSecret,
.isDynamic = isDynamic,
.isLoggingRelated = false,
.defaultValue = { defaultValue },
.interpretIniRawValue = &interpretOptionalBoolIniRawValue,
.parseRawValue = &parseOptionalBoolValue,
.streamParsedValue = &streamParsedOptionalBool,
.setField = setFieldFunc,
.getField = getFieldFunc,
.parsedValueToZval = &parsedOptionalBoolValueToZval,
.additionalData = {}
};
}
static OptionMetadata buildDurationOptionMetadata(
String name
, StringView iniName
, bool isSecret
, bool isDynamic
, Duration defaultValue
, SetConfigSnapshotFieldFunc setFieldFunc
, GetConfigSnapshotFieldFunc getFieldFunc
, DurationUnits defaultUnits
, bool isNegativeValid )
{
return (OptionMetadata)
{
.name = name,
.iniName = iniName,
.isSecret = isSecret,
.isDynamic = isDynamic,
.isLoggingRelated = false,
.defaultValue = { defaultValue },
.interpretIniRawValue = &interpretStringIniRawValue,
.parseRawValue = &parseDurationValue,
.streamParsedValue = &streamParsedDuration,
.setField = setFieldFunc,
.getField = getFieldFunc,
.parsedValueToZval = &parsedDurationValueToZval,
.additionalData = (OptionAdditionalMetadata){ .durationData = (DurationOptionAdditionalMetadata){ .defaultUnits = defaultUnits, .isNegativeValid = isNegativeValid } }
};
}
[[maybe_unused]] static OptionMetadata buildSizeOptionMetadata(
String name
, StringView iniName
, bool isSecret
, bool isDynamic
, Size defaultValue
, SetConfigSnapshotFieldFunc setFieldFunc
, GetConfigSnapshotFieldFunc getFieldFunc
, SizeUnits defaultUnits
)
{
return (OptionMetadata)
{
.name = name,
.iniName = iniName,
.isSecret = isSecret,
.isDynamic = isDynamic,
.isLoggingRelated = false,
.defaultValue = { defaultValue },
.interpretIniRawValue = &interpretStringIniRawValue,
.parseRawValue = &parseSizeValue,
.streamParsedValue = &streamParsedSize,
.setField = setFieldFunc,
.getField = getFieldFunc,
.parsedValueToZval = &parsedSizeValueToZval,
.additionalData = (OptionAdditionalMetadata){ .sizeData = (SizeOptionAdditionalMetadata){ .defaultUnits = defaultUnits } }
};
}
static OptionMetadata buildEnumOptionMetadata(
String name
, StringView iniName
, bool isSecret
, bool isDynamic
, bool isLoggingRelated
, int defaultValue
, InterpretIniRawValueFunc interpretIniRawValue
, SetConfigSnapshotFieldFunc setFieldFunc
, GetConfigSnapshotFieldFunc getFieldFunc
, StreamParsedValueFunc streamParsedValue
, EnumOptionAdditionalMetadata additionalMetadata
)
{
return (OptionMetadata)
{
.name = name,
.iniName = iniName,
.isSecret = isSecret,
.isDynamic = isDynamic,
.isLoggingRelated = isLoggingRelated,
.defaultValue = { defaultValue },
.interpretIniRawValue = interpretIniRawValue,
.parseRawValue = &parseEnumValue,
.streamParsedValue = streamParsedValue,
.setField = setFieldFunc,
.getField = getFieldFunc,
.parsedValueToZval = &parsedEnumValueToZval,
.additionalData = (OptionAdditionalMetadata){ .enumData = additionalMetadata }
};
}
static void initOptionMetadataForId( OptionMetadata* optsMeta
, OptionId actualOptId
, OptionId expectedOptId
, OptionMetadata optionMetadata )
{
ELASTIC_APM_ASSERT_VALID_PTR( optsMeta );
ELASTIC_APM_ASSERT_VALID_OPTION_ID( actualOptId );
ELASTIC_APM_ASSERT_VALID_OPTION_ID( expectedOptId );
ELASTIC_APM_ASSERT_EQ_UINT64( actualOptId, expectedOptId );
ELASTIC_APM_FOR_EACH_INDEX( i, actualOptId )
ELASTIC_APM_ASSERT( ! areStringsEqualIgnoringCase( optsMeta[ i ].name, optionMetadata.name )
, "i: %u, optionMetadata.name: %s", (unsigned int)i, optionMetadata.name );
optsMeta[ actualOptId ] = optionMetadata;
}
#define ELASTIC_APM_FREE_AND_RESET_FIELD_FUNC_NAME( fieldName ) freeAndReset_ConfigSnapshot_##fieldName##_field
#define ELASTIC_APM_SET_FIELD_FUNC_NAME( fieldName ) set_ConfigSnapshot_##fieldName##_field
#define ELASTIC_APM_GET_FIELD_FUNC_NAME( fieldName ) get_ConfigSnapshot_##fieldName##_field
#define ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( unionFieldForType, fieldName ) \
static void ELASTIC_APM_SET_FIELD_FUNC_NAME( fieldName ) ( const OptionMetadata* optMeta, ParsedOptionValue parsedValue, ConfigSnapshot* dst ) \
{ \
ELASTIC_APM_ASSERT_VALID_PTR( optMeta ); \
ELASTIC_APM_ASSERT_VALID_PARSED_OPTION_VALUE( parsedValue ); \
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedValue.type ); \
ELASTIC_APM_ASSERT_VALID_PTR( dst ); \
\
dst->fieldName = parsedValue.u.unionFieldForType; \
} \
\
static ParsedOptionValue ELASTIC_APM_GET_FIELD_FUNC_NAME( fieldName ) ( const OptionMetadata* optMeta, const ConfigSnapshot* src ) \
{ \
ELASTIC_APM_ASSERT_VALID_PTR( optMeta ); \
ELASTIC_APM_ASSERT_VALID_PTR( src ); \
\
return ParsedOptionValue{ src->fieldName }; \
}
#define ELASTIC_APM_DEFINE_ENUM_FIELD_ACCESS_FUNCS( EnumType, fieldName ) \
static void ELASTIC_APM_SET_FIELD_FUNC_NAME( fieldName ) ( const OptionMetadata* optMeta, ParsedOptionValue parsedValue, ConfigSnapshot* dst ) \
{ \
ELASTIC_APM_ASSERT_VALID_PTR( optMeta ); \
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_int ); \
ELASTIC_APM_ASSERT_VALID_PARSED_OPTION_VALUE( parsedValue ); \
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedValue.type ); \
ELASTIC_APM_ASSERT_VALID_PTR( dst ); \
\
dst->fieldName = (EnumType)( parsedValue.u.intValue ); \
} \
\
static ParsedOptionValue ELASTIC_APM_GET_FIELD_FUNC_NAME( fieldName ) ( const OptionMetadata* optMeta, const ConfigSnapshot* src ) \
{ \
ELASTIC_APM_ASSERT_VALID_PTR( optMeta ); \
ELASTIC_APM_ASSERT_EQ_UINT64( optMeta->defaultValue.type, parsedOptionValueType_int ); \
ELASTIC_APM_ASSERT_VALID_PTR( src ); \
\
return ParsedOptionValue{(int)(src->fieldName)}; \
}
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( boolValue, abortOnMemoryLeak )
# ifdef PHP_WIN32
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( boolValue, allowAbortDialog )
# endif
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, apiKey )
# if ( ELASTIC_APM_ASSERT_ENABLED_01 != 0 )
ELASTIC_APM_DEFINE_ENUM_FIELD_ACCESS_FUNCS( AssertLevel, assertLevel )
# endif
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( boolValue, astProcessEnabled )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( boolValue, astProcessDebugDumpConvertedBackToSource )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, astProcessDebugDumpForPathPrefix )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, astProcessDebugDumpOutDir )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( optionalBoolValue, asyncBackendComm )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, bootstrapPhpPartFile )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( boolValue, breakdownMetrics )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( boolValue, captureErrors )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, devInternal )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( boolValue, devInternalBackendCommLogVerbose )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, disableInstrumentations )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( boolValue, disableSend )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( boolValue, enabled )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, environment )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, globalLabels )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, hostname )
ELASTIC_APM_DEFINE_ENUM_FIELD_ACCESS_FUNCS( InternalChecksLevel, internalChecksLevel )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, logFile )
ELASTIC_APM_DEFINE_ENUM_FIELD_ACCESS_FUNCS( LogLevel, logLevel )
ELASTIC_APM_DEFINE_ENUM_FIELD_ACCESS_FUNCS( LogLevel, logLevelFile )
ELASTIC_APM_DEFINE_ENUM_FIELD_ACCESS_FUNCS( LogLevel, logLevelStderr )
# ifndef PHP_WIN32
ELASTIC_APM_DEFINE_ENUM_FIELD_ACCESS_FUNCS( LogLevel, logLevelSyslog )
# endif
# ifdef PHP_WIN32
ELASTIC_APM_DEFINE_ENUM_FIELD_ACCESS_FUNCS( LogLevel, logLevelWinSysDebug )
# endif
# if ( ELASTIC_APM_MEMORY_TRACKING_ENABLED_01 != 0 )
ELASTIC_APM_DEFINE_ENUM_FIELD_ACCESS_FUNCS( MemoryTrackingLevel, memoryTrackingLevel )
# endif
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, nonKeywordStringMaxLength )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( boolValue, profilingInferredSpansEnabled )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, profilingInferredSpansMinDuration )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, profilingInferredSpansSamplingInterval )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, sanitizeFieldNames )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, secretToken )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( durationValue, serverTimeout )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, serverUrl )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, serviceName )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, serviceNodeName )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, serviceVersion )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( boolValue, spanCompressionEnabled )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, spanCompressionExactMatchMaxDuration )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, spanCompressionSameKindMaxDuration )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, spanStackTraceMinDuration )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, stackTraceLimit )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, transactionIgnoreUrls )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, transactionMaxSpans )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, transactionSampleRate )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, urlGroups )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( boolValue, verifyServerCert )
ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS( stringValue, debugDiagnosticsFile )
#undef ELASTIC_APM_DEFINE_FIELD_ACCESS_FUNCS
#undef ELASTIC_APM_DEFINE_ENUM_FIELD_ACCESS_FUNCS
#define ELASTIC_APM_INIT_METADATA_EX( buildFunc, fieldName, optName, isSecret, isDynamic, defaultValue, ... ) \
initOptionMetadataForId \
( \
optsMeta \
, (OptionId)(i++) \
, optionId_##fieldName \
, buildFunc \
( \
optName \
, ELASTIC_APM_STRING_LITERAL_TO_VIEW( ELASTIC_APM_CFG_CONVERT_OPT_NAME_TO_INI_NAME( optName ) ) \
, isSecret \
, isDynamic \
, defaultValue \
, ELASTIC_APM_SET_FIELD_FUNC_NAME( fieldName ) \
, ELASTIC_APM_GET_FIELD_FUNC_NAME( fieldName ) \
, ##__VA_ARGS__ \
) \
)
#define ELASTIC_APM_INIT_METADATA( buildFunc, fieldName, optName, defaultValue ) \
ELASTIC_APM_INIT_METADATA_EX( buildFunc, fieldName, optName, /* isSecret */ false, /* isDynamic */ false, defaultValue )
#define ELASTIC_APM_INIT_DURATION_METADATA( fieldName, optName, defaultValue, defaultUnits, isNegativeValid ) \
ELASTIC_APM_INIT_METADATA_EX( buildDurationOptionMetadata, fieldName, optName, /* isSecret */ false, /* isDynamic */ false, defaultValue, defaultUnits, isNegativeValid )
#define ELASTIC_APM_INIT_SECRET_METADATA( buildFunc, fieldName, optName, defaultValue ) \
ELASTIC_APM_INIT_METADATA_EX( buildFunc, fieldName, optName, /* isSecret */ true, /* isDynamic */ false, defaultValue )
#define ELASTIC_APM_INIT_DYNAMIC_METADATA( buildFunc, fieldName, optName, defaultValue ) \
ELASTIC_APM_INIT_METADATA_EX( buildFunc, fieldName, optName, /* isSecret */ false, /* isDynamic */ true, defaultValue )
#define ELASTIC_APM_ENUM_INIT_METADATA_EX( fieldName, optName, isDynamic, isLoggingRelated, defaultValue, interpretIniRawValue, enumNamesArray, isUniquePrefixEnoughArg ) \
initOptionMetadataForId \
( \
optsMeta \
, (OptionId)(i++) \
, optionId_##fieldName \
, buildEnumOptionMetadata \
( \
optName \
, ELASTIC_APM_STRING_LITERAL_TO_VIEW( ELASTIC_APM_CFG_CONVERT_OPT_NAME_TO_INI_NAME( optName ) ) \
, /* isSecret */ false \
, isDynamic \
, isLoggingRelated \
, defaultValue \
, interpretIniRawValue \
, ELASTIC_APM_SET_FIELD_FUNC_NAME( fieldName ) \
, ELASTIC_APM_GET_FIELD_FUNC_NAME( fieldName ) \
, &streamParsedLogLevel \
, (EnumOptionAdditionalMetadata) \
{ \
.names = (enumNamesArray), \
.enumElementsCount = ELASTIC_APM_STATIC_ARRAY_SIZE( (enumNamesArray) ), \
.isUniquePrefixEnough = (isUniquePrefixEnoughArg) \
} \
) \
)
#define ELASTIC_APM_ENUM_INIT_METADATA( fieldName, optName, defaultValue, interpretIniRawValue, enumNamesArray, isUniquePrefixEnoughArg ) \
ELASTIC_APM_ENUM_INIT_METADATA_EX( fieldName, optName, /* isDynamic */ false, /* isLoggingRelated */ false, defaultValue, interpretIniRawValue, enumNamesArray, isUniquePrefixEnoughArg )
#define ELASTIC_APM_INIT_LOG_LEVEL_METADATA_EX( fieldName, optName, isDynamic ) \
ELASTIC_APM_ENUM_INIT_METADATA_EX( fieldName, optName, isDynamic, /* isLoggingRelated */ true, logLevel_not_set, &interpretEmptyIniRawValueAsOff, logLevelNames, /* isUniquePrefixEnough: */ true )
#define ELASTIC_APM_INIT_LOG_LEVEL_METADATA( fieldName, optName ) \
ELASTIC_APM_INIT_LOG_LEVEL_METADATA_EX( fieldName, optName, /* isDynamic: */ false )
#define ELASTIC_APM_INIT_DYNAMIC_LOG_LEVEL_METADATA( fieldName, optName ) \
ELASTIC_APM_INIT_LOG_LEVEL_METADATA_EX( fieldName, optName, /* isDynamic: */ true )
static void initOptionsMetadata( OptionMetadata* optsMeta )
{
ELASTIC_APM_ASSERT_VALID_PTR( optsMeta );
size_t i = 0;
//
// The order of calls to ELASTIC_APM_INIT_METADATA below should be the same as in OptionId
//
ELASTIC_APM_INIT_METADATA(
buildBoolOptionMetadata,
abortOnMemoryLeak,
ELASTIC_APM_CFG_OPT_NAME_ABORT_ON_MEMORY_LEAK,
/* defaultValue: */ ELASTIC_APM_MEMORY_TRACKING_DEFAULT_ABORT_ON_MEMORY_LEAK );
#ifdef PHP_WIN32
ELASTIC_APM_INIT_METADATA(
buildBoolOptionMetadata,
allowAbortDialog,
ELASTIC_APM_CFG_OPT_NAME_ALLOW_ABORT_DIALOG,
/* defaultValue: */ false );
#endif
ELASTIC_APM_INIT_SECRET_METADATA(
buildStringOptionMetadata,
apiKey,
ELASTIC_APM_CFG_OPT_NAME_API_KEY,
/* defaultValue: */ NULL );
#if ( ELASTIC_APM_ASSERT_ENABLED_01 != 0 )
ELASTIC_APM_ENUM_INIT_METADATA(
/* fieldName: */ assertLevel,
/* optName: */ ELASTIC_APM_CFG_OPT_NAME_ASSERT_LEVEL,
/* defaultValue: */ assertLevel_not_set,
&interpretEmptyIniRawValueAsOff,
assertLevelNames,
/* isUniquePrefixEnough: */ true );
#endif
ELASTIC_APM_INIT_METADATA(
buildBoolOptionMetadata,
astProcessEnabled,
ELASTIC_APM_CFG_OPT_NAME_AST_PROCESS_ENABLED,
/* defaultValue: */ false );
ELASTIC_APM_INIT_METADATA(
buildBoolOptionMetadata,
astProcessDebugDumpConvertedBackToSource,
ELASTIC_APM_CFG_OPT_NAME_AST_PROCESS_DEBUG_DUMP_CONVERTED_BACK_TO_SOURCE,
/* defaultValue: */ true );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
astProcessDebugDumpForPathPrefix,
ELASTIC_APM_CFG_OPT_NAME_AST_PROCESS_DEBUG_DUMP_FOR_PATH_PREFIX,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
astProcessDebugDumpOutDir,
ELASTIC_APM_CFG_OPT_NAME_AST_PROCESS_DEBUG_DUMP_OUT_DIR,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildOptionalBoolOptionMetadata,
asyncBackendComm,
ELASTIC_APM_CFG_OPT_NAME_ASYNC_BACKEND_COMM,
/* defaultValue: */ makeNotSetOptionalBool() );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
bootstrapPhpPartFile,
ELASTIC_APM_CFG_OPT_NAME_BOOTSTRAP_PHP_PART_FILE,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildBoolOptionMetadata,
breakdownMetrics,
ELASTIC_APM_CFG_OPT_NAME_BREAKDOWN_METRICS,
/* defaultValue: */ true );
ELASTIC_APM_INIT_METADATA(
buildBoolOptionMetadata,
captureErrors,
ELASTIC_APM_CFG_OPT_NAME_CAPTURE_ERRORS,
/* defaultValue: */ true );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
devInternal,
ELASTIC_APM_CFG_OPT_NAME_DEV_INTERNAL,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildBoolOptionMetadata,
devInternalBackendCommLogVerbose,
ELASTIC_APM_CFG_OPT_NAME_DEV_INTERNAL_BACKEND_COMM_LOG_VERBOSE,
/* defaultValue: */ false );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
disableInstrumentations,
ELASTIC_APM_CFG_OPT_NAME_DISABLE_INSTRUMENTATIONS,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildBoolOptionMetadata,
disableSend,
ELASTIC_APM_CFG_OPT_NAME_DISABLE_SEND,
/* defaultValue: */ false );
ELASTIC_APM_INIT_METADATA(
buildBoolOptionMetadata,
enabled,
ELASTIC_APM_CFG_OPT_NAME_ENABLED,
/* defaultValue: */ true );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
environment,
ELASTIC_APM_CFG_OPT_NAME_ENVIRONMENT,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
globalLabels,
ELASTIC_APM_CFG_OPT_NAME_GLOBAL_LABELS,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
hostname,
ELASTIC_APM_CFG_OPT_NAME_HOSTNAME,
/* defaultValue: */ NULL );
ELASTIC_APM_ENUM_INIT_METADATA(
/* fieldName: */ internalChecksLevel,
/* optName: */ ELASTIC_APM_CFG_OPT_NAME_INTERNAL_CHECKS_LEVEL,
/* defaultValue: */ internalChecksLevel_not_set,
&interpretEmptyIniRawValueAsOff,
internalChecksLevelNames,
/* isUniquePrefixEnough: */ true );
ELASTIC_APM_INIT_METADATA(
buildLoggingRelatedStringOptionMetadata,
logFile,
ELASTIC_APM_CFG_OPT_NAME_LOG_FILE,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_DYNAMIC_LOG_LEVEL_METADATA(
logLevel,
ELASTIC_APM_CFG_OPT_NAME_LOG_LEVEL );
ELASTIC_APM_INIT_LOG_LEVEL_METADATA(
logLevelFile,
ELASTIC_APM_CFG_OPT_NAME_LOG_LEVEL_FILE );
ELASTIC_APM_INIT_LOG_LEVEL_METADATA(
logLevelStderr,
ELASTIC_APM_CFG_OPT_NAME_LOG_LEVEL_STDERR );
#ifndef PHP_WIN32
ELASTIC_APM_INIT_LOG_LEVEL_METADATA(
logLevelSyslog,
ELASTIC_APM_CFG_OPT_NAME_LOG_LEVEL_SYSLOG );
#endif
#ifdef PHP_WIN32
ELASTIC_APM_INIT_LOG_LEVEL_METADATA(
logLevelWinSysDebug,
ELASTIC_APM_CFG_OPT_NAME_LOG_LEVEL_WIN_SYS_DEBUG );
#endif
#if ( ELASTIC_APM_MEMORY_TRACKING_ENABLED_01 != 0 )
ELASTIC_APM_ENUM_INIT_METADATA(
/* fieldName: */ memoryTrackingLevel,
/* optName: */ ELASTIC_APM_CFG_OPT_NAME_MEMORY_TRACKING_LEVEL,
/* defaultValue: */ memoryTrackingLevel_not_set,
&interpretEmptyIniRawValueAsOff,
memoryTrackingLevelNames,
/* isUniquePrefixEnough: */ true );
#endif
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
nonKeywordStringMaxLength,
ELASTIC_APM_CFG_OPT_NAME_NON_KEYWORD_STRING_MAX_LENGTH,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildBoolOptionMetadata,
profilingInferredSpansEnabled,
ELASTIC_APM_CFG_OPT_NAME_PROFILING_INFERRED_SPANS_ENABLED,
/* defaultValue: */ false );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
profilingInferredSpansMinDuration,
ELASTIC_APM_CFG_OPT_NAME_PROFILING_INFERRED_SPANS_MIN_DURATION,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
profilingInferredSpansSamplingInterval,
ELASTIC_APM_CFG_OPT_NAME_PROFILING_INFERRED_SPANS_SAMPLING_INTERVAL,
"50ms" );
ELASTIC_APM_INIT_SECRET_METADATA(
buildStringOptionMetadata,
sanitizeFieldNames,
ELASTIC_APM_CFG_OPT_NAME_SANITIZE_FIELD_NAMES,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_SECRET_METADATA(
buildStringOptionMetadata,
secretToken,
ELASTIC_APM_CFG_OPT_NAME_SECRET_TOKEN,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_DURATION_METADATA(
serverTimeout
, ELASTIC_APM_CFG_OPT_NAME_SERVER_TIMEOUT
, /* defaultValue */ makeDuration( 30, durationUnits_second )
, /* defaultUnits: */ durationUnits_second
, /* isNegativeValid */ false );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
serverUrl,
ELASTIC_APM_CFG_OPT_NAME_SERVER_URL,
/* defaultValue: */ "http://localhost:8200" );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
serviceName,
ELASTIC_APM_CFG_OPT_NAME_SERVICE_NAME,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
serviceNodeName,
ELASTIC_APM_CFG_OPT_NAME_SERVICE_NODE_NAME,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
serviceVersion,
ELASTIC_APM_CFG_OPT_NAME_SERVICE_VERSION,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildBoolOptionMetadata,
spanCompressionEnabled,
ELASTIC_APM_CFG_OPT_NAME_SPAN_COMPRESSION_ENABLED,
/* defaultValue: */ true );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
spanCompressionExactMatchMaxDuration,
ELASTIC_APM_CFG_OPT_NAME_SPAN_COMPRESSION_EXACT_MATCH_MAX_DURATION,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
spanCompressionSameKindMaxDuration,
ELASTIC_APM_CFG_OPT_NAME_SPAN_COMPRESSION_SAME_KIND_MAX_DURATION,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
spanStackTraceMinDuration,
ELASTIC_APM_CFG_OPT_NAME_SPAN_STACK_TRACE_MIN_DURATION,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
stackTraceLimit,
ELASTIC_APM_CFG_OPT_NAME_STACK_TRACE_LIMIT,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
transactionIgnoreUrls,
ELASTIC_APM_CFG_OPT_NAME_TRANSACTION_IGNORE_URLS,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
transactionMaxSpans,
ELASTIC_APM_CFG_OPT_NAME_TRANSACTION_MAX_SPANS,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
transactionSampleRate,
ELASTIC_APM_CFG_OPT_NAME_TRANSACTION_SAMPLE_RATE,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
urlGroups,
ELASTIC_APM_CFG_OPT_NAME_URL_GROUPS,
/* defaultValue: */ NULL );
ELASTIC_APM_INIT_METADATA(
buildBoolOptionMetadata,
verifyServerCert,
ELASTIC_APM_CFG_OPT_NAME_VERIFY_SERVER_CERT,
/* defaultValue: */ true );
ELASTIC_APM_INIT_METADATA(
buildStringOptionMetadata,
debugDiagnosticsFile,
ELASTIC_APM_CFG_OPT_NAME_DEBUG_DIAGNOSTICS_FILE,
/* defaultValue: */ nullptr );
ELASTIC_APM_ASSERT_EQ_UINT64( i, numberOfOptions );
}
#undef ELASTIC_APM_SET_FIELD_FUNC_NAME
#undef ELASTIC_APM_GET_FIELD_FUNC_NAME
#undef ELASTIC_APM_FREE_AND_RESET_FIELD_FUNC_NAME
#undef ELASTIC_APM_INIT_METADATA_EX
#undef ELASTIC_APM_INIT_METADATA
#undef ELASTIC_APM_ENUM_INIT_METADATA
#undef ELASTIC_APM_ENUM_INIT_METADATA_EX
#undef ELASTIC_APM_INIT_LOG_LEVEL_METADATA
#undef ELASTIC_APM_INIT_LOG_LEVEL_METADATA
static
void parseCombinedRawConfigSnapshot(
ConfigManager* cfgManager,
const CombinedRawConfigSnapshot* combinedRawCfgSnapshot,
ConfigSnapshot* cfgSnapshot )
{
ELASTIC_APM_ASSERT_VALID_PTR( cfgManager );
ELASTIC_APM_ASSERT_VALID_PTR( combinedRawCfgSnapshot );
ELASTIC_APM_ASSERT_VALID_PTR( cfgSnapshot );
const OptionMetadata* const optsMeta = cfgManager->meta.optionsMeta;
ELASTIC_APM_FOR_EACH_OPTION_ID( optId )
{
char txtOutStreamBuf[ ELASTIC_APM_TEXT_OUTPUT_STREAM_ON_STACK_BUFFER_SIZE ];
TextOutputStream txtOutStream = ELASTIC_APM_TEXT_OUTPUT_STREAM_FROM_STATIC_BUFFER( txtOutStreamBuf );
const OptionMetadata* const optMeta = &( optsMeta[ optId ] );
const String originalRawValue = combinedRawCfgSnapshot->original[ optId ];
const String interpretedRawValue = combinedRawCfgSnapshot->interpreted[ optId ];
const String sourceDescription = combinedRawCfgSnapshot->sourceDescriptions[ optId ];
ParsedOptionValue parsedOptValue;
ELASTIC_APM_ZERO_STRUCT( &parsedOptValue );
if ( cfgManager->isLoggingRelatedOnly && !optMeta->isLoggingRelated )
{
continue;
}
if ( interpretedRawValue == NULL )
{
parsedOptValue = optMeta->defaultValue;
ELASTIC_APM_LOG_DEBUG(
"Configuration option `%s' is not set - using default value (%s)",
optMeta->name,
optMeta->streamParsedValue( optMeta, parsedOptValue, &txtOutStream ) );
}
else if ( optMeta->parseRawValue( optMeta, interpretedRawValue, &parsedOptValue ) == resultSuccess )
{
ELASTIC_APM_LOG_DEBUG(
"Successfully parsed configuration option `%s' - "
"parsed value: %s (raw value: `%s', interpreted as: `%s', source: %s)",
optMeta->name,
optMeta->streamParsedValue( optMeta, parsedOptValue, &txtOutStream ),
originalRawValue,
interpretedRawValue,
sourceDescription );
}
else
{
parsedOptValue = optMeta->defaultValue;
ELASTIC_APM_LOG_ERROR(
"Failed to parse configuration option `%s' - "
"using default value (%s). Failed to parse raw value: `%s', interpreted as: `%s', source: %s.",
optMeta->name,
optMeta->streamParsedValue( optMeta, parsedOptValue, &txtOutStream ),
originalRawValue,
interpretedRawValue,
sourceDescription );
}
optMeta->setField( optMeta, parsedOptValue, cfgSnapshot );
}
}
static ResultCode constructEnvVarNameForOption( String optName, String* envVarName )
{
ELASTIC_APM_ASSERT_VALID_STRING( optName );
ELASTIC_APM_ASSERT_VALID_OUT_PTR_TO_PTR( envVarName );
ResultCode resultCode;
StringView envVarNamePrefix = ELASTIC_APM_STRING_LITERAL_TO_VIEW( "ELASTIC_APM_" );
MutableString envVarNameBuffer = NULL;
const size_t envVarNameBufferSize = envVarNamePrefix.length + strlen( optName ) + 1;
ELASTIC_APM_PEMALLOC_STRING_IF_FAILED_GOTO( envVarNameBufferSize, envVarNameBuffer );
strcpy( envVarNameBuffer, envVarNamePrefix.begin );
copyStringAsUpperCase( optName, /* out */ envVarNameBuffer + envVarNamePrefix.length );
resultCode = resultSuccess;
*envVarName = envVarNameBuffer;
finally:
return resultCode;
failure:
ELASTIC_APM_PEFREE_STRING_SIZE_AND_SET_TO_NULL( envVarNameBufferSize, envVarNameBuffer );
goto finally;
}
static void destructEnvVarNames( /* in,out */ String envVarNames[] )
{
ELASTIC_APM_ASSERT_VALID_PTR( envVarNames );
ELASTIC_APM_FOR_EACH_OPTION_ID( optId )
ELASTIC_APM_PEFREE_STRING_AND_SET_TO_NULL( envVarNames[ optId ] );
}
static ResultCode constructEnvVarNames( OptionMetadata* optsMeta, /* out */ String envVarNames[] )
{
ELASTIC_APM_ASSERT_VALID_PTR( optsMeta );
ELASTIC_APM_ASSERT_VALID_PTR( envVarNames );
ResultCode resultCode;
ELASTIC_APM_FOR_EACH_OPTION_ID( optId )
ELASTIC_APM_CALL_IF_FAILED_GOTO( constructEnvVarNameForOption( optsMeta[ optId ].name, &envVarNames[ optId ] ) );
resultCode = resultSuccess;
finally:
return resultCode;
failure:
destructEnvVarNames( envVarNames );
goto finally;
}
#ifdef ELASTIC_APM_GETENV_FUNC
// Declare to avoid warnings
char* ELASTIC_APM_MOCK_GETENV_FUNC( const char* name );
#else
#define ELASTIC_APM_GETENV_FUNC getenv
#endif
String readRawOptionValueFromEnvVars( const ConfigManager* cfgManager, OptionId optId )
{
ELASTIC_APM_ASSERT_VALID_PTR( cfgManager );
ELASTIC_APM_ASSERT_VALID_OPTION_ID( optId );
return ELASTIC_APM_GETENV_FUNC( cfgManager->meta.envVarNames[ optId ] );
}
static
ResultCode getRawOptionValueFromEnvVars(
const ConfigManager* cfgManager,
OptionId optId,
String* originalRawValue,
String* interpretedRawValue )
{
ELASTIC_APM_ASSERT_VALID_PTR( cfgManager );
ELASTIC_APM_ASSERT_VALID_OPTION_ID( optId );
ELASTIC_APM_ASSERT_VALID_OUT_PTR_TO_PTR( originalRawValue );
ELASTIC_APM_ASSERT_VALID_OUT_PTR_TO_PTR( interpretedRawValue );
ResultCode resultCode;
String returnedRawValue;
String rawValue = NULL;
returnedRawValue = readRawOptionValueFromEnvVars( cfgManager, optId );
if ( returnedRawValue != NULL )
{
StringView processedRawValue;
processedRawValue = trimStringView( makeStringViewFromString( returnedRawValue ) );
ELASTIC_APM_PEMALLOC_DUP_STRING_VIEW_IF_FAILED_GOTO( processedRawValue.begin, processedRawValue.length, rawValue );
}
resultCode = resultSuccess;
*originalRawValue = rawValue;
*interpretedRawValue = *originalRawValue;
finally:
return resultCode;
failure:
ELASTIC_APM_PEFREE_STRING_AND_SET_TO_NULL( rawValue );
goto finally;
}
String readRawOptionValueFromIni(
const ConfigManager* cfgManager,
OptionId optId,
bool* exists )
{
ELASTIC_APM_ASSERT_VALID_PTR( cfgManager );
ELASTIC_APM_ASSERT_VALID_OPTION_ID( optId );
const OptionMetadata* const optMeta = &( cfgManager->meta.optionsMeta[ optId ] );
zend_bool existsZendBool = 0;
String returnedRawValue = zend_ini_string_ex(
(char*)( optMeta->iniName.begin ),
optMeta->iniName.length,
/* orig: */ 0,
&existsZendBool );
*exists = ( existsZendBool != 0 );
return returnedRawValue;
}
static
ResultCode getRawOptionValueFromIni(
const ConfigManager* cfgManager,
OptionId optId,
String* originalRawValue,
String* interpretedRawValue )
{
ELASTIC_APM_ASSERT_VALID_PTR( cfgManager );
ELASTIC_APM_ASSERT_VALID_OPTION_ID( optId );
ELASTIC_APM_ASSERT_VALID_OUT_PTR_TO_PTR( originalRawValue );
ELASTIC_APM_ASSERT_VALID_OUT_PTR_TO_PTR( interpretedRawValue );
ResultCode resultCode;
bool exists = 0;
String returnedRawValue = NULL;
String rawValue = NULL;
const OptionMetadata* const optMeta = &( cfgManager->meta.optionsMeta[ optId ] );
returnedRawValue = readRawOptionValueFromIni( cfgManager,optId, &exists );
if ( exists && ( returnedRawValue != NULL ) )
{
StringView processedRawValue;
processedRawValue = trimStringView( makeStringViewFromString( returnedRawValue ) );
ELASTIC_APM_PEMALLOC_DUP_STRING_VIEW_IF_FAILED_GOTO( processedRawValue.begin, processedRawValue.length, rawValue );
}
resultCode = resultSuccess;
*originalRawValue = rawValue;
*interpretedRawValue = optMeta->interpretIniRawValue( rawValue );
finally:
return resultCode;
failure:
ELASTIC_APM_PEFREE_STRING_AND_SET_TO_NULL( rawValue );
goto finally;
}
static void initRawConfigSources( RawConfigSnapshotSource rawCfgSources[ numberOfRawConfigSources ] )
{
ELASTIC_APM_ASSERT_VALID_PTR( rawCfgSources );
size_t i = 0;
ELASTIC_APM_ASSERT_EQ_UINT64( i, rawConfigSourceId_iniFile );
rawCfgSources[ i++ ] = (RawConfigSnapshotSource)
{
.description = "INI file",
.getOptionValue = &getRawOptionValueFromIni
};
ELASTIC_APM_ASSERT_EQ_UINT64( i, rawConfigSourceId_envVars );
rawCfgSources[ i++ ] = (RawConfigSnapshotSource)
{
.description = "Environment variables",
.getOptionValue = &getRawOptionValueFromEnvVars
};
ELASTIC_APM_ASSERT_EQ_UINT64( i, numberOfRawConfigSources );
}
static
void deleteConfigRawDataAndSetToNull( /* in,out */ ConfigRawData** pRawData )
{
ELASTIC_APM_ASSERT_VALID_PTR( pRawData );
ConfigRawData* rawData = *pRawData;
if ( rawData == NULL ) return;
ELASTIC_APM_ASSERT_VALID_PTR( rawData );
ELASTIC_APM_FOR_EACH_OPTION_ID( optId )
ELASTIC_APM_FOR_EACH_INDEX( rawSourceIndex, numberOfRawConfigSources )
{
const char** pOriginalRawValue = &( rawData->fromSources[ rawSourceIndex ].original[ optId ] );
ELASTIC_APM_PEFREE_STRING_AND_SET_TO_NULL( *pOriginalRawValue );
}
ELASTIC_APM_PEFREE_INSTANCE_AND_SET_TO_NULL( ConfigRawData, *pRawData );
}
static
ResultCode fetchConfigRawDataFromAllSources( const ConfigManager* cfgManager, /* out */ ConfigRawData* newRawData )
{
ELASTIC_APM_ASSERT_VALID_PTR( cfgManager );
ELASTIC_APM_ASSERT_VALID_PTR( newRawData );
ResultCode resultCode;
ELASTIC_APM_FOR_EACH_OPTION_ID( optId )
{
ELASTIC_APM_FOR_EACH_INDEX( rawCfgSourceIndex, numberOfRawConfigSources )
{
ELASTIC_APM_CALL_IF_FAILED_GOTO( cfgManager->meta.rawCfgSources[ rawCfgSourceIndex ].getOptionValue(
cfgManager,
optId,
&newRawData->fromSources[ rawCfgSourceIndex ].original[ optId ],
&newRawData->fromSources[ rawCfgSourceIndex ].interpreted[ optId ] ) );
}
}
resultCode = resultSuccess;
finally:
return resultCode;
failure:
goto finally;
}
static
void combineConfigRawData( const ConfigManager* cfgManager, /* in,out */ ConfigRawData* newRawData )
{
ELASTIC_APM_ASSERT_VALID_PTR( cfgManager );
ELASTIC_APM_ASSERT_VALID_PTR( newRawData );
ELASTIC_APM_FOR_EACH_OPTION_ID( optId )
{
ELASTIC_APM_FOR_EACH_INDEX( rawCfgSourceIndex, numberOfRawConfigSources )
{
if ( newRawData->fromSources[ rawCfgSourceIndex ].interpreted[ optId ] == NULL ) continue;
newRawData->combined.original[ optId ] = newRawData->fromSources[ rawCfgSourceIndex ].original[ optId ];
newRawData->combined.interpreted[ optId ] = newRawData->fromSources[ rawCfgSourceIndex ].interpreted[ optId ];
newRawData->combined.sourceDescriptions[ optId ] = cfgManager->meta.rawCfgSources[ rawCfgSourceIndex ].description;
break;
}
}
}
static
ResultCode fetchConfigRawData( const ConfigManager* cfgManager, /* out */ ConfigRawData** pNewRawData )
{
ELASTIC_APM_ASSERT_VALID_PTR( cfgManager );
ELASTIC_APM_ASSERT_VALID_OUT_PTR_TO_PTR( pNewRawData );
ResultCode resultCode;
ConfigRawData* newRawData = NULL;
ELASTIC_APM_PEMALLOC_INSTANCE_IF_FAILED_GOTO( ConfigRawData, newRawData );
ELASTIC_APM_ZERO_STRUCT( newRawData );
ELASTIC_APM_CALL_IF_FAILED_GOTO( fetchConfigRawDataFromAllSources( cfgManager, /* out */ newRawData ) );
combineConfigRawData( cfgManager, /* in,out */ newRawData );
resultCode = resultSuccess;
*pNewRawData = newRawData;
finally:
return resultCode;
failure:
deleteConfigRawDataAndSetToNull( &newRawData );
goto finally;
}
static
bool areEqualCombinedRawConfigSnapshots( const CombinedRawConfigSnapshot* snapshot1, const CombinedRawConfigSnapshot* snapshot2 )
{
ELASTIC_APM_ASSERT_VALID_PTR( snapshot1 );
ELASTIC_APM_ASSERT_VALID_PTR( snapshot2 );
ELASTIC_APM_FOR_EACH_OPTION_ID( optId )
if ( ( ! areEqualNullableStrings( snapshot1->original[ optId ], snapshot2->original[ optId ] ) ) ||
( ! areEqualNullableStrings( snapshot1->interpreted[ optId ], snapshot2->interpreted[ optId ] ) ) ||
( ! areEqualNullableStrings( snapshot1->sourceDescriptions[ optId ], snapshot2->sourceDescriptions[ optId ] ) ) )
return false;
return true;
}
const ConfigSnapshot* getConfigManagerCurrentSnapshot( const ConfigManager* cfgManager )
{
ELASTIC_APM_ASSERT_VALID_PTR( cfgManager );
return &cfgManager->current.snapshot;
}
ResultCode ensureConfigManagerHasLatestConfig( ConfigManager* cfgManager, bool* didConfigChange )
{
ELASTIC_APM_ASSERT_VALID_PTR( cfgManager );
ELASTIC_APM_ASSERT_VALID_PTR( didConfigChange );
ResultCode resultCode;
ConfigRawData* newRawData = NULL;
ConfigSnapshot newCfgSnapshot;
ELASTIC_APM_ZERO_STRUCT(&newCfgSnapshot);
ELASTIC_APM_CALL_IF_FAILED_GOTO( fetchConfigRawData( cfgManager, &newRawData ) );
if ( cfgManager->current.rawData != NULL &&
areEqualCombinedRawConfigSnapshots( &cfgManager->current.rawData->combined, &newRawData->combined ) )
{
ELASTIC_APM_LOG_DEBUG( "Current configuration is already the latest" );
resultCode = resultSuccess;
*didConfigChange = false;
goto finally;
}
parseCombinedRawConfigSnapshot( cfgManager, &newRawData->combined, &newCfgSnapshot );
deleteConfigRawDataAndSetToNull( /* in,out */ &cfgManager->current.rawData );
cfgManager->current.rawData = newRawData;
cfgManager->current.snapshot = newCfgSnapshot;
newRawData = NULL;
resultCode = resultSuccess;
*didConfigChange = true;
finally:
deleteConfigRawDataAndSetToNull( /* in,out */ &newRawData );
return resultCode;
failure:
goto finally;
}
static
void destructConfigManagerCurrentState( /* in,out */ ConfigManagerCurrentState* cfgManagerCurrent )
{
ELASTIC_APM_ASSERT_VALID_PTR( cfgManagerCurrent );
deleteConfigRawDataAndSetToNull( /* in,out */ &cfgManagerCurrent->rawData );
ELASTIC_APM_ZERO_STRUCT( cfgManagerCurrent );
}
static
void initConfigManagerCurrentState(
const ConfigMetadata* cfgManagerMeta,
/* out */ ConfigManagerCurrentState* cfgManagerCurrent )
{
ELASTIC_APM_ASSERT_VALID_PTR( cfgManagerMeta );
ELASTIC_APM_ASSERT_VALID_PTR( cfgManagerCurrent );
ELASTIC_APM_FOR_EACH_OPTION_ID( optId )
{
const OptionMetadata* const optMeta = &( cfgManagerMeta->optionsMeta[ optId ] );
optMeta->setField( optMeta, optMeta->defaultValue, &cfgManagerCurrent->snapshot );
}
}
static
void destructConfigManagerMetadata( ConfigMetadata* cfgManagerMeta )
{
ELASTIC_APM_ASSERT_VALID_PTR( cfgManagerMeta );
destructEnvVarNames( /* in,out */ cfgManagerMeta->envVarNames );
ELASTIC_APM_ZERO_STRUCT( cfgManagerMeta );
}
ResultCode constructConfigManagerMetadata( ConfigMetadata* cfgManagerMeta )
{
ELASTIC_APM_ASSERT_VALID_PTR( cfgManagerMeta );
ResultCode resultCode;
initOptionsMetadata( cfgManagerMeta->optionsMeta );
ELASTIC_APM_CALL_IF_FAILED_GOTO( constructEnvVarNames( cfgManagerMeta->optionsMeta, /* out */ cfgManagerMeta->envVarNames ) );
initRawConfigSources( cfgManagerMeta->rawCfgSources );
resultCode = resultSuccess;
finally:
return resultCode;
failure:
destructConfigManagerMetadata( cfgManagerMeta );
goto finally;
}
ResultCode getConfigManagerOptionValueByName(
const ConfigManager* cfgManager
, String optionName
, GetConfigManagerOptionValueByNameResult* result
)
{
ELASTIC_APM_ASSERT_VALID_PTR( result );
ELASTIC_APM_ASSERT_VALID_PTR_TEXT_OUTPUT_STREAM( &result->txtOutStream );
const OptionMetadata* optMeta = NULL;
ELASTIC_APM_FOR_EACH_OPTION_ID( optId )
{
if ( areStringsEqualIgnoringCase( cfgManager->meta.optionsMeta[ optId ].name, optionName ) )
{
optMeta = &( cfgManager->meta.optionsMeta[ optId ] );
break;
}
}
if ( optMeta == NULL ) return resultFailure;
optMeta->parsedValueToZval( optMeta, optMeta->getField( optMeta, &cfgManager->current.snapshot ), &result->parsedValueAsZval );
result->streamedParsedValue = optMeta->streamParsedValue(
optMeta, optMeta->getField( optMeta, &( cfgManager->current.snapshot ) ), &result->txtOutStream );
return resultSuccess;
}
void getConfigManagerOptionMetadata(
const ConfigManager* cfgManager
, OptionId optId
, GetConfigManagerOptionMetadataResult* result
)
{
ELASTIC_APM_ASSERT_VALID_PTR( cfgManager );
ELASTIC_APM_ASSERT_VALID_PTR( result );
const OptionMetadata* const optMeta = &( cfgManager->meta.optionsMeta[ optId ] );
result->isSecret = optMeta->isSecret;
result->isDynamic = optMeta->isDynamic;
result->optName = optMeta->name;
result->envVarName = cfgManager->meta.envVarNames[ optId ];
result->iniName = optMeta->iniName;
}
void getConfigManagerOptionValueById(
const ConfigManager* cfgManager
, OptionId optId
, GetConfigManagerOptionValueByIdResult* result
)
{
ELASTIC_APM_ASSERT_VALID_PTR( cfgManager );
ELASTIC_APM_ASSERT_VALID_OPTION_ID( optId );
ELASTIC_APM_ASSERT_VALID_PTR( result );
ELASTIC_APM_ASSERT_VALID_PTR_TEXT_OUTPUT_STREAM( &result->txtOutStream );
const OptionMetadata* const optMeta = &( cfgManager->meta.optionsMeta[ optId ] );
const ParsedOptionValue parsedOpVal = optMeta->getField( optMeta, &( cfgManager->current.snapshot ) );
result->streamedParsedValue =
( parsedOpVal.type == parsedOptionValueType_string && parsedOpVal.u.stringValue == NULL )
? NULL
: optMeta->streamParsedValue( optMeta, parsedOpVal, &result->txtOutStream );
if ( cfgManager->current.rawData == NULL )
{
result->rawValue = NULL;
result->rawValueSourceDescription = NULL;
}
else
{
result->rawValue = cfgManager->current.rawData->combined.original[ optId ];
result->rawValueSourceDescription = cfgManager->current.rawData->combined.sourceDescriptions[ optId ];
}
}
void getConfigManagerRawData(
const ConfigManager* cfgManager,
OptionId optId,
RawConfigSourceId rawCfgSourceId,
/* out */ String* originalRawValue,
/* out */ String* interpretedRawValue )
{
ELASTIC_APM_ASSERT_VALID_PTR( cfgManager );
ELASTIC_APM_ASSERT_VALID_OPTION_ID( optId );
ELASTIC_APM_ASSERT_LT_UINT64( rawCfgSourceId, numberOfRawConfigSources );
ELASTIC_APM_ASSERT_VALID_OUT_PTR_TO_PTR( originalRawValue );
ELASTIC_APM_ASSERT_VALID_OUT_PTR_TO_PTR( interpretedRawValue );
*originalRawValue = cfgManager->current.rawData->fromSources[ rawCfgSourceId ].original[ optId ];
*interpretedRawValue = cfgManager->current.rawData->fromSources[ rawCfgSourceId ].interpreted[ optId ];
}
void deleteConfigManagerAndSetToNull( ConfigManager** pCfgManager )
{
ELASTIC_APM_ASSERT_VALID_PTR( pCfgManager );
ConfigManager* const cfgManager = *pCfgManager;
if ( cfgManager == NULL ) return;
ELASTIC_APM_ASSERT_VALID_PTR( cfgManager );
destructConfigManagerCurrentState( /* in,out */ &cfgManager->current );
destructConfigManagerMetadata( /* in,out */ &cfgManager->meta );
ELASTIC_APM_ZERO_STRUCT( cfgManager );
ELASTIC_APM_PEFREE_INSTANCE_AND_SET_TO_NULL( ConfigManager, *pCfgManager );
}
ResultCode newConfigManager( ConfigManager** pNewCfgManager, bool isLoggingRelatedOnly )
{
ELASTIC_APM_ASSERT_VALID_OUT_PTR_TO_PTR( pNewCfgManager );
ResultCode resultCode;
ConfigManager* cfgManager = NULL;
ELASTIC_APM_PEMALLOC_INSTANCE_IF_FAILED_GOTO( ConfigManager, cfgManager );
ELASTIC_APM_ZERO_STRUCT( cfgManager );
cfgManager->isLoggingRelatedOnly = isLoggingRelatedOnly;
ELASTIC_APM_CALL_IF_FAILED_GOTO( constructConfigManagerMetadata( /* out */ &cfgManager->meta ) );
initConfigManagerCurrentState( &cfgManager->meta, /* out */ &cfgManager->current );
resultCode = resultSuccess;
*pNewCfgManager = cfgManager;
finally:
return resultCode;
failure:
deleteConfigManagerAndSetToNull( /* in,out */ &cfgManager );
goto finally;
}