Skip to content

Commit

Permalink
Merge pull request #1006 from DataDog/labbati/defer-integrations
Browse files Browse the repository at this point in the history
Defer loading of PDO, Memcached, Slim, WordPress, and Yii integrations until first usage
  • Loading branch information
morrisonlevi authored and SammyK committed Oct 14, 2020
1 parent 46c9da3 commit 7de83cb
Show file tree
Hide file tree
Showing 12 changed files with 189 additions and 252 deletions.
1 change: 0 additions & 1 deletion bridge/_files.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@
__DIR__ . '/../src/DDTrace/Integrations/Laravel/LaravelIntegration.php',
__DIR__ . '/../src/DDTrace/Integrations/Lumen/LumenIntegration.php',
__DIR__ . '/../src/DDTrace/Integrations/Guzzle/GuzzleIntegration.php',
__DIR__ . '/../src/DDTrace/Integrations/Yii/V2/YiiIntegrationLoader.php',
__DIR__ . '/../src/DDTrace/Integrations/Yii/YiiIntegration.php',
__DIR__ . '/../src/DDTrace/Integrations/WordPress/WordPressIntegration.php',
__DIR__ . '/../src/DDTrace/Integrations/WordPress/V4/WordPressIntegrationLoader.php',
Expand Down
1 change: 1 addition & 0 deletions dockerfiles/ci/xfail_tests/5.6.list
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ ext/standard/tests/serialize/bug21957.phpt
ext/standard/tests/serialize/bug27469.phpt
ext/standard/tests/serialize/bug30234.phpt
ext/standard/tests/serialize/bug62836_1.phpt
ext/standard/tests/serialize/bug64146.phpt
ext/standard/tests/serialize/bug68976.phpt
ext/standard/tests/serialize/bug69210.phpt
ext/standard/tests/serialize/bug69425.phpt
Expand Down
24 changes: 12 additions & 12 deletions src/DDTrace/Integrations/IntegrationsLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,31 +73,31 @@ public function __construct(array $integrations)
'\DDTrace\Integrations\Laravel\LaravelIntegration';
$this->integrations[LumenIntegration::NAME] =
'\DDTrace\Integrations\Lumen\LumenIntegration';
$this->integrations[MemcachedIntegration::NAME] =
'\DDTrace\Integrations\Memcached\MemcachedIntegration';
$this->integrations[MongoIntegration::NAME] =
'\DDTrace\Integrations\Mongo\MongoIntegration';
$this->integrations[MysqliIntegration::NAME] =
'\DDTrace\Integrations\Mysqli\MysqliIntegration';
$this->integrations[PDOIntegration::NAME] =
'\DDTrace\Integrations\PDO\PDOIntegration';
$this->integrations[SlimIntegration::NAME] =
'\DDTrace\Integrations\Slim\SlimIntegration';
$this->integrations[SymfonyIntegration::NAME] =
'\DDTrace\Integrations\Symfony\SymfonyIntegration';
$this->integrations[WordPressIntegration::NAME] =
'\DDTrace\Integrations\WordPress\WordPressIntegration';
$this->integrations[YiiIntegration::NAME] =
'\DDTrace\Integrations\Yii\YiiIntegration';
$this->integrations[ZendFrameworkIntegration::NAME] =
'\DDTrace\Integrations\ZendFramework\ZendFrameworkIntegration';

// For PHP 7.0+ use C level deferred integration loader
if (\PHP_MAJOR_VERSION < 7) {
$this->integrations[PredisIntegration::NAME] =
'\DDTrace\Integrations\Predis\PredisIntegration';
$this->integrations[ElasticSearchIntegration::NAME] =
'\DDTrace\Integrations\ElasticSearch\V1\ElasticSearchIntegration';
$this->integrations[MemcachedIntegration::NAME] =
'\DDTrace\Integrations\Memcached\MemcachedIntegration';
$this->integrations[PDOIntegration::NAME] =
'\DDTrace\Integrations\PDO\PDOIntegration';
$this->integrations[PredisIntegration::NAME] =
'\DDTrace\Integrations\Predis\PredisIntegration';
$this->integrations[SlimIntegration::NAME] =
'\DDTrace\Integrations\Slim\SlimIntegration';
$this->integrations[YiiIntegration::NAME] =
'\DDTrace\Integrations\Yii\YiiIntegration';
$this->integrations[WordPressIntegration::NAME] =
'\DDTrace\Integrations\WordPress\WordPressIntegration';
}
}

Expand Down
21 changes: 2 additions & 19 deletions src/DDTrace/Integrations/WordPress/WordPressIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,6 @@ class WordPressIntegration extends Integration
{
const NAME = 'wordpress';

/**
* @var self
*/
private static $instance;

/**
* @return self
*/
public static function getInstance()
{
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}

/**
* @return string The integration name.
*/
Expand All @@ -50,10 +34,10 @@ public function init()
return self::NOT_AVAILABLE;
}

$integration = self::getInstance();
$integration = $this;

// This call happens right after WP registers an autoloader for the first time
\DDTrace\trace_method('Requests', 'set_certificate_path', function () use ($integration) {
\DDTrace\hook_method('Requests', 'set_certificate_path', null, function () use ($integration) {
if (!isset($GLOBALS['wp_version']) || !is_string($GLOBALS['wp_version'])) {
return false;
}
Expand All @@ -62,7 +46,6 @@ public function init()
$loader = new WordPressIntegrationLoader();
$loader->load($integration);
}
return false; // Drop this span to reduce noise
});

return self::LOADED;
Expand Down
120 changes: 0 additions & 120 deletions src/DDTrace/Integrations/Yii/V2/YiiIntegrationLoader.php

This file was deleted.

130 changes: 109 additions & 21 deletions src/DDTrace/Integrations/Yii/YiiIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,19 @@

namespace DDTrace\Integrations\Yii;

use DDTrace\Contracts\Scope;
use DDTrace\GlobalTracer;
use DDTrace\Integrations\Integration;
use DDTrace\SpanData;
use DDTrace\Tag;
use DDTrace\Type;
use DDTrace\Util\Versions;
use yii\helpers\Url;

class YiiIntegration extends Integration
{
const NAME = 'yii';

/**
* @var self
*/
private static $instance;

/**
* @return self
*/
public static function getInstance()
{
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}

/**
* @return string The integration name.
*/
Expand All @@ -50,17 +40,115 @@ public function init()
return self::NOT_AVAILABLE;
}

$integration = self::getInstance();
$integration = $this;

// This happens somewhat early in the setup, though there may be a better candidate
\DDTrace\trace_method('yii\di\Container', '__construct', function () use ($integration) {
\DDTrace\hook_method('yii\di\Container', '__construct', null, function () use ($integration) {
if (Versions::versionMatches('2.0', \Yii::getVersion())) {
$loader = new V2\YiiIntegrationLoader();
$loader->load($integration);
$integration->loadV2();
}
return false; // Drop this span to reduce noise
});

return self::LOADED;
}

public function loadV2()
{
$scope = GlobalTracer::get()->getRootScope();
if (!$scope instanceof Scope) {
return;
}
$root = $scope->getSpan();
$this->addTraceAnalyticsIfEnabledLegacy($root);
$service = \ddtrace_config_app_name(YiiIntegration::NAME);

\DDTrace\trace_method(
'yii\web\Application',
'run',
function (SpanData $span) use ($service) {
$span->name = $span->resource = \get_class($this) . '.run';
$span->type = Type::WEB_SERVLET;
$span->service = $service;
}
);

// We assume the first controller is the one to assign to app.endpoint
$firstController = null;
\DDTrace\hook_method(
'yii\web\Application',
'createController',
null,
function ($app, $appClass, $args, $retval) use (&$firstController) {
if ($firstController === null && isset($args[0], $retval) && \is_array($retval) && !empty($retval)) {
$firstController = $retval[0];
}
}
);

/* Note that Applications are Modules, so this will also trace Application::runAction, but
* modules are worth tracing independently, as multiple modules can trigger per
* application, such as in the event of an unhandled exception.
*/
\DDTrace\trace_method(
'yii\base\Module',
'runAction',
function (SpanData $span, $args) use ($service) {
$span->name = \get_class($this) . '.runAction';
$span->type = Type::WEB_SERVLET;
$span->service = $service;
$span->resource = isset($args[0]) && \is_string($args[0]) ? $args[0] : $span->name;
}
);

\DDTrace\trace_method(
'yii\base\Controller',
'runAction',
function (SpanData $span, $args) use (&$firstController, $service, $root) {
$span->name = \get_class($this) . '.runAction';
$span->type = Type::WEB_SERVLET;
$span->service = $service;
$span->resource = isset($args[0]) && \is_string($args[0]) ? $args[0] : $span->name;

if (
$firstController === $this
&& $root->getTag('app.endpoint') === null
&& isset($this->action->actionMethod)
) {
$controller = \get_class($this);
$endpoint = "{$controller}::{$this->action->actionMethod}";
$root->setTag("app.endpoint", $endpoint);
$root->setTag(Tag::HTTP_URL, Url::base(true) . Url::current());
}

if ($root->getTag('app.route.path') === null) {
$route = $this->module->requestedRoute;
$namedParams = [$route];
$placeholders = [$route];
if (isset($args[1]) && \is_array($args[1]) && !empty($args[1])) {
foreach ($args[1] as $param => $unused) {
$namedParams[$param] = ":{$param}";
$placeholders[$param] = '?';
}
}

$routePath = \urldecode(Url::toRoute($namedParams));
$root->setTag('app.route.path', $routePath);

$resourceName = \urldecode(Url::toRoute($placeholders));
$root->setTag(Tag::RESOURCE_NAME, "{$_SERVER['REQUEST_METHOD']} {$resourceName}", true);
}
}
);

\DDTrace\trace_method(
'yii\base\View',
'renderFile',
function (SpanData $span, $args) use ($service) {
$span->name = \get_class($this) . '.renderFile';
$span->type = Type::WEB_SERVLET;
$span->service = $service;
$span->resource = isset($args[0]) && \is_string($args[0]) ? $args[0] : $span->name;
}
);
}
}

0 comments on commit 7de83cb

Please sign in to comment.