Skip to content

Commit

Permalink
Add default tags functionality (#3)
Browse files Browse the repository at this point in the history
* passes tags to all instances; cleans up PHPDoc

* update facade docblock
  • Loading branch information
cosmastech authored Jul 8, 2024
1 parent bee4e17 commit 0ef91c8
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 14 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
},
"require": {
"php": "^8.2",
"cosmastech/statsd-client-adapter": "^0.0.2",
"cosmastech/statsd-client-adapter": "^0.1.1",
"illuminate/support": "^10.0|^11.0",
"illuminate/contracts": "^10.0|^11.0"
},
Expand Down
5 changes: 5 additions & 0 deletions config/statsd-adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
return [
'default' => env("STATSD_ADAPTER_DEFAULT", "memory"),

/**
* These are tags which should be added to every outgoing stat.
*/
"default_tags" => [],

/**
* You may name your channel anything you wish. Valid drivers are:
* memory
Expand Down
60 changes: 54 additions & 6 deletions src/AdapterManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@
use Cosmastech\StatsDClientAdapter\Adapters\Datadog\DatadogStatsDClientAdapter;
use Cosmastech\StatsDClientAdapter\Adapters\InMemory\InMemoryClientAdapter;
use Cosmastech\StatsDClientAdapter\Adapters\League\LeagueStatsDClientAdapter;
use Cosmastech\StatsDClientAdapter\Adapters\StatsDClientAdapter;
use Cosmastech\StatsDClientAdapter\Clients\Datadog\DatadogLoggingClient;
use Cosmastech\StatsDClientAdapter\Utility\SampleRateDecider\SampleRateSendDecider;
use DataDog\DogStatsd;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Support\MultipleInstanceManager;
use League\StatsD\Client;
use League\StatsD\Exception\ConfigurationException;

/**
* @property array<int, StatsDClientAdapter> $instances
* @method StatsDClientAdapter instance($name = null)
*
* @mixin \Cosmastech\StatsDClientAdapter\Adapters\StatsDClientAdapter
*/
class AdapterManager extends MultipleInstanceManager
Expand All @@ -30,6 +35,11 @@ class AdapterManager extends MultipleInstanceManager
*/
protected $config;

/**
* @var array<mixed, mixed>
*/
protected array $defaultTags;

/**
* @inheritDoc
*/
Expand Down Expand Up @@ -64,6 +74,35 @@ public function getInstanceConfig($name)
return $this->config->get("statsd-adapter.channels.{$name}");
}

/**
* @param array<mixed, mixed> $tags
* @return void
*/
public function setDefaultTags(array $tags): void
{
$this->defaultTags = $tags;

foreach ($this->instances as $instance) {
$instance->setDefaultTags($this->defaultTags);
}
}

/**
* @return array<mixed, mixed>
*/
public function getDefaultTags(): array
{
return $this->defaultTags ?? $this->getDefaultTagsFromConfig();
}

/**
* @return array<mixed, mixed>
*/
protected function getDefaultTagsFromConfig(): array
{
return $this->config->get('statsd-adapter.default_tags', []);
}

/**
* @param array<string, mixed> $config
* @return InMemoryClientAdapter
Expand All @@ -72,12 +111,14 @@ protected function createMemoryAdapter(array $config): InMemoryClientAdapter
{
$wrapperClock = new WrapperClock(FactoryImmutable::getDefaultInstance());

return new InMemoryClientAdapter($wrapperClock);
return new InMemoryClientAdapter($wrapperClock, $this->getDefaultTags());
}

/**
* @param array<string, mixed> $config
* @return DatadogStatsDClientAdapter
*
* @throws BindingResolutionException
*/
protected function createLog_datadogAdapter(array $config): DatadogStatsDClientAdapter
{
Expand All @@ -87,14 +128,16 @@ protected function createLog_datadogAdapter(array $config): DatadogStatsDClientA
/**
* @param array<string, mixed> $config
* @return DatadogStatsDClientAdapter
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*
* @throws BindingResolutionException
*/
protected function createLogDatadogAdapter(array $config): DatadogStatsDClientAdapter
{
$logLevel = $config['log_level'] ?? 'debug';

return new DatadogStatsDClientAdapter(
new DatadogLoggingClient($this->app->make('log'), $logLevel, $config)
new DatadogLoggingClient($this->app->make('log'), $logLevel, $config),
$this->getDefaultTags()
);
}

Expand All @@ -104,19 +147,24 @@ protected function createLogDatadogAdapter(array $config): DatadogStatsDClientAd
*/
protected function createDatadogAdapter(array $config): DatadogStatsDClientAdapter
{
return new DatadogStatsDClientAdapter(new DogStatsd($config));
return new DatadogStatsDClientAdapter(new DogStatsd($config), $this->getDefaultTags());
}

/**
* @param array<string, mixed> $config
* @param array<string, mixed> $config
* @return LeagueStatsDClientAdapter
*
* @throws ConfigurationException
*/
protected function createLeagueAdapter(array $config): LeagueStatsDClientAdapter
{
$leagueClient = new Client($config['instance_id'] ?? null);
$leagueClient->configure($config);

return new LeagueStatsDClientAdapter($leagueClient, new SampleRateSendDecider());
return new LeagueStatsDClientAdapter(
$leagueClient,
new SampleRateSendDecider(),
$this->getDefaultTags()
);
}
}
2 changes: 2 additions & 0 deletions src/Stats.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
* @method static void getDefaultInstance()
* @method static void setDefaultInstance(string $name)
* @method static array|null getInstanceConfig(string $name)
* @method static void setDefaultTags(array $tags)
* @method static array getDefaultTags()
* @method static mixed instance(string|null $name = null)
* @method static \Cosmastech\LaravelStatsDAdapter\AdapterManager forgetInstance(array|string|null $name = null)
* @method static void purge(string|null $name = null)
Expand Down
9 changes: 5 additions & 4 deletions src/StatsDAdapterServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,22 @@
namespace Cosmastech\LaravelStatsDAdapter;

use Cosmastech\StatsDClientAdapter\Adapters\StatsDClientAdapter;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;

class StatsDAdapterServiceProvider extends ServiceProvider implements DeferrableProvider
{
public function register()
public function register(): void
{
$this->app->singleton(
AdapterManager::class,
fn ($app) => new AdapterManager($app)
fn (Application $app) => new AdapterManager($app),
);

$this->app->singleton(
$this->app->bind(
StatsDClientAdapter::class,
fn ($app) => $app->make(AdapterManager::class)->instance()
fn (Application $app) => $app->make(AdapterManager::class)->instance()
);
}

Expand Down
61 changes: 58 additions & 3 deletions tests/AdapterManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public function setDefaultInstance_overridesConfigDefault(): void
}

#[Test]
public function memoryAdapter_instance_returnsInMemoryClientAdapter(): void
public function instance_memoryAdapter_returnsInMemoryClientAdapter(): void
{
// Given
$adapterManager = $this->createAdapterManager();
Expand All @@ -59,7 +59,7 @@ public function memoryAdapter_instance_returnsInMemoryClientAdapter(): void
}

#[Test]
public function logDatadog_instance_returnsConfiguredDatadogClient(): void
public function instance_logDatadog_returnsConfiguredDatadogClient(): void
{
// Given
$adapterManager = $this->createAdapterManager();
Expand All @@ -74,7 +74,7 @@ public function logDatadog_instance_returnsConfiguredDatadogClient(): void
self::assertInstanceOf(DatadogLoggingClient::class, $datadogClientAdapter->getClient());
}

public function league_instance_returnsConfiguredLeagueStatsDClient(): void
public function instance_league_returnsConfiguredLeagueStatsDClient(): void
{
// Given
$adapterManager = $this->createAdapterManager();
Expand All @@ -89,4 +89,59 @@ public function league_instance_returnsConfiguredLeagueStatsDClient(): void
self::assertInstanceOf(LeagueStatsDClientAdapter::class, $leagueStatsDClientAdapter);
self::assertInstanceOf(StatsDClient::class, $leagueStatsDClientAdapter->getClient());
}

#[Test]
public function getDefaultTags_withNoDefaultTagsSet_returnsEmptyArray(): void
{
// Given
$adapterManager = $this->createAdapterManager();

// Then
self::assertEquals([], $adapterManager->getDefaultTags());
}

#[Test]
public function getDefaultTags_withDefaultTagsSet_returnsDefaultTagsArray(): void
{
// Given
$adapterManager = $this->createAdapterManager();

// When
$adapterManager->setDefaultTags(['abc' => true]);

// Then
self::assertSame(["abc" => true], $adapterManager->getDefaultTags());
}

#[Test]
public function setDefaultTags_passesTagsToExistingInstance(): void
{
// Given
$adapterManager = $this->createAdapterManager();

/** @var InMemoryClientAdapter $inMemoryClientAdapter */
$inMemoryClientAdapter = $adapterManager->instance("memory");

// When
$adapterManager->setDefaultTags(["abc" => "hello"]);

// Then
self::assertSame(["abc" => "hello"], $inMemoryClientAdapter->getDefaultTags());
}

#[Test]
public function setDefaultTags_passesToNewInstance(): void
{
// Given
$adapterManager = $this->createAdapterManager();

// And an instance is created
$adapterManager->instance("log_datadog");

// When
$adapterManager->setDefaultTags(["abc" => "123"]);

// Then
self::assertEquals(["abc" => "123"], $adapterManager->instance("memory")->getDefaultTags());
}
}
18 changes: 18 additions & 0 deletions tests/StatsDAdapterServiceProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,22 @@ public function makeStatsDClientAdapter_returnsSingleton(): void
// And
self::assertSame($clientAdapter, $this->app->make(StatsDClientAdapter::class));
}

#[Test]
public function passesDefaultTagsToAdapterManager(): void
{
// Given
$defaultTags = [
"my_first_tag" => 1,
"my_second_tag" => 2,
"my_third_tag" => 3.0,
];
Config::set("statsd-adapter.default_tags", $defaultTags);

// When
$clientAdapter = $this->app->make(StatsDClientAdapter::class);

// Then
self::assertEqualsCanonicalizing($defaultTags, $clientAdapter->getDefaultTags());
}
}

0 comments on commit 0ef91c8

Please sign in to comment.