Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to use multiply DD clients with DSN config #16

Merged
merged 3 commits into from
Jan 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 30 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,35 @@ return [

```
okvpn_datadog:
profiling: true
namespace: app # You app namespace for custome metric app.*, see https://docs.datadoghq.com/developers/metrics/#naming-metrics
clients:
default: 'datadog://127.0.0.1/namespase'

## More clients
i2pd_client: 'datadog://10.10.1.1:8125/app?tags=tg1,tg2'
'null': null://null
mock: mock://mock
dns: '%env(DD_CLIENT)%'
```

Where env var looks like:
```
DD_CLIENT=datadog://127.0.0.1:8125/app1?tags=tg1,tg2
```

Access to client via DIC:

```php
class FeedController extends Controller
{
// Inject via arg for Symfony 4+
#[Route(path: '/', name: 'feeds')]
public function feedsAction(DogStatsInterface $dogStats, DogStatsInterface $i2pdClient): Response
{
$dogStats->decrement('feed');

return $this->render('feed/feeds.html.twig');
}
}
```

## Custom metrics that provided by OkvpnDatadogBundle
Expand All @@ -59,15 +86,7 @@ Where `app` metrics namespace.

## Configuration

And create config `config/packages/datadog.yml` with

```
okvpn_datadog:
namespace: app
port: 8125
```

A more complex setup look like this `config.yml`:
A more complex setup look like this `config/packages/ddog.yml`:

```

Expand Down
100 changes: 98 additions & 2 deletions src/Client/DatadogDns.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,106 @@

namespace Okvpn\Bundle\DatadogBundle\Client;

class DatadogDns
final class DatadogDns
{
public static function parser(string $dsn): array
private string $originalDsn;
private string $scheme;
private string $host;
private int $port;
private string $namespace;
private array $tags = [];

public function __construct(string $dsn)
{
$this->parser($dsn);
}

public static function fromString(string $dsn): self
{
return new DatadogDns($dsn);
}

private function parser(string $dsn): void
{
$this->originalDsn = $dsn;

if (false === $dsn = parse_url($dsn)) {
throw new \InvalidArgumentException('The datadog DSN is invalid.');
}

if (!isset($dsn['scheme'])) {
throw new \InvalidArgumentException('The datadog DSN must contain a scheme.');
}

$this->scheme = $dsn['scheme'];
$this->host = $dsn['host'] ?? '127.0.0.1';
$this->port = $dsn['port'] ?? 8125;
$this->namespace = str_replace('/', '', $dsn['path'] ?? 'app');

if (isset($dsn['query'])) {
parse_str($dsn['query'], $query);
if (isset($query['tags'])) {
$this->tags = explode(',', $query['tags']);
}
}
}

/**
* @return string
*/
public function getOriginalDsn(): string
{
return $this->originalDsn;
}

/**
* @return string
*/
public function getScheme(): string
{
return $this->scheme;
}

/**
* @return string
*/
public function getHost(): string
{
return $this->host;
}

/**
* @return int
*/
public function getPort(): int
{
return $this->port;
}

/**
* @return string
*/
public function getNamespace(): string
{
return $this->namespace;
}

/**
* @return array
*/
public function getTags(): array
{
return $this->tags;
}

public function toArray(): array
{
return [
'scheme' => $this->getScheme(),
'namespace' => $this->getNamespace(),
'tags' => $this->getTags(),
'host' => $this->getHost(),
'port' => $this->getPort(),
];
}
}
22 changes: 22 additions & 0 deletions src/Client/DatadogFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,32 @@

class DatadogFactory implements DatadogFactoryInterface
{
protected static $clientFactories = [
'null' => NullDatadogClient::class,
'mock' => MockClient::class,
'datadog' => DatadogClient::class,
];

/**
* {@inheritdoc}
*/
public function createClient(array $options): DogStatsInterface
{
if (isset($options['dsn'])) {
$dsn = DatadogDns::fromString($options['dsn']);
$options = $dsn->toArray() + $options;
}

$scheme = $options['scheme'] ?? 'datadog';
if (!static::$clientFactories[$scheme]) {
throw new \InvalidArgumentException('The datadog DSN scheme "%s" does not exists. Allowed "%s"', $scheme, implode(",", static::$clientFactories));
}

return new static::$clientFactories[$scheme]($options);
}

public static function setClientFactory(string $alias, string $className): void
{
static::$clientFactories[$alias] = $className;
}
}
3 changes: 1 addition & 2 deletions src/DependencyInjection/CompilerPass/SqlLoggerPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\Reference;

class SqlLoggerPass implements CompilerPassInterface
Expand All @@ -34,7 +33,7 @@ public function process(ContainerBuilder $container): void
continue;
}
$loggerId = 'okvpn_datadog.sql_logger.' . $name;
$container->setDefinition($loggerId, class_exists(ChildDefinition::class) ? new ChildDefinition('okvpn_datadog.logger.sql') : new DefinitionDecorator('okvpn_datadog.logger.sql'));
$container->setDefinition($loggerId, new ChildDefinition('okvpn_datadog.logger.sql'));
$configuration = $container->getDefinition($configuration);
if ($configuration->hasMethodCall('setSQLLogger')) {
$chainLoggerId = 'doctrine.dbal.logger.chain.' . $name;
Expand Down
32 changes: 32 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Okvpn\Bundle\DatadogBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

Expand Down Expand Up @@ -74,6 +75,37 @@ public function getConfigTreeBuilder(): TreeBuilder
->defaultFalse()
->end();

$this->addClientsSection($rootNode);

return $treeBuilder;
}

private function addClientsSection(ArrayNodeDefinition $rootNode): void
{
$rootNode->children()
->arrayNode('clients')
->useAttributeAsKey('alias', false)
->beforeNormalization()
->always()
->then(static function ($v) {
if (is_iterable($v)) {
foreach ($v as $name => $client) {
if (is_string($client)) {
$client = ['dsn' => $client];
}
$client['alias'] = $name;
$v[$name] = $client;
}
}
return $v;
})
->end()
->arrayPrototype()
->children()
->scalarNode('alias')->isRequired()->end()
->scalarNode('dsn')->isRequired()->end()
->end()
->end()
->end();
}
}
26 changes: 26 additions & 0 deletions src/DependencyInjection/OkvpnDatadogExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@

namespace Okvpn\Bundle\DatadogBundle\DependencyInjection;

use Okvpn\Bundle\DatadogBundle\Client\DatadogFactoryInterface;
use Okvpn\Bundle\DatadogBundle\Client\DogStatsInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;

Expand All @@ -28,9 +32,22 @@ public function load(array $configs, ContainerBuilder $container): void
->replaceArgument(6, $config['dedup_keep_time']);
$container->getDefinition('okvpn_datadog.logger.artifact_storage')
->replaceArgument(0, $config['artifacts_path'] ?: $container->getParameter('kernel.logs_dir'));

$container->getDefinition('okvpn_datadog.client')
->replaceArgument(0, $config);

if (isset($config['clients'])) {
foreach ($config['clients'] as $client) {
$this->loadClient($container, $client);
}

if (isset($config['clients']['default'])) {
$container->removeDefinition('okvpn_datadog.client');
$container->setAlias('okvpn_datadog.client', 'okvpn_datadog.client.default')->setPublic(true);
$container->setAlias(DogStatsInterface::class, 'okvpn_datadog.client.default')->setPublic(true);
}
}

if (true === $config['profiling']) {
if (true === $config['doctrine']) {
$loader->load('sqllogger.yml');
Expand All @@ -42,6 +59,15 @@ public function load(array $configs, ContainerBuilder $container): void
$container->setParameter('okvpn_datadog.profiling', $config['profiling']);
}

protected function loadClient(ContainerBuilder $container, array $client)
{
$ddDef = new Definition(DogStatsInterface::class, [$client]);
$ddDef->setFactory([new Reference(DatadogFactoryInterface::class), 'createClient']);

$container->setDefinition($id = sprintf('okvpn_datadog.client.%s', $client['alias']), $ddDef);
$container->registerAliasForArgument($id, DogStatsInterface::class, $client['alias']);
}

protected function defaultHandlerExceptions(array $config): array
{
$config = $config['handle_exceptions'] ?? [];
Expand Down
8 changes: 7 additions & 1 deletion src/Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@ services:
- null
- null

Okvpn\Bundle\DatadogBundle\Client\DatadogFactory: ~

Okvpn\Bundle\DatadogBundle\Client\DatadogFactoryInterface:
alias: Okvpn\Bundle\DatadogBundle\Client\DatadogFactory

okvpn_datadog.client:
class: Okvpn\Bundle\DatadogBundle\Client\DatadogClient
arguments: [~]
factory: ['@Okvpn\Bundle\DatadogBundle\Client\DatadogFactoryInterface', 'createClient']
arguments: [[]]
public: true

Okvpn\Bundle\DatadogBundle\Client\DogStatsInterface:
Expand Down