Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
RobinHoutevelts committed Jul 2, 2024
0 parents commit 827d16f
Show file tree
Hide file tree
Showing 20 changed files with 883 additions and 0 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Test

on:
workflow_dispatch:
pull_request_target:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
php-version: [ '8.2', '8.3', '8.4' ]
composer-flag: [ '', '--prefer-lowest' ]
steps:
- uses: actions/checkout@v4

- name: Setup PHP with PECL extension
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}

- name: Install dependencies
run: composer update ${{ matrix.composer-flag }}

- name: Run tests
run: composer test
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/.phpunit.cache
/vendor
.env
.phpunit.result.cache
/.fleet
/.idea
/.vscode
composer.lock
68 changes: 68 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# AWS X-Ray integration for Saloon

This package provides a Saloon Sender that sends traces to AWS X-Ray.
It creates a separate trace for each request and sends the trace to AWS X-Ray when the request is finished.

## Installation

```bash
composer require wieni/saloon-aws-xray
```

## Configuration

### Laravel

When using Laravel, this package plays nicely with [napp/xray-laravel](https://github.com/Napp/xray-laravel).
Please read the documentation of that package to configure AWS X-Ray for Laravel.

You can then create a ServiceProvider to configure Saloon to use the AWS X-Ray sender.

```php
// app/Providers/SaloonXrayServiceProvider.php
<?php declare(strict_types=1);

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Napp\Xray\Submission\DaemonSegmentSubmitter;
use Napp\Xray\Xray;
use Saloon\Config as SaloonConfig;
use Saloon\HttpSender\HttpSender;
use Wieni\SaloonAwsXray\XrayHttpSender;

final class SaloonXrayServiceProvider extends ServiceProvider
{
public function register(): void
{
// Configure the XrayHttpSender
$this->app->bind(
XrayHttpSender::class,
function (): XrayHttpSender {
$submitterClass = config('xray.submitter', DaemonSegmentSubmitter::class);
$senderClass = config('saloon.default_sender', HttpSender::class);

return new XrayHttpSender(
new $senderClass(),
$this->app[Xray::class]->tracer(),
new $submitterClass(),
);
},
);

// Configure Saloon to use the XrayHttpSender
SaloonConfig::setSenderResolver(fn() => $this->app[XrayHttpSender::class]);
}
}
```

And register the ServiceProvider in your `config/app.php`:

```diff
// config/app.php
'providers' => [
// ...
+ App\Providers\SaloonXrayServiceProvider::class,
// ...
],
```
32 changes: 32 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "wieni/saloon-aws-xray",
"description": "AWS X-Ray integration for Saloon",
"license": "MIT",
"type": "library",
"authors": [
{
"name": "Robin Houtevelts",
"email": "robin@wieni.be"
}
],
"require": {
"pkerrigan/xray": "^1.3",
"saloonphp/saloon": "^3"
},
"require-dev": {
"phpunit/phpunit": "^11"
},
"autoload": {
"psr-4": {
"Wieni\\SaloonAwsXray\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Wieni\\SaloonAwsXray\\Test\\": "tests/"
}
},
"scripts": {
"test": "vendor/bin/phpunit --testdox"
}
}
17 changes: 17 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" bootstrap="vendor/autoload.php"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.2/phpunit.xsd" cacheDirectory=".phpunit.cache">
<testsuite name="saloon-aws-xray">
<directory suffix="Test.php">tests</directory>
</testsuite>
<php>
<ini name="error_reporting" value="E_ALL"/>
<ini name="display_errors" value="On"/>
<ini name="display_startup_errors" value="On"/>
</php>
<source>
<include>
<directory suffix=".php">src</directory>
</include>
</source>
</phpunit>
44 changes: 44 additions & 0 deletions src/DataProvider/RequestMetadataProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

namespace Wieni\SaloonAwsXray\DataProvider;

use Pkerrigan\Xray\HttpSegment;
use Pkerrigan\Xray\Segment;
use Saloon\Http\PendingRequest;

/**
* This data provider is always being applied.
*
* Adds metadata to the Xray segment with information about the http request.
*
* @see \Wieni\SaloonAwsXray\XrayHttpSender::createHttpSegment()
*/
class RequestMetadataProvider
{

public function addXrayMetadata(Segment $segment, PendingRequest $pendingRequest): array
{
$metaData = [
'query_string' => $pendingRequest->query()->all(),
'headers' => $pendingRequest->headers()->all(),
'body' => $pendingRequest->body()?->all(),
];

$segmentName = $pendingRequest->getMethod()->name . ' ' . $pendingRequest->getUrl();
$segment->setName($segmentName);

if ($segment instanceof HttpSegment) {
$segment->setUrl($pendingRequest->getUrl());
$segment->setMethod($pendingRequest->getMethod()->name);
}

$segment->addMetadata('request', $metaData);

$segment->addAnnotation('Host', $pendingRequest->getUri()->getHost());

return $metaData;
}

}
34 changes: 34 additions & 0 deletions src/DataProvider/ResponseBodyMetadataProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Wieni\SaloonAwsXray\DataProvider;

use Pkerrigan\Xray\Segment;
use Saloon\Http\Response;
use Wieni\SaloonAwsXray\XrayDataProviderInterface;

class ResponseBodyMetadataProvider implements XrayDataProviderInterface
{

public function addXrayMetadata(Segment $segment, Response $response): void
{
// Re-use the ResponseMetadataProvider because we will overwrite
// the 'response' metadata attribute of the segment
$metaData = (new ResponseMetadataProvider())->addXrayMetadata(
$segment,
$response
);

$responseBody = $response->body();
if (str_contains($response->header('Content-Type') ?? '', 'json')) {
$responseBody = $response->array();
}

// Add the response body to the metadata and overwrite the response
// metadata on the segment
$metaData['body'] = $responseBody;
$segment->addMetadata('response', $metaData);
}

}
37 changes: 37 additions & 0 deletions src/DataProvider/ResponseMetadataProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Wieni\SaloonAwsXray\DataProvider;

use Pkerrigan\Xray\HttpSegment;
use Pkerrigan\Xray\Segment;
use Saloon\Http\Response;

/**
* This data provider is always being applied.
*
* Adds metadata to the Xray segment with information about the http response.
*
* @see \Wieni\SaloonAwsXray\XrayHttpSender::finalise()
*/
class ResponseMetadataProvider
{

public function addXrayMetadata(Segment $segment, Response $response): array
{
$metaData = [
'status' => $response->status(),
'headers' => $response->headers()->all(),
];

if ($segment instanceof HttpSegment) {
$segment->setResponseCode($response->status());
}

$segment->addMetadata('response', $metaData);

return $metaData;
}

}
28 changes: 28 additions & 0 deletions src/DataProvider/SaloonMetadataProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Wieni\SaloonAwsXray\DataProvider;

use Pkerrigan\Xray\Segment;
use Saloon\Http\PendingRequest;

/**
* This data provider is always being applied.
*
* Adds metadata to the Xray segment with information about the Saloon request.
*
* @see \Wieni\SaloonAwsXray\XrayHttpSender::createTrace()
*/
class SaloonMetadataProvider
{

public function addXrayMetadata(Segment $segment, PendingRequest $pendingRequest): void
{
$requestClass = get_class($pendingRequest->getRequest());

$segment->addAnnotation('framework', 'Saloon');
$segment->addAnnotation('SaloonRequest', $requestClass);
}

}
15 changes: 15 additions & 0 deletions src/HasXrayDataProvidersInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Wieni\SaloonAwsXray;

use Saloon\Http\Response;

interface HasXrayDataProvidersInterface
{

/** @return XrayDataProviderInterface[] */
public function getXrayDataProviders(Response $response): array;

}
19 changes: 19 additions & 0 deletions src/HasXrayDataProvidersTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Wieni\SaloonAwsXray;

use Saloon\Http\Response;

trait HasXrayDataProvidersTrait
{

public function getXrayDataProviders(Response $response): array
{
return [
new DataProvider\ResponseBodyMetadataProvider(),
];
}

}
15 changes: 15 additions & 0 deletions src/XrayDataProviderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Wieni\SaloonAwsXray;

use Pkerrigan\Xray\Segment;
use Saloon\Http\Response;

interface XrayDataProviderInterface
{

public function addXrayMetadata(Segment $segment, Response $response): void;

}
Loading

0 comments on commit 827d16f

Please sign in to comment.