prod/native/extension/code/ModuleInit.cpp (80 lines of code) (raw):
/*
* Copyright Elasticsearch B.V. and/or 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.
*/
#if defined(PHP_WIN32) && ! defined(CURL_STATICLIB)
# define CURL_STATICLIB
#endif
#include "elastic_otel_version.h"
#include "CommonUtils.h"
#include "ConfigurationManager.h"
#include "ConfigurationSnapshot.h"
#include "ForkHandler.h"
#include "Hooking.h"
#include "InternalFunctionInstrumentation.h"
#include "ModuleIniEntries.h"
#include "ModuleFunctions.h"
#include "ModuleGlobals.h"
#include "PeriodicTaskExecutor.h"
#include "RequestScope.h"
#include "SigSegvHandler.h"
#include "os/OsUtils.h"
#include <curl/curl.h>
#include <inttypes.h> // PRIu64
#include <stdbool.h>
#include <php.h>
#include <zend_compile.h>
#include <zend_exceptions.h>
#include <zend_builtin_functions.h>
#include <Zend/zend_observer.h>
#include "php_error.h"
#include "util_for_PHP.h"
extern elasticapm::php::ConfigurationManager configManager;
void logStartupPreamble(elasticapm::php::LoggerInterface *logger) {
constexpr LogLevel level = LogLevel::logLevel_debug;
constexpr int colWidth = 40;
using namespace std::literals;
ELOGF_NF(logger, level, "Elastic Distribution for OpenTelemetry PHP");
ELOGF_NF(logger, level, "%*s%s", -colWidth, "Native part version:", ELASTIC_OTEL_VERSION);
ELOGF_NF(logger, level, "%*s%s", -colWidth, "Process command line:", elasticapm::utils::sanitizeKeyValueString(elasticapm::utils::getEnvName(EL_STRINGIFY(ELASTIC_OTEL_CFG_OPT_NAME_API_KEY)), elasticapm::osutils::getCommandLine()).c_str());
ELOGF_NF(logger, level, "%*s%s", -colWidth, "Process environment:", elasticapm::utils::sanitizeKeyValueString(elasticapm::utils::getEnvName(EL_STRINGIFY(ELASTIC_OTEL_CFG_OPT_NAME_API_KEY)), elasticapm::osutils::getProcessEnvironment()).c_str());
}
void elasticApmModuleInit(int moduleType, int moduleNumber) {
auto const &sapi = *ELASTICAPM_G(globals)->sapi_;
auto globals = ELASTICAPM_G(globals);
elasticapm::php::registerElasticApmIniEntries(EAPM_GL(logger_).get(), moduleNumber);
configManager.update();
globals->config_->update();
ELOGF_DEBUG(globals->logger_, MODULE, "%s entered: moduleType: %d, moduleNumber: %d, parent PID: %d, SAPI: %s (%d) is %s", __FUNCTION__, moduleType, moduleNumber, static_cast<int>(elasticapm::osutils::getParentProcessId()), sapi.getName().data(), static_cast<uint8_t>(sapi.getType()), sapi.isSupported() ? "supported" : "unsupported");
if (!sapi.isSupported()) {
return;
}
registerSigSegvHandler(globals->logger_.get());
logStartupPreamble(globals->logger_.get());
if (!EAPM_CFG(enabled)) {
ELOGF_INFO(globals->logger_, MODULE, "Extension is disabled");
return;
}
if (EAPM_CFG(bootstrap_php_part_file).empty()) {
ELOGF_WARNING(globals->logger_, MODULE, "bootstrap_php_part_file configuration option is not set - extension will be disabled");
return;
}
ELOGF_DEBUG(globals->logger_, MODULE, "MINIT Replacing hooks");
elasticapm::php::Hooking::getInstance().fetchOriginalHooks();
elasticapm::php::Hooking::getInstance().replaceHooks(globals->config_->get().inferred_spans_enabled, globals->config_->get().dependency_autoloader_guard_enabled);
zend_observer_activate();
zend_observer_fcall_register(elasticapm::php::elasticRegisterObserver);
if (php_check_open_basedir_ex(EAPM_GL(config_)->get(&elasticapm::php::ConfigurationSnapshot::bootstrap_php_part_file).c_str(), false) != 0) {
ELOGF_WARNING(globals->logger_, MODULE, "EDOT PHP bootstrap file (%s) is located outside of paths allowed by open_basedir ini setting. Read more details here https://elastic.github.io/opentelemetry/edot-sdks/php/setup/limitations.html", EAPM_GL(config_)->get(&elasticapm::php::ConfigurationSnapshot::bootstrap_php_part_file).c_str());
}
}
void elasticApmModuleShutdown( int moduleType, int moduleNumber ) {
if (!ELASTICAPM_G(globals)->sapi_->isSupported()) {
return;
}
if (!EAPM_CFG(enabled)) {
return;
}
if (EAPM_CFG(bootstrap_php_part_file).empty()) {
return;
}
elasticapm::php::Hooking::getInstance().restoreOriginalHooks();
// curl_global_cleanup();
zend_unregister_ini_entries(moduleNumber);
unregisterSigSegvHandler();
}
// void elasticApmGetLastPhpError(zval* return_value) {
// if (!ELASTICAPM_G(lastErrorData)) {
// RETURN_NULL();
// }
// array_init( return_value );
// ELASTIC_OTEL_ZEND_ADD_ASSOC(return_value, "type", long, static_cast<zend_long>(ELASTICAPM_G(lastErrorData)->getType()));
// ELASTIC_OTEL_ZEND_ADD_ASSOC_NULLABLE_STRING( return_value, "fileName", ELASTICAPM_G(lastErrorData)->getFileName().data() );
// ELASTIC_OTEL_ZEND_ADD_ASSOC(return_value, "lineNumber", long, static_cast<zend_long>(ELASTICAPM_G(lastErrorData)->getLineNumber()));
// ELASTIC_OTEL_ZEND_ADD_ASSOC_NULLABLE_STRING( return_value, "message", ELASTICAPM_G(lastErrorData)->getMessage().data());
// Z_TRY_ADDREF_P((ELASTICAPM_G(lastErrorData)->getStackTrace()));
// ELASTIC_OTEL_ZEND_ADD_ASSOC(return_value, "stackTrace", zval, (ELASTICAPM_G(lastErrorData)->getStackTrace()));
// }
//
// void elasticApmGetLastThrown(zval *return_value) {
// if (Z_TYPE(ELASTICAPM_G(lastException)) == IS_UNDEF) {
// RETURN_NULL();
// }
// RETURN_ZVAL(&ELASTICAPM_G(lastException), /* copy */ true, /* dtor */ false );
// }