agent/native/ext/log.h (255 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. */ #pragma once #include "LogLevel.h" #include <stdbool.h> #include <stdarg.h> #ifndef PHP_WIN32 # include <syslog.h> #endif #include "ResultCode.h" #include "basic_types.h" #include "basic_macros.h" // ELASTIC_APM_PRINTF_ATTRIBUTE #include "TextOutputStream.h" #include "platform.h" extern String logLevelNames[ numberOfLogLevels ]; enum LogSinkType { logSink_stderr, #ifndef PHP_WIN32 logSink_syslog, #endif #ifdef PHP_WIN32 logSink_winSysDebug, #endif logSink_file, numberOfLogSinkTypes }; typedef enum LogSinkType LogSinkType; #ifdef __cplusplus inline LogSinkType &operator++(LogSinkType &type) { type = static_cast<LogSinkType>(static_cast<int>(type) + 1); return type; } #endif extern String logSinkTypeName[ numberOfLogSinkTypes ]; extern LogLevel defaultLogLevelPerSinkType[ numberOfLogSinkTypes ]; #define ELASTIC_APM_FOR_EACH_LOG_SINK_TYPE( logSinkTypeVar ) ELASTIC_APM_FOR_EACH_INDEX_EX( LogSinkType, logSinkTypeVar, numberOfLogSinkTypes ) struct LoggerConfig { LogLevel levelPerSinkType[ numberOfLogSinkTypes ]; String file = nullptr; }; typedef struct LoggerConfig LoggerConfig; enum { maxLoggerReentrancyDepth = 2 }; struct Logger { LoggerConfig config; char* messageBuffer; char* auxMessageBuffer; LogLevel maxEnabledLevel; UInt8 reentrancyDepth; bool fileFailed; }; typedef struct Logger Logger; ResultCode constructLogger( Logger* logger ); ResultCode reconfigureLogger( Logger* logger, const LoggerConfig* newConfig, LogLevel generalLevel ); void destructLogger( Logger* logger ); void logWithLogger( Logger* logger /* <- argument #1 */ , bool isForced , LogLevel statementLevel , StringView category , StringView filePath , UInt lineNumber , StringView funcName , String msgPrintfFmt /* <- printf format is argument #8 */ , ... /* <- arguments for printf format placeholders start from argument #9 */ ) ELASTIC_APM_PRINTF_ATTRIBUTE( /* printfFmtPos: */ 8, /* printfFmtArgsPos: */ 9 ); void vLogWithLogger( Logger* logger , bool isForced , LogLevel statementLevel , StringView category , StringView filePath , UInt lineNumber , StringView funcName , String msgPrintfFmt , va_list msgPrintfFmtArgs ); LogLevel calcMaxEnabledLogLevel( LogLevel levelPerSinkType[ numberOfLogSinkTypes ] ); Logger* getGlobalLogger(); bool isInLogContext(); const char* logLevelToName( LogLevel level ); #define ELASTIC_APM_LOG_LINE_PREFIX_TRACER_PART "[Elastic APM PHP Tracer]" #ifdef PHP_WIN32 # define ELASTIC_APM_LOG_TO_BACKGROUND_SINK( statementLevel, fmt, ... ) #else // #ifdef PHP_WIN32 int logLevelToSyslog( LogLevel level ); # define ELASTIC_APM_LOG_WRITE_TO_SYSLOG( statementLevel, fmt, ... ) \ syslog( \ logLevelToSyslog( statementLevel ) \ , ELASTIC_APM_LOG_LINE_PREFIX_TRACER_PART \ " [PID: %d]" \ " [TID: %d]" \ " [%s] " \ fmt \ , (int)(getCurrentProcessId()) \ , (int)(getCurrentThreadId()) \ , logLevelToName( statementLevel ) \ , ##__VA_ARGS__ ) extern LogLevel g_elasticApmDirectLogLevelSyslog; # define ELASTIC_APM_LOG_TO_BACKGROUND_SINK( statementLevel, fmt, ... ) \ do { \ if ( g_elasticApmDirectLogLevelSyslog >= (statementLevel) ) \ { \ ELASTIC_APM_LOG_WRITE_TO_SYSLOG( statementLevel, fmt, ##__VA_ARGS__ ); \ } \ } while ( 0 ) #endif // #ifdef PHP_WIN32 #define ELASTIC_APM_LOG_WRITE_TO_STDERR( statementLevel, fmt, ... ) \ do { \ fprintf( stderr \ , ELASTIC_APM_LOG_LINE_PREFIX_TRACER_PART \ " [PID: %d]" \ " [TID: %d]" \ " [%s] " \ fmt "\n" \ , (int)(getCurrentProcessId()) \ , (int)(getCurrentThreadId()) \ , logLevelToName( statementLevel ) \ , ##__VA_ARGS__ ); \ fflush( stderr ); \ } while ( 0 ) extern LogLevel g_elasticApmDirectLogLevelStderr; #define ELASTIC_APM_LOG_DIRECT( statementLevel, fmt, ... ) \ do { \ ELASTIC_APM_LOG_TO_BACKGROUND_SINK( (statementLevel), fmt, ##__VA_ARGS__ ); \ if ( g_elasticApmDirectLogLevelStderr >= (statementLevel) ) \ { \ ELASTIC_APM_LOG_WRITE_TO_STDERR( (statementLevel), fmt, ##__VA_ARGS__ ); \ } \ } while ( 0 ) #define ELASTIC_APM_LOG_WITH_LEVEL( statementLevel, fmt, ... ) \ do { \ Logger* const globalStateLogger = getGlobalLogger(); \ if ( globalStateLogger->maxEnabledLevel >= (statementLevel) ) \ { \ if ( isInLogContext() ) \ { \ ELASTIC_APM_LOG_DIRECT( statementLevel, fmt, ##__VA_ARGS__ ); \ } \ else \ { \ logWithLogger( \ globalStateLogger, \ /* isForced: */ false, \ (statementLevel), \ ELASTIC_APM_STRING_LITERAL_TO_VIEW( ELASTIC_APM_CURRENT_LOG_CATEGORY ), \ ELASTIC_APM_STRING_LITERAL_TO_VIEW( __FILE__ ), \ __LINE__, \ ELASTIC_APM_STRING_LITERAL_TO_VIEW( __FUNCTION__ ), \ (fmt) , ##__VA_ARGS__ ); \ } \ } \ } while ( 0 ) #define ELASTIC_APM_LOG_CRITICAL( fmt, ... ) ELASTIC_APM_LOG_WITH_LEVEL( logLevel_critical, fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_ERROR( fmt, ... ) ELASTIC_APM_LOG_WITH_LEVEL( logLevel_error, fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_WARNING( fmt, ... ) ELASTIC_APM_LOG_WITH_LEVEL( logLevel_warning, fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_INFO( fmt, ... ) ELASTIC_APM_LOG_WITH_LEVEL( logLevel_info, fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_DEBUG( fmt, ... ) ELASTIC_APM_LOG_WITH_LEVEL( logLevel_debug, fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_TRACE( fmt, ... ) ELASTIC_APM_LOG_WITH_LEVEL( logLevel_trace, fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_CONDITIONAL_CTX_SEPARATOR( separator, fmt ) \ ( ELASTIC_APM_STATIC_ARRAY_SIZE( fmt ) > 1 ? (separator) : "" ) #define ELASTIC_APM_LOG_FUNCTION_PREFIX_MSG_WITH_LEVEL( statementLevel, prefix, fmt, ... ) \ ELASTIC_APM_LOG_WITH_LEVEL( statementLevel, "%s%s" fmt, prefix, ELASTIC_APM_LOG_CONDITIONAL_CTX_SEPARATOR( "; ", fmt ), ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_FUNCTION_ENTRY_MSG_WITH_LEVEL( statementLevel, fmt, ... ) \ ELASTIC_APM_LOG_FUNCTION_PREFIX_MSG_WITH_LEVEL( statementLevel, "Entered", fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_DEBUG_FUNCTION_ENTRY_MSG( fmt, ... ) ELASTIC_APM_LOG_FUNCTION_ENTRY_MSG_WITH_LEVEL( logLevel_debug, fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_TRACE_FUNCTION_ENTRY_MSG( fmt, ... ) ELASTIC_APM_LOG_FUNCTION_ENTRY_MSG_WITH_LEVEL( logLevel_trace, fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_DEBUG_FUNCTION_ENTRY() ELASTIC_APM_LOG_DEBUG_FUNCTION_ENTRY_MSG( "" ) #define ELASTIC_APM_LOG_TRACE_FUNCTION_ENTRY() ELASTIC_APM_LOG_TRACE_FUNCTION_ENTRY_MSG( "" ) #define ELASTIC_APM_LOG_FUNCTION_EXIT_MSG_WITH_LEVEL( statementLevel, fmt, ... ) \ ELASTIC_APM_LOG_FUNCTION_PREFIX_MSG_WITH_LEVEL( statementLevel, "Exiting...", fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_DEBUG_FUNCTION_EXIT_MSG( fmt, ... ) ELASTIC_APM_LOG_FUNCTION_EXIT_MSG_WITH_LEVEL( logLevel_debug, fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_TRACE_FUNCTION_EXIT_MSG( fmt, ... ) ELASTIC_APM_LOG_FUNCTION_EXIT_MSG_WITH_LEVEL( logLevel_trace, fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_DEBUG_FUNCTION_EXIT() ELASTIC_APM_LOG_DEBUG_FUNCTION_EXIT_MSG( "" ) #define ELASTIC_APM_LOG_TRACE_FUNCTION_EXIT() ELASTIC_APM_LOG_TRACE_FUNCTION_EXIT_MSG( "" ) #define ELASTIC_APM_LOG_RESULT_CODE_FUNCTION_EXIT_MSG_WITH_LEVEL( successLevel, fmt, ... ) \ ELASTIC_APM_LOG_FUNCTION_EXIT_MSG_WITH_LEVEL \ ( \ resultCode == resultSuccess ? (successLevel) : logLevel_error \ , "resultCode: %s (%d); " fmt \ , resultCodeToString( resultCode ), resultCode , ##__VA_ARGS__ \ ) #define ELASTIC_APM_LOG_DEBUG_RESULT_CODE_FUNCTION_EXIT_MSG( fmt, ... ) ELASTIC_APM_LOG_RESULT_CODE_FUNCTION_EXIT_MSG_WITH_LEVEL( logLevel_debug, fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_TRACE_RESULT_CODE_FUNCTION_EXIT_MSG( fmt, ... ) ELASTIC_APM_LOG_RESULT_CODE_FUNCTION_EXIT_MSG_WITH_LEVEL( logLevel_trace, fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_DEBUG_RESULT_CODE_FUNCTION_EXIT() ELASTIC_APM_LOG_DEBUG_RESULT_CODE_FUNCTION_EXIT_MSG( "" ) #define ELASTIC_APM_LOG_TRACE_RESULT_CODE_FUNCTION_EXIT() ELASTIC_APM_LOG_TRACE_RESULT_CODE_FUNCTION_EXIT_MSG( "" ) #define ELASTIC_APM_FORCE_LOG_CRITICAL( fmt, ... ) \ do { \ logWithLogger( \ getGlobalLogger(), \ /* isForced: */ true, \ logLevel_critical, \ ELASTIC_APM_STRING_LITERAL_TO_VIEW( ELASTIC_APM_CURRENT_LOG_CATEGORY ), \ ELASTIC_APM_STRING_LITERAL_TO_VIEW( __FILE__ ), \ __LINE__, \ ELASTIC_APM_STRING_LITERAL_TO_VIEW( __FUNCTION__ ), \ (fmt) , ##__VA_ARGS__ ); \ } while ( 0 ) static inline String streamLogLevel( LogLevel level, TextOutputStream* txtOutStream ) { if ( level == logLevel_not_set ) return streamStringView( ELASTIC_APM_STRING_LITERAL_TO_VIEW( "not_set" ), txtOutStream ); if ( level >= numberOfLogLevels ) return streamInt( level, txtOutStream ); return streamString( logLevelToName( level ), txtOutStream ); } static inline LogLevel maxEnabledLogLevel() { return getGlobalLogger()->maxEnabledLevel; } static inline bool canLogSecuritySensitive() { return maxEnabledLogLevel() >= logLevel_debug; } static inline String logSecuritySensitiveOr( String securitySensitiveString, String notSecuritySensitiveAltString ) { return canLogSecuritySensitive() ? securitySensitiveString : notSecuritySensitiveAltString; } static inline String logSecuritySensitive( String securitySensitiveString ) { return logSecuritySensitiveOr( securitySensitiveString, /* notSecuritySensitiveAltString */ "REDACTED" ); } ResultCode resetLoggingStateInForkedChild(); #define ELASTIC_APM_LOG_CATEGORY_ASSERT "Assert" #define ELASTIC_APM_LOG_CATEGORY_AUTO_INSTRUMENT "Auto-Instrument" #define ELASTIC_APM_LOG_CATEGORY_BACKEND_COMM "Backend-Comm" #define ELASTIC_APM_LOG_CATEGORY_CONFIG "Configuration" #define ELASTIC_APM_LOG_CATEGORY_C_TO_PHP "C-to-PHP" #define ELASTIC_APM_LOG_CATEGORY_EXT_API "Ext-API" #define ELASTIC_APM_LOG_CATEGORY_EXT_INFRA "Ext-Infra" #define ELASTIC_APM_LOG_CATEGORY_LIFECYCLE "Lifecycle" #define ELASTIC_APM_LOG_CATEGORY_LOG "Log" #define ELASTIC_APM_LOG_CATEGORY_MEM_TRACKER "Memory-Tracker" #define ELASTIC_APM_LOG_CATEGORY_PLATFORM "Platform" #define ELASTIC_APM_LOG_CATEGORY_SUPPORT "Supportability" #define ELASTIC_APM_LOG_CATEGORY_SYS_METRICS "System-Metrics" #define ELASTIC_APM_LOG_CATEGORY_UTIL "Util" #define ELASTIC_APM_LOG_DIRECT_CRITICAL( fmt, ... ) ELASTIC_APM_LOG_DIRECT( logLevel_critical, fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_DIRECT_WARNING( fmt, ... ) ELASTIC_APM_LOG_DIRECT( logLevel_warning, fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_DIRECT_INFO( fmt, ... ) ELASTIC_APM_LOG_DIRECT( logLevel_info, fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_LOG_DIRECT_DEBUG( fmt, ... ) ELASTIC_APM_LOG_DIRECT( logLevel_debug, fmt, ##__VA_ARGS__ ) #ifdef PHP_WIN32 #define ELASTIC_APM_SIGNAL_SAFE_LOG_CRITICAL( fmt, ... ) #define ELASTIC_APM_SIGNAL_SAFE_LOG_WARNING( fmt, ... ) #define ELASTIC_APM_SIGNAL_SAFE_LOG_DEBUG( fmt, ... ) #else // #ifdef PHP_WIN32 #define ELASTIC_APM_SIGNAL_SAFE_LOG_CRITICAL( fmt, ... ) ELASTIC_APM_LOG_TO_BACKGROUND_SINK( logLevel_critical, fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_SIGNAL_SAFE_LOG_WARNING( fmt, ... ) ELASTIC_APM_LOG_TO_BACKGROUND_SINK( logLevel_warning, fmt, ##__VA_ARGS__ ) #define ELASTIC_APM_SIGNAL_SAFE_LOG_DEBUG( fmt, ... ) ELASTIC_APM_LOG_TO_BACKGROUND_SINK( logLevel_debug, fmt, ##__VA_ARGS__ ) #endif // #ifdef PHP_WIN32