Skip to content

Commit

Permalink
Add Guzzle v5 integration
Browse files Browse the repository at this point in the history
  • Loading branch information
SammyK committed Nov 27, 2018
1 parent 1619cf7 commit 7829665
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 0 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"opentracing/opentracing": "1.0.0-beta5"
},
"require-dev": {
"guzzlehttp/guzzle": "^5.0",
"phpcompatibility/php-compatibility": "^9.0",
"phpcompatibility/phpcompatibility-passwordcompat": "^1.0",
"phpcompatibility/phpcompatibility-symfony": "*",
Expand Down
28 changes: 28 additions & 0 deletions src/DDTrace/Integrations/Guzzle/v5/GuzzleIntegration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace DDTrace\Integrations\Guzzle\v5;

use DDTrace\Tags;
use DDTrace\Types;
use OpenTracing\Span;
use DDTrace\Integrations\Integration;

class GuzzleIntegration extends Integration
{
const CLASS_NAME = 'GuzzleHttp\Client';

public static function load()
{
parent::load();
self::traceMethod('send', function (Span $span, array $args) {
$span->setTag('http.method', $args[0]->getMethod());
});
}

public static function setDefaultTags(Span $span, $method)
{
parent::setDefaultTags($span, $method);
$span->setTag(Tags\SPAN_TYPE, Types\GUZZLE);
$span->setTag(Tags\SERVICE_NAME, 'guzzle');
}
}
62 changes: 62 additions & 0 deletions src/DDTrace/Integrations/Integration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace DDTrace\Integrations;

use DDTrace\Tags;
use OpenTracing\Span;
use OpenTracing\GlobalTracer;

abstract class Integration
{
const CLASS_NAME = '';

public static function load()
{
if (!extension_loaded('ddtrace')) {
trigger_error('The ddtrace extension is required to trace ' . static::CLASS_NAME, E_USER_WARNING);
return;
}
if (!class_exists(static::CLASS_NAME)) {
trigger_error(static::CLASS_NAME . ' is not loaded and cannot be traced', E_USER_WARNING);
return;
}
}

/**
* @param string $method
* @param \Closure $spanMutator
*/
protected static function traceMethod($method, \Closure $spanMutator = null)
{
$className = static::CLASS_NAME;
$integrationClass = get_called_class();
dd_trace($className, $method, function () use ($className, $integrationClass, $method, $spanMutator) {
$args = func_get_args();
$scope = GlobalTracer::get()->startActiveSpan($className . '.' . $method);
$span = $scope->getSpan();
$integrationClass::setDefaultTags($span, $method);
if (null !== $spanMutator) {
$spanMutator($span, $args);
}

$returnVal = null;
$thrownException = null;
try {
$returnVal = call_user_func_array([$this, $method], $args);
} catch (\Exception $e) {
$span->setError($e);
$thrownException = $e;
}
$scope->close();
if (null !== $thrownException) {
throw $thrownException;
}
return $returnVal;
});
}

public static function setDefaultTags(Span $span, $method)
{
$span->setTag(Tags\RESOURCE_NAME, $method);
}
}
1 change: 1 addition & 0 deletions src/DDTrace/Types.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
const SQL = 'sql';

const CASSANDRA = 'cassandra';
const GUZZLE = 'guzzle';
const MEMCACHED = 'memcached';
const MONGO = 'mongodb';
const REDIS = 'redis';
Expand Down
71 changes: 71 additions & 0 deletions tests/Integration/Integrations/Guzzle/v5/GuzzleIntegrationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

namespace DDTrace\Tests\Integration\Integrations\Guzzle\v5;

use GuzzleHttp\Client;
use GuzzleHttp\Message\Request;
use GuzzleHttp\Ring\Client\MockHandler;
use DDTrace\Tests\Integration\Common\SpanAssertion;
use DDTrace\Integrations\Guzzle\v5\GuzzleIntegration;
use DDTrace\Tests\Integration\Common\IntegrationTestCase;

final class GuzzleIntegrationTest extends IntegrationTestCase
{
/** @var Client */
private $client;

public static function setUpBeforeClass()
{
GuzzleIntegration::load();
}

protected function setUp()
{
parent::setUp();
$handler = new MockHandler(['status' => 200]);
$this->client = new Client(['handler' => $handler]);
}

/**
* @dataProvider providerHttpMethods
*/
public function testAliasMethods($method)
{
$traces = $this->isolateTracer(function () use ($method) {
$this->client->$method('http://example.com');
});
$this->assertSpans($traces, [
SpanAssertion::build('GuzzleHttp\Client.send', 'guzzle', 'guzzle', 'send')
->withExactTags([
'http.method' => strtoupper($method),
]),
]);
}

public function providerHttpMethods()
{
return [
['get'],
['delete'],
['head'],
['options'],
['patch'],
['post'],
['put'],
];
}

public function testSend()
{
$traces = $this->isolateTracer(function () {
$request = new Request('put', 'http://example.com');
$this->client->send($request);
});
$this->assertSpans($traces, [
SpanAssertion::build('GuzzleHttp\Client.send', 'guzzle', 'guzzle', 'send')
->withExactTags([
'http.method' => 'PUT',
]),
]);
}
}

0 comments on commit 7829665

Please sign in to comment.