Skip to content

Instantly share code, notes, and snippets.

@assada
Last active October 5, 2018 10:26
Show Gist options
  • Select an option

  • Save assada/06da4018d45130cf2b9194ea5409b1f0 to your computer and use it in GitHub Desktop.

Select an option

Save assada/06da4018d45130cf2b9194ea5409b1f0 to your computer and use it in GitHub Desktop.
OpenTracing ProxyManager
<?php
declare(strict_types = 1);
namespace SignNow\Core\OpenTracing;
use PDFfiller\OpenTracing\Span\SpanInterface;
use PDFfiller\OpenTracing\Tag\StringTag;
use PDFfiller\OpenTracing\TracerBridgeInterface;
use ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory as Factory;
use ReflectionException;
use Zend\Code\Reflection\ClassReflection;
use Zend\Code\Reflection\MethodReflection;
/**
* Class ProxyManager
*
* @package SignNow\Core\OpenTracing
*/
class ProxyManager implements ProxyManagerInterface
{
/**
* @var Factory
*/
private $factory;
/**
* @var TracerBridgeInterface
*/
private $tracer;
/**
* @var SpanInterface[]
*/
private $spanCache = [];
/**
* @var array
*/
private $reflection = [];
/**
* @var array
*/
private $ignore;
/**
* ProxyManager constructor.
*
* @param Factory $factory
* @param TracerBridgeInterface $tracer
*/
public function __construct(Factory $factory, TracerBridgeInterface $tracer, array $ignore = [])
{
$this->factory = $factory;
$this->tracer = $tracer;
$this->ignore = $ignore;
}
/**
* @param object $object
*
* @return ClassReflection
* @throws ReflectionException
*/
private function getClassReflection($object): ClassReflection
{
$class = \get_class($object);
if (!array_key_exists($class, $this->reflection)) {
$this->reflection[$class] = new ClassReflection($object);
}
return $this->reflection[$class];
}
/**
* @param $object
*
* @return MethodReflection[]
* @throws ReflectionException
*/
private function getMethods($object): array
{
$reflect = $this->getClassReflection($object);
return $reflect->getMethods();
}
/**
* @param object $object
*
* @return string
* @throws ReflectionException
*/
private function getClassName($object): string
{
$reflect = $this->getClassReflection($object);
return $reflect->getName();
}
/**
* @param object $object
*
* @return string
* @throws ReflectionException
*/
private function getClassFile($object): string
{
$reflect = $this->getClassReflection($object);
return $reflect->getDeclaringFile()->getFileName();
}
/**
* @param object $object
* @param string $methodName
*
* @return string
*/
private function getSpanCacheName($object, string $methodName): string
{
return spl_object_hash($object) . '::' . $methodName;
}
/**
* @param object $object
* @param callable $callback
*
* @return array
* @throws ReflectionException
*/
private function getAction($object, string $stage): array
{
$methods = $this->getMethods($object);
$className = $this->getClassName($object);
$callbacks = [];
foreach ($methods as $method) {
$methodName = $method->getName();
if (\in_array($className . '::' . $methodName, $this->ignore, true)) {
continue;
}
$callbacks[$methodName] = call_user_func_array(
[$this, $stage . 'Callback'],
[$methodName, $className, $object]
);
}
return $callbacks;
}
/**
* @param string $methodName
* @param string $className
* @param object $object
*
* @return callable
*/
private function beforeCallback(string $methodName, string $className, $object): callable
{
return function () use ($methodName, $className, $object) {
$spanCacheName = $this->getSpanCacheName($object, $methodName);
$this->spanCache[$spanCacheName] = $this->tracer->start($className . '::' . $methodName)
->addTag(new StringTag('file', $this->getClassFile($object)))
->addTag(new StringTag('class', $className))
->addTag(new StringTag('method', $methodName));
};
}
/**
* @return callable
*/
private function afterCallback(string $methodName, string $className, $object): callable
{
return function () use ($methodName, $className, $object) {
$spanCacheName = $this->getSpanCacheName($object, $methodName);
if (array_key_exists($spanCacheName, $this->spanCache)) {
$this->spanCache[$spanCacheName]->finish();
}
};
}
/**
* @param object $object
*
* @return object
* @throws ReflectionException
*/
public function proxy($object)
{
return $this->factory->createProxy(
$object,
$this->getAction($object, ProxyManagerInterface::BEFORE_ACTION),
$this->getAction($object, ProxyManagerInterface::AFTER_ACTION)
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment