Skip to content

Commit

Permalink
Merge pull request #12 from softonic/Allow-logs-for-outgoing-and-inco…
Browse files Browse the repository at this point in the history
…ming-protobuf-messages

Allowed logs for outgoing and incoming protobuf messages
  • Loading branch information
xaviapa authored Feb 29, 2024
2 parents 293264e + 9066629 commit b7fe0b5
Show file tree
Hide file tree
Showing 11 changed files with 341 additions and 49 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/php.yml → .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.0'
php-version: '8.1'
extensions: pcntl, bcmath, protobuf

- name: Install dependencies
Expand Down
6 changes: 3 additions & 3 deletions .php-cs-fixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
->setRules([
'@PSR2' => true,
'array_syntax' => ['syntax' => 'short'],
'blank_lines_before_namespace' => true,
'concat_space' => ['spacing' => 'one'],
'new_with_braces' => true,
'new_with_parentheses' => true,
'no_blank_lines_after_phpdoc' => true,
'no_empty_phpdoc' => true,
'no_empty_comment' => true,
'no_leading_import_slash' => true,
'no_trailing_comma_in_singleline_array' => true,
'no_trailing_comma_in_singleline' => true,
'no_unused_imports' => true,
'ordered_imports' => ['imports_order' => null, 'sort_algorithm' => 'alpha'],
'phpdoc_add_missing_param_annotation' => ['only_untyped' => true],
Expand All @@ -24,7 +25,6 @@
'phpdoc_to_comment' => true,
'psr_autoloading' => true,
'return_type_declaration' => ['space_before' => 'none'],
'single_blank_line_before_namespace' => true,
'single_quote' => true,
'space_after_semicolon' => true,
'ternary_operator_spaces' => true,
Expand Down
25 changes: 19 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ composer require softonic/laravel-protobuf-events
First you need to configure the [nuwber/rabbit-events package](https://github.com/nuwber/rabbitevents) to be able
to use the package.

Then You must configure ``config/protobuf-events.php`` to set the client of the library. This client allow to isolate
Then you must configure `config/protobuf-events.php` to set the client of the library. This client allows to isolate
different services, identifying the origin of the message.

#### Configuring a listener

In the RabbitEventsServiceProvider::boot register the listeners that you want using the ExternalEvents::decorateListener method.
In the `RabbitEventsServiceProvider::boot()` register the listeners that you want using the `ExternalEvents::decorateListener()` method.
```php
/**
* Register any events for your application.
Expand All @@ -50,7 +50,8 @@ In the RabbitEventsServiceProvider::boot register the listeners that you want us
}
```

The listener needs a method called handle that will receive the message and the routing key, and a method called setClient to identify the origin of the message.
The listener needs a method called `handle()` that will receive the message and the routing key,
and a method called `setClient()` to identify the origin of the message.
```php
class MyListener
{
Expand All @@ -67,7 +68,7 @@ class MyListener

#### Publishing messages

To publish a message, you need to use the ExternalEvents::publish method.
To publish a message, you need to use the `ExternalEvents::publish()` method.
```php
ExternalEvents::publish(
':service:',
Expand All @@ -80,15 +81,27 @@ ExternalEvents::publish(
#### Advanced usage

Sometimes you need to use the package in a different way than the default. For example, you can use the package to decode
a message from a string. In that case, you are able to decode the message using the ExternalEvents::decode method.
a message from a string. In that case, you are able to decode the message using the `ExternalEvents::decode()` method.

```php
$message = ExternalEvents::decode(
ProtobufExampleMessage::class,
'\n My name\n 10\n' // The message is a string with the protobuf message
'\n My name\n 10\n' // The message is a string with the protobuf message.
);
```

### Logging protobuf messages

If you want to log the outgoing protobuf messages and the incoming ones, you can configure a logger and a formatter for the message to be logged.
For that purpose you have the methods `ExternalEvents::setLogger()` and `ExternalEvents::setFormatter()`.
The logger must implement the `Psr\Log\LoggerInterface` and the formatter, the `LogMessageFormatterInterface` interface.
```php
ExternalEvents::setLogger(Log:getFacadeRoot());
ExternalEvents::setFormatter(new ProtobufLogMessageFormatter());
```
The formatter will have two methods, `formatOutgoingMessage()` and `formatIncomingMessage()`, that will be called when a message is sent or received, respectively.
Both should return a `LogMessage` object, which contains the message to log and the context.

Testing
-------

Expand Down
9 changes: 5 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,19 @@
"issues": "https://github.com/softonic/laravel-protobuf-events/issues"
},
"require": {
"php": ">=8.0",
"google/protobuf": "^3.19",
"php": ">=8.1",
"ext-protobuf": "*",
"ext-pcntl": "*",
"ext-bcmath": "*",
"ext-sockets": "*",
"nuwber/rabbitevents": "^7.0"
"google/protobuf": "^3.19",
"nuwber/rabbitevents": "^7.0",
"psr/log": "^2.0"
},
"require-dev": {
"phpunit/phpunit": "^9.0",
"mockery/mockery": "^1.0",
"friendsofphp/php-cs-fixer": "^2.4",
"friendsofphp/php-cs-fixer": "^3.50",
"squizlabs/php_codesniffer": "^3",
"rector/rector": "^0.11.20",
"orchestra/testbench": "^6.24"
Expand Down
18 changes: 10 additions & 8 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,19 @@
</testsuite>
</testsuites>

<filter>
<whitelist>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">src</directory>
</whitelist>
</filter>
</include>
<report>
<clover outputFile="./build/clover.xml"/>
<html outputDirectory="./build/coverage"/>
<text outputFile="./build/coverage.txt" />
</report>
</coverage>

<logging>
<log type="junit" target="build/report.junit.xml"/>
<log type="coverage-html" target="build/coverage" charset="UTF-8" yui="true" highlight="true"/>
<log type="coverage-text" target="build/coverage.txt"/>
<log type="coverage-clover" target="build/clover.xml"/>
<junit outputFile="./build/report.junit.xml"/>
</logging>

</phpunit>
68 changes: 66 additions & 2 deletions src/ExternalEvents.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,30 @@
use BadMethodCallException;
use Exception;
use Google\Protobuf\Internal\Message;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use ReflectionException;
use ReflectionParameter;
use Softonic\LaravelProtobufEvents\Exceptions\InvalidMessageException;

class ExternalEvents
{
public static ?LoggerInterface $logger;

public static ?LogMessageFormatterInterface $formatter;

private const CAMEL_CASE_LETTERS_DETECTION = '#(?!(?<=^)|(?<=\\\))[A-Z]#';
public static function setLogger(LoggerInterface $logger): void
{
self::$logger = $logger;
}
public static function setFormatter(LogMessageFormatterInterface $formatter): void
{
self::$formatter = $formatter;
}
public static function publish(string $service, Message $class, array $headers = []): void
{
$routingKey = str_replace(
Expand All @@ -35,13 +51,42 @@ public static function publish(string $service, Message $class, array $headers =
'headers' => $headers,
];

publish($routingKey, $message);
try {
$startTimeMs = microtime(true);

publish($routingKey, $message);

$level = LogLevel::INFO;
} catch (Exception $exception) {
$level = LogLevel::ERROR;
}

if (isset(self::$formatter)) {
$endTimeMs = microtime(true);
$executionTimeMs = ($endTimeMs - $startTimeMs) * 1000;

$logMessage = self::$formatter->formatOutgoingMessage(
$service,
$routingKey,
$message,
$executionTimeMs,
$exception ?? null
);

self::$logger->log($level, $logMessage->message, $logMessage->context);
}

if (isset($exception)) {
throw $exception;
}
}

public static function decorateListener(string $listenerClass): \Closure
{
return static function (string $event, array $message) use ($listenerClass) {
try {
$startTimeMs = microtime(true);

$listener = resolve($listenerClass);

if (!method_exists($listener, 'setClient')) {
Expand All @@ -60,12 +105,31 @@ public static function decorateListener(string $listenerClass): \Closure

$payload = ExternalEvents::decode($className, $message[0]['data']);

return $listener->handle($payload);
$response = $listener->handle($payload);

$level = LogLevel::INFO;
} catch (ReflectionException $e) {
throw new BadMethodCallException(
"$listenerClass must have a handle method with a single parameter of type object child of \Google\Protobuf\Internal\Message"
);
} catch (Exception $exception) {
$level = LogLevel::ERROR;
}

if (isset(self::$formatter)) {
$endTimeMs = microtime(true);
$executionTimeMs = ($endTimeMs - $startTimeMs) * 1000;

$logMessage = self::$formatter->formatIncomingMessage(
$event,
$message[0],
$executionTimeMs
);

self::$logger->log($level, $logMessage->message, $logMessage->context);
}

return isset($exception) ? throw $exception : $response;
};
}

Expand Down
10 changes: 10 additions & 0 deletions src/LogMessage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Softonic\LaravelProtobufEvents;

class LogMessage
{
public function __construct(public readonly string $message, public readonly array $context)
{
}
}
22 changes: 22 additions & 0 deletions src/LogMessageFormatterInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Softonic\LaravelProtobufEvents;

use Throwable;

interface LogMessageFormatterInterface
{
public function formatOutgoingMessage(
string $service,
string $routingKey,
array $message,
int $executionTimeMs,
?Throwable $exception = null
): LogMessage;

public function formatIncomingMessage(
string $routingKey,
array $message,
int $executionTimeMs
): LogMessage;
}
10 changes: 5 additions & 5 deletions src/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,14 @@
namespace Softonic\LaravelProtobufEvents;

use Illuminate\Support\ServiceProvider as LaravelServiceProvider;
use Psr\Log\NullLogger;

class ServiceProvider extends LaravelServiceProvider
{
/**
* @var string
*/
protected string $packageName = 'protobuf-events';

/**
* Bootstrap the application services.
*
*/
public function boot()
{
Expand All @@ -23,11 +20,14 @@ public function boot()
],
'config'
);

if (ExternalEvents::$logger === null) {
ExternalEvents::setLogger(new NullLogger());
}
}

/**
* Register the application services.
*
*/
public function register()
{
Expand Down
Loading

0 comments on commit b7fe0b5

Please sign in to comment.