Initial Commit

This commit is contained in:
David Stone
2024-11-30 18:24:12 -07:00
commit e8f7955c1c
5432 changed files with 1397750 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
<?php
namespace WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Events;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Entities\DNSRecordCollection;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Entities\DNSRecordType;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Entities\Hostname;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Resolvers\Interfaces\Resolver;
final class DNSQueried extends ObservableEventAbstract
{
public const NAME = 'dns.queried';
private Resolver $resolver;
private Hostname $hostname;
private DNSRecordType $recordType;
private DNSRecordCollection $recordCollection;
public function __construct(Resolver $resolver, Hostname $hostname, DNSRecordType $recordType, DNSRecordCollection $recordCollection = null)
{
parent::__construct();
$this->resolver = $resolver;
$this->hostname = $hostname;
$this->recordType = $recordType;
$this->recordCollection = $recordCollection ?? new DNSRecordCollection();
}
public function getResolver() : Resolver
{
return $this->resolver;
}
public function getHostname() : Hostname
{
return $this->hostname;
}
public function getRecordType() : DNSRecordType
{
return $this->recordType;
}
public function getRecordCollection() : DNSRecordCollection
{
return $this->recordCollection;
}
public static function getName() : string
{
return self::NAME;
}
public function toArray() : array
{
return ['resolver' => $this->resolver->getName(), 'hostname' => (string) $this->hostname, 'type' => (string) $this->recordType, 'records' => $this->formatCollection($this->recordCollection), 'empty' => $this->recordCollection->isEmpty()];
}
private function formatCollection(DNSRecordCollection $recordCollection) : array
{
$formatted = [];
foreach ($recordCollection as $record) {
if ($record) {
$formatted[] = $record->toArray();
}
}
return $formatted;
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Events;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Entities\DNSRecordType;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Entities\Hostname;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Exceptions\Exception;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Resolvers\Interfaces\Resolver;
final class DNSQueryFailed extends ObservableEventAbstract
{
public const NAME = 'dns.query.failed';
private Resolver $resolver;
private Hostname $hostname;
private DNSRecordType $recordType;
private Exception $error;
public function __construct(Resolver $resolver, Hostname $hostname, DNSRecordType $recordType, Exception $error)
{
parent::__construct();
$this->resolver = $resolver;
$this->hostname = $hostname;
$this->recordType = $recordType;
$this->error = $error;
}
public function getResolver() : Resolver
{
return $this->resolver;
}
public function getHostName() : Hostname
{
return $this->hostname;
}
public function getRecordType() : DNSRecordType
{
return $this->recordType;
}
public function getError() : Exception
{
return $this->error;
}
public static function getName() : string
{
return self::NAME;
}
public function toArray() : array
{
return ['resolver' => $this->resolver->getName(), 'hostname' => (string) $this->hostname, 'type' => (string) $this->recordType, 'error' => $this->error];
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Events;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Performance\Interfaces\ProfileInterface;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Performance\Profile;
final class DNSQueryProfiled extends ObservableEventAbstract
{
public const NAME = 'dns.query.profiled';
private ProfileInterface $profile;
public function __construct(ProfileInterface $profile)
{
parent::__construct();
$this->profile = $profile;
}
public function getProfile() : ProfileInterface
{
return $this->profile;
}
public static function getName() : string
{
return self::NAME;
}
public function toArray() : array
{
return ['elapsedSeconds' => $this->profile->getElapsedSeconds(), 'transactionName' => $this->profile->getTransactionName(), 'peakMemoryUsage' => $this->profile->getPeakMemoryUsage()];
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Events;
use JsonSerializable;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Entities\Interfaces\Arrayable;
use WP_Ultimo\Dependencies\Symfony\Component\EventDispatcher\GenericEvent;
abstract class ObservableEventAbstract extends GenericEvent implements JsonSerializable, Arrayable
{
public static abstract function getName() : string;
public function jsonSerialize() : array
{
return [$this::getName() => $this->toArray()];
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Interfaces;
use WP_Ultimo\Dependencies\Symfony\Component\EventDispatcher\EventSubscriberInterface;
interface Observable
{
public function addSubscriber(EventSubscriberInterface $subscriber) : void;
public function addListener(string $eventName, callable $listener, int $priority = 0) : void;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Performance\Interfaces;
interface ProfileInterface
{
public function startTransaction() : void;
public function endTransaction() : void;
public function getTransactionName() : string;
public function getElapsedSeconds() : float;
public function samplePeakMemoryUsage() : void;
public function getPeakMemoryUsage() : int;
}

View File

@@ -0,0 +1,10 @@
<?php
namespace WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Performance\Interfaces;
use DateTimeInterface;
interface Time
{
public function getMicrotime() : float;
public function now() : DateTimeInterface;
}

View File

@@ -0,0 +1,44 @@
<?php
namespace WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Performance;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Performance\Interfaces\ProfileInterface;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Performance\Interfaces\Time;
use function memory_get_peak_usage;
final class Profile implements ProfileInterface
{
private string $transactionName;
private float $startTime = 0.0;
private float $stopTime = 0.0;
private int $peakMemoryUsage = 0;
private Time $time;
public function __construct(string $transactionName, Time $time = null)
{
$this->transactionName = $transactionName;
$this->time = $time ?? new Timer();
}
public function startTransaction() : void
{
$this->startTime = $this->time->getMicroTime();
}
public function endTransaction() : void
{
$this->stopTime = $this->time->getMicroTime();
}
public function getTransactionName() : string
{
return $this->transactionName;
}
public function getElapsedSeconds() : float
{
return $this->stopTime - $this->startTime;
}
public function samplePeakMemoryUsage() : void
{
$this->peakMemoryUsage = memory_get_peak_usage();
}
public function getPeakMemoryUsage() : int
{
return $this->peakMemoryUsage;
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Performance;
class ProfileFactory
{
public function create(string $transactionName) : Profile
{
return new Profile($transactionName);
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Performance;
use DateTimeImmutable;
use DateTimeInterface;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Performance\Interfaces\Time;
use function microtime;
final class Timer implements Time
{
public function getMicroTime() : float
{
return microtime(\true);
}
public function now() : DateTimeInterface
{
return new DateTimeImmutable('now');
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Subscribers;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Events\DNSQueried;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Events\DNSQueryFailed;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Events\DNSQueryProfiled;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Events\ObservableEventAbstract;
use SplFileObject;
use WP_Ultimo\Dependencies\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use function json_encode;
final class STDIOSubscriber implements EventSubscriberInterface
{
private SplFileObject $STDOUT;
private SplFileObject $STDERR;
public function __construct(SplFileObject $stdOut, SplFileObject $stdErr)
{
$this->STDOUT = $stdOut;
$this->STDERR = $stdErr;
}
public static function getSubscribedEvents()
{
return [DNSQueryFailed::getName() => 'onDNSQueryFailed', DNSQueried::getName() => 'onDNSQueried', DNSQueryProfiled::getName() => 'onDNSQueryProfiled'];
}
public function onDNSQueryFailed(ObservableEventAbstract $event) : void
{
$this->STDERR->fwrite(json_encode($event, \JSON_PRETTY_PRINT) . \PHP_EOL);
}
public function onDNSQueried(ObservableEventAbstract $event) : void
{
$this->STDOUT->fwrite(json_encode($event, \JSON_PRETTY_PRINT) . \PHP_EOL);
}
public function onDNSQueryProfiled(ObservableEventAbstract $event) : void
{
$this->STDOUT->fwrite(json_encode($event, \JSON_PRETTY_PRINT) . \PHP_EOL);
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Traits;
use LogicException;
use ReflectionClass;
use ReflectionMethod;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Events\ObservableEventAbstract;
use WP_Ultimo\Dependencies\Symfony\Component\EventDispatcher\EventDispatcher;
use WP_Ultimo\Dependencies\Symfony\Component\EventDispatcher\EventDispatcherInterface;
use WP_Ultimo\Dependencies\Symfony\Component\EventDispatcher\EventSubscriberInterface;
use function call_user_func_array;
trait Dispatcher
{
private ?EventDispatcherInterface $dispatcher = null;
public function setDispatcher(EventDispatcherInterface $dispatcher) : void
{
$this->dispatcher = $dispatcher;
}
public function addSubscriber(EventSubscriberInterface $subscriber) : void
{
$this->getDispatcher()->addSubscriber($subscriber);
}
public function addListener(string $eventName, callable $listener, int $priority = 0) : void
{
$this->getDispatcher()->addListener($eventName, $listener, $priority);
}
public function dispatch(ObservableEventAbstract $event) : void
{
call_user_func_array([$this->getDispatcher(), 'dispatch'], $this->getOrderedDispatcherArguments($event));
}
private function getOrderedDispatcherArguments(ObservableEventAbstract $event) : array
{
$reflection = new ReflectionClass($this->getDispatcher());
foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
if ($method->getName() !== 'dispatch') {
continue;
}
// handle the reverse argument BC from symfony dispatcher 3.* to 4.*
foreach ($method->getParameters() as $parameter) {
return $parameter->getName() === 'event' ? [$event, $event::getName()] : [$event::getName(), $event];
}
}
throw new LogicException('Could not determine argument order for dispatcher');
}
private function getDispatcher() : EventDispatcherInterface
{
if ($this->dispatcher === null) {
$this->dispatcher = new EventDispatcher();
}
return $this->dispatcher;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Traits;
use WP_Ultimo\Dependencies\Psr\Log\LoggerInterface;
use WP_Ultimo\Dependencies\Psr\Log\NullLogger;
trait Logger
{
private ?LoggerInterface $logger = null;
public function setLogger(LoggerInterface $logger) : void
{
$this->logger = $logger;
}
protected function getLogger() : LoggerInterface
{
if ($this->logger === null) {
$this->logger = new NullLogger();
}
return $this->logger;
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Traits;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Performance\Profile;
use WP_Ultimo\Dependencies\RemotelyLiving\PHPDNS\Observability\Performance\ProfileFactory;
trait Profileable
{
private ?ProfileFactory $profileFactory = null;
public function createProfile(string $transactionName) : Profile
{
return $this->getProfileFactory()->create($transactionName);
}
public function setProfileFactory(ProfileFactory $profileFactory) : void
{
$this->profileFactory = $profileFactory;
}
private function getProfileFactory() : ProfileFactory
{
if ($this->profileFactory === null) {
$this->profileFactory = new ProfileFactory();
}
return $this->profileFactory;
}
}