PHP code example of performance-x / opentelemetry-php-instrumentation-trait

1. Go to this page and download the library: Download performance-x/opentelemetry-php-instrumentation-trait library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?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}"

/**
* @see \Drupal\Core\Cache\CacheBackendInterface::get()
*/
$instrumentation->helperHook(
    'get',
    ['cid'],
    'returnValue',
    postHandler: function($span, $object, array $params, $returnValue, ?Throwable $exception) {
        if ($exception) {
            // Add minimal error context - detailed information should go to logs
            $span->setAttribute(
                $this->getAttributeName('error_context'),
                [
                    'cache_backend' => get_class($object),
                    'attempted_key' => $params[0] ?? null,
                ]
            );
            // Simple error categorization helps with metrics
            if ($exception instanceof \InvalidArgumentException) {
                $span->setAttribute($this->getAttributeName('error_type'), 'validation');
            } elseif ($exception instanceof \RuntimeException) {
                $span->setAttribute($this->getAttributeName('error_type'), 'connection');
            }
        } elseif ($returnValue === FALSE) {
            // Track cache misses for performance monitoring
            $span->setAttribute($this->getAttributeName('cache_miss'), true);
        }
    }
);

// Error cases are automatically handled:
try {
    $cache->get(null);  // Invalid argument
} catch (\InvalidArgumentException $e) {
    // Span will