diff --git a/README.md b/README.md index 665e537..47627f0 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ moesif: options: max_queue_size: 50 max_batch_size: 25 - + hooks_class: 'App\Configuration\MyMoesifHooks' ``` Your Moesif Application Id can be found in the [_Moesif Portal_](https://www.moesif.com/). @@ -64,23 +64,29 @@ If set, will override the default max queue size before data is sent over to Moe Type: Int If set, will override the default max batch size that is sent over to Moesif. The default is `10`. -## Subscriber Configuration Options +#### __`hooks_class`__ -Certain functionalities can be overridden and customized within the plugin. To override these functions, within your projects `/src/EventSubscriber` directory, you must add a `CustomMoesifSubscriber.php` file. +Type: String +Optional, if set, this should be your implementation of the `Moesif\MoesifBundle\Interfaces\MoesifHooksInterface`. + +## User Hook class Options + +Certain functionalities can be overridden and customized within the plugin with hooks. -In your `services.yaml` file you will also need to add the following: -``` yaml -services: - # Existing services config - ... +Within the `MyMoesifHooks.php` file, you will need to override the following methods: - App\EventSubscriber\CustomMoesifSubscriber: - class: App\EventSubscriber\CustomMoesifSubscriber # Ensure this matches the namespace and class name of your custom subscriber - tags: - - { name: moesif.event_subscriber } +```php +use Moesif\MoesifBundle\Interfaces\MoesifHooksInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +class MyMoesifHooks implements MoesifHooksInterface { + // your implementation of every method below. +} ``` -Within the `CustomMoesifSubscriber.php` file, you will need to override the following methods: + +The method you should implement is: ### __`identifyUserId`__ @@ -129,67 +135,73 @@ Optional, a function that takes a $request and $response and returns $metdata wh Type: `($request, $response) => String` Optional, a function that takes a $request and $response and returns true if this API call should be not be sent to Moesif. -Here is an example of what the `CustomMoesifSubscriber.php` file may look like: +Here is an example of what the `MyMoesifHooks.php` file may look like: ``` php headers->get('X-Company-Id'); + } + + public function identifySessionToken(Request $request, Response $response): string|null + { + return null; + } + + public function getMetadata(Request $request, Response $response): ?array + { + return null; + } + + public function skip(Request $request, Response $response): bool + { + return false; + } + + public function maskRequestHeaders(array $headers): array + { + return $headers; + } + + public function maskResponseHeaders(array $headers): array + { + return $headers; + } + + public function maskRequestBody($body) + { + // this can be a string or array object. + // because prior to php 8, can not declare union type (such as string|array) + return $body; + } + + public function maskResponseBody($body) + { + // this can be a string or array object. + // because prior to php 8, can not declare union type (such as string|array) + return $body; + } } + ``` ## Update a Single User diff --git a/src/Consumer/SendCurlTaskConsumer.php b/src/Consumer/SendCurlTaskConsumer.php index 2dd08b8..bdcf269 100644 --- a/src/Consumer/SendCurlTaskConsumer.php +++ b/src/Consumer/SendCurlTaskConsumer.php @@ -67,7 +67,7 @@ public function persist(array $batch): bool { public function updateUser(array $userData): bool { $data = json_encode($userData); $url = $this->protocol . '://' . $this->host . $this->usersEndpoint; - + return $this->fork ? $this->_executeForked($url, $data) : $this->_executeCurl($url, $data); } @@ -107,10 +107,6 @@ public function updateSubscriptionsBatch(array $subscriptionsBatchData): bool { } protected function _executeCurl(string $url, string $data): bool { - - if ($this->debug) { - // $this->logger->error('Moesif cURL data: ' . $data); - } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); @@ -126,13 +122,13 @@ protected function _executeCurl(string $url, string $data): bool { $curlCommand = 'curl -X POST -H "Content-Type: application/json" -H "X-Moesif-Application-Id: ' . $this->appId . '" -d \'' . addslashes($data) . '\' \'' . $url . '\''; if ($this->debug) { - $this->logger->info('Moesif cURL command: ' . $curlCommand); + $this->logger->debug('Moesif cURL command: ' . $curlCommand); } $result = curl_exec($ch); if ($this->debug) { - $this->logger->error('Moesif cURL result: ' . $result); + $this->logger->debug('Moesif cURL result: ' . $result); } if (curl_errno($ch)) { diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index a7652c2..cba58a2 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -21,6 +21,9 @@ public function getConfigTreeBuilder(): TreeBuilder ->booleanNode('debug') ->defaultFalse() ->end() + ->scalarNode('hooks_class') + ->defaultValue('Moesif\MoesifBundle\Interfaces\MoesifDefaultHooks') + ->end() ->arrayNode('options') ->addDefaultsIfNotSet() ->children() diff --git a/src/DependencyInjection/MoesifExtension.php b/src/DependencyInjection/MoesifExtension.php index 9a810e4..c9a19ad 100644 --- a/src/DependencyInjection/MoesifExtension.php +++ b/src/DependencyInjection/MoesifExtension.php @@ -7,6 +7,8 @@ use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Symfony\Component\Config\Definition\Processor; +use Symfony\Component\DependencyInjection\Loader; +use Symfony\Component\DependencyInjection\Definition; class MoesifExtension extends Extension { @@ -33,6 +35,12 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter('moesif.moesif_application_id', $config['moesif_application_id']); } + if ($config['hooks_class']) { + $userMoesifConfigClass = $config['hooks_class']; + $definition = new Definition($userMoesifConfigClass); + $container->setDefinition('moesif.user_hooks', $definition); + } + if (isset($config['debug'])) { $container->setParameter('moesif.debug', $config['debug']); } diff --git a/src/EventSubscriber/MoesifSubscriber.php b/src/EventSubscriber/MoesifSubscriber.php index e16d1e3..419ef88 100644 --- a/src/EventSubscriber/MoesifSubscriber.php +++ b/src/EventSubscriber/MoesifSubscriber.php @@ -11,14 +11,22 @@ use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Moesif\MoesifBundle\Service\MoesifApiService; -use Moesif\MoesifBundle\Interfaces\EventSubscriberInterface as MoesifEventSubscriberInterface; +use Moesif\MoesifBundle\Interfaces\MoesifHooksInterface; -class MoesifSubscriber implements SymfonyEventSubscriberInterface, MoesifEventSubscriberInterface +use Psr\Log\LoggerInterface; + +class MoesifSubscriber implements SymfonyEventSubscriberInterface { private MoesifApiService $moesifApiService; + private LoggerInterface $logger; + private $options; + + private $configHooks; - public function __construct(MoesifApiService $moesifApiService) + public function __construct(MoesifApiService $moesifApiService, MoesifHooksInterface $configHooks, LoggerInterface $logger = null) { + $this->configHooks = $configHooks; + $this->logger = $logger; $this->moesifApiService = $moesifApiService; } @@ -32,7 +40,11 @@ public static function getSubscribedEvents(): array public function onKernelRequest(RequestEvent $event): void { - // Optional: Perform actions before the request is handled, such as initializing logging or tracking + $startTime = new DateTime(); + $startTime->setTimezone(new DateTimeZone("UTC")); + + $request = $event->getRequest(); + $request->attributes->set('mo_start_time', $startTime); } public function onKernelResponse(ResponseEvent $event): void @@ -48,9 +60,8 @@ public function onKernelResponse(ResponseEvent $event): void private function prepareData(Request $request, Response $response): array { - $startTime = new DateTime(); - $startTime->setTimezone(new DateTimeZone("UTC")); - + $startTime = $request->attributes->get('mo_start_time'); + $endTime = new DateTime(); $endTime->setTimezone(new DateTimeZone("UTC")); @@ -78,7 +89,6 @@ private function prepareData(Request $request, Response $response): array 'user_id' => $this->identifyUserId($request, $response), 'company_id' => $this->identifyCompanyId($request, $response), 'session_token' => $this->identifySessionToken($request, $response), - 'company_id' => $this->identifyCompanyId($request, $response), 'metadata' => $this->getMetadata($request, $response), ]; @@ -101,46 +111,74 @@ private function getIp(Request $request): ?string public function identifyUserId(Request $request, Response $response): ?string { + + if ($this->configHooks) { + return $this->configHooks->identifyUserId($request, $response); + } return null; } public function identifyCompanyId(Request $request, Response $response): ?string { + if ($this->configHooks) { + return $this->configHooks->identifyCompanyId($request, $response); + } return null; } public function identifySessionToken(Request $request, Response $response): ?string { + if ($this->configHooks) { + return $this->configHooks->identifySessionToken($request, $response); + } return null; } public function getMetadata(Request $request, Response $response): ?array { + if ($this->configHooks) { + return $this->configHooks->getMetadata($request, $response); + } return null; } public function skip(Request $request, Response $response): bool { + if ($this->configHooks) { + return $this->configHooks->skip($request, $response); + } return false; } public function maskRequestHeaders(array $headers): array { + if ($this->configHooks) { + return $this->configHooks->maskRequestHeaders($headers); + } return $headers; } public function maskResponseHeaders(array $headers): array { + if ($this->configHooks) { + return $this->configHooks->maskResponseHeaders($headers); + } return $headers; } - public function maskRequestBody(string $body): ?string + public function maskRequestBody($body) { + if ($this->configHooks) { + return $this->configHooks->maskRequestBody($body); + } return $body; } - public function maskResponseBody(string $body): ?string + public function maskResponseBody($body) { + if ($this->configHooks) { + return $this->configHooks->maskResponseBody($body); + } return $body; } } diff --git a/src/Interfaces/MoesifDefaultHooks.php b/src/Interfaces/MoesifDefaultHooks.php new file mode 100644 index 0000000..b669a8d --- /dev/null +++ b/src/Interfaces/MoesifDefaultHooks.php @@ -0,0 +1,59 @@ +