<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
performance-x / opentelemetry-php-instrumentation-trait example snippets
namespace OpenTelemetry\Contrib\Instrumentation\Drupal;
use Drupal\Core\Cache\CacheBackendInterface;
use OpenTelemetry\API\Trace\SpanKind;
use PerformanceX\OpenTelemetry\Instrumentation\InstrumentationTrait;
class CacheBackendInstrumentation {
use InstrumentationTrait;
public static function register(): void {
// Create instance with name and prefix
$instrumentation = self::create(
name: 'io.opentelemetry.contrib.php.drupal',
prefix: 'drupal.cache',
className: CacheBackendInterface::class
);
// Or with custom span kind
$instrumentation = self::create(
name: 'io.opentelemetry.contrib.php.drupal',
prefix: 'drupal.cache',
spanKind: SpanKind::KIND_CLIENT,
className: CacheBackendInterface::class
);
// Or with pre-configured instrumentation
$instrumentation = self::create(
instrumentation: new CachedInstrumentation('custom.name'),
prefix: 'drupal.cache',
className: CacheBackendInterface::class
);
// Register method hooks
$instrumentation
->helperHook(
'get',
['cid'],
'returnValue'
)
->helperHook(
'set',
['cid', 'data', 'expire', 'tags'],
'returnValue',
preHandler: function($spanBuilder, $object, array $params, $class, $function, $filename, $lineno) {
$spanBuilder->setAttribute($this->getAttributeName('ttl'), $params[2] ?? 0);
},
postHandler: function($span, $object, array $params, $returnValue, $exception) {
$span->setAttribute($this->getAttributeName('success'), $returnValue !== FALSE);
}
);
}
}
$instrumentation->helperHook(
'save',
['entity'],
preHandler: function($spanBuilder, $object, array $params) {
$entity = $params[0];
// Instead of directly setting the name (which isn't possible at this stage),
// use the UPDATE_NAME attribute
$spanBuilder->setAttribute(
static::UPDATE_NAME,
sprintf(
'Entity save (%s:%s)',
$entity->getEntityTypeId(),
$entity->isNew() ? 'new' : $entity->id()
)
);
}
);
// When called with a new article entity:
$entity->save();
// Creates span with name: "Entity save (article:new)"
// When called with an existing article entity:
$entity->save();
// Creates span with name: "Entity save (article:123)"
/**
* @see \Drupal\Core\Cache\CacheBackendInterface::set()
*/
$instrumentation->helperHook(
'set',
[
'cid', // String cache ID stored as-is
'data', // Complex data will be JSON encoded
'expire', // Integer timestamp stored as-is
'tags', // Array will be JSON encoded
],
'returnValue'
);
// When called with:
$cache->set('my-key', ['foo' => 'bar'], time() + 3600, ['tag1', 'tag2']);
// Creates span attributes:
// drupal.cache.cid = "my-key"
// drupal.cache.data = "{\"foo\":\"bar\"}"
// drupal.cache.expire = 1677589324
// drupal.cache.tags = "[\"tag1\",\"tag2\"]"
// Maps the 'cid' parameter to 'drupal.cache.cid' attribute
$instrumentation->helperHook(
'get',
['cid'], // Parameter name becomes the attribute name
);
// When called with:
$cache->get('my-key');
// Creates span attribute:
// drupal.cache.cid = "my-key"
// Maps the 'cid' parameter to 'drupal.cache.key' attribute
$instrumentation->helperHook(
'get',
['cid' => 'key'], // Parameter name => custom attribute name
);
// When called with:
$cache->get('my-key');
// Creates span attribute:
// drupal.cache.key = "my-key"
$instrumentation->helperHook(
'set',
[
'cid' => 'key', // Will be prefixed: 'drupal.cache.key'
'data' => 'value', // Will be prefixed: 'drupal.cache.value'
'expire' => 'ttl', // Will be prefixed: 'drupal.cache.ttl'
'tags' => 'metadata' // Will be prefixed: 'drupal.cache.metadata'
],
);
// When called with:
$cache->set('my-key', ['foo' => 'bar'], time() + 3600, ['tag1', 'tag2']);
// Creates span attributes:
// drupal.cache.key = "my-key"
// drupal.cache.value = "{\"foo\":\"bar\"}"
// drupal.cache.ttl = 1677589324
// drupal.cache.metadata = "[\"tag1\",\"tag2\"]"
/**
* @see \Drupal\Core\Cache\CacheBackendInterface::get()
* Returns object|false The cache item or FALSE on failure.
*/
$instrumentation->helperHook(
'get',
['cid'],
'returnValue' // Capture the return value under this attribute name
);
// When called with:
$cache->get('my-key'); // Returns a cache object: { data: 'cached value', expire: 1677589324 }
// Creates span attributes:
// drupal.cache.cid = "my-key"
// drupal.cache.returnValue = "{\"data\":\"cached value\",\"expire\":1677589324}"
// When called with a missing key:
$cache->get('missing-key'); // Returns FALSE
// Creates span attributes:
// drupal.cache.cid = "missing-key"
// drupal.cache.returnValue = false
$instrumentation->helperHook(
'get',
['cid'], // Map the cache ID parameter
'returnValue',
preHandler: function($spanBuilder, $object, array $params, $class, $function, $filename, $lineno) {
// Add timestamp when cache was checked
$spanBuilder->setAttribute(
$this->getAttributeName('custom_time'),
time()
);
},
postHandler: function($span, $object, array $params, $returnValue, $exception) {
// Track if this was a cache hit
$span->setAttribute(
$this->getAttributeName('hit'),
$returnValue !== FALSE
);
}
);
// When called with:
$cache->get('my-key'); // Returns cached data
// Creates span attributes:
// drupal.cache.cid = "my-key"
// drupal.cache.custom_time = 1677589324
// drupal.cache.hit = true
// drupal.cache.returnValue = "{\"data\":\"cached value\",\"expire\":1677589324}"