From 75e312a2f212aabc670448329a4b402249f5faf3 Mon Sep 17 00:00:00 2001 From: Luke Kuzmish Date: Sun, 19 Oct 2025 07:57:39 -0400 Subject: [PATCH] wip --- config/statsd-adapter.php | 4 ++ src/AdapterManager.php | 11 ++++- src/StatsDAdapterServiceProvider.php | 15 +++++++ tests/StatsDAdapterServiceProviderTest.php | 50 ++++++++++++++++++++++ 4 files changed, 79 insertions(+), 1 deletion(-) diff --git a/config/statsd-adapter.php b/config/statsd-adapter.php index 32dd385..2cceb5f 100644 --- a/config/statsd-adapter.php +++ b/config/statsd-adapter.php @@ -29,6 +29,10 @@ 'throwConnectionExceptions' => true, ], "datadog" => [ + /** + * By setting batch_size to a positive integer, the batched dogstatsd provider will be used. + */ + 'batch_size' => null, // see configuration options: https://docs.datadoghq.com/developers/dogstatsd/?code-lang=php&tab=hostagent#client-instantiation-parameters "adapter" => "datadog", "host" => env("DD_AGENT_HOST"), diff --git a/src/AdapterManager.php b/src/AdapterManager.php index f8a7b1b..1981ba1 100644 --- a/src/AdapterManager.php +++ b/src/AdapterManager.php @@ -10,6 +10,7 @@ use Cosmastech\StatsDClientAdapter\Adapters\League\LeagueStatsDClientAdapter; use Cosmastech\StatsDClientAdapter\Adapters\StatsDClientAdapter; use Cosmastech\StatsDClientAdapter\Clients\Datadog\DatadogLoggingClient; +use DataDog\BatchedDogStatsd; use DataDog\DogStatsd; use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Support\MultipleInstanceManager; @@ -158,8 +159,16 @@ protected function createLogDatadogAdapter(array $config): DatadogStatsDClientAd */ protected function createDatadogAdapter(array $config): DatadogStatsDClientAdapter { + $batchSize = (int) ($config['batch_size'] ?? null); + if ($batchSize > 0) { + $client = new BatchedDogStatsd($config); + BatchedDogStatsd::$maxBufferLength = $batchSize; + } else { + $client = new DogStatsd($config); + } + return new DatadogStatsDClientAdapter( - new DogStatsd($config), + $client, $this->getDefaultTags(), clock: $this->getClockImplementation() ); diff --git a/src/StatsDAdapterServiceProvider.php b/src/StatsDAdapterServiceProvider.php index 76c65da..b70ab40 100644 --- a/src/StatsDAdapterServiceProvider.php +++ b/src/StatsDAdapterServiceProvider.php @@ -4,6 +4,8 @@ use Cosmastech\StatsDClientAdapter\Adapters\InMemory\Models\InMemoryStatsRecord; use Cosmastech\StatsDClientAdapter\Adapters\StatsDClientAdapter; +use DataDog\BatchedDogStatsd; +use Illuminate\Container\Container; use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Support\DeferrableProvider; use Illuminate\Support\ServiceProvider; @@ -13,6 +15,19 @@ class StatsDAdapterServiceProvider extends ServiceProvider implements Deferrable public function boot(): void { $this->offerPublishing(); + $this->app->terminating(static function () { + $adapterInstance = Container::getInstance() + ->make(AdapterManager::class) + ->instance() + ->getClient(); + + if ( + BatchedDogStatsd::getBufferLength() > 0 + && $adapterInstance instanceof BatchedDogStatsd + ) { + $adapterInstance->flushBuffer(); + } + }); } public function register(): void diff --git a/tests/StatsDAdapterServiceProviderTest.php b/tests/StatsDAdapterServiceProviderTest.php index c826fe6..4de30b1 100644 --- a/tests/StatsDAdapterServiceProviderTest.php +++ b/tests/StatsDAdapterServiceProviderTest.php @@ -7,11 +7,28 @@ use Cosmastech\StatsDClientAdapter\Adapters\InMemory\Models\InMemoryStatsRecord; use Cosmastech\StatsDClientAdapter\Adapters\StatsDClientAdapter; use Cosmastech\StatsDClientAdapter\Clients\Datadog\DatadogLoggingClient; +use DataDog\BatchedDogStatsd; use Illuminate\Support\Facades\Config; use PHPUnit\Framework\Attributes\Test; class StatsDAdapterServiceProviderTest extends AbstractTestCase { + private int $initialBufferSize; + + #[\Override] + protected function setUp(): void + { + parent::setUp(); + $this->initialBufferSize = BatchedDogStatsd::$maxBufferLength; + } + + #[\Override] + protected function tearDown(): void + { + BatchedDogStatsd::$maxBufferLength = $this->initialBufferSize; + parent::tearDown(); + } + #[Test] public function makeStatsDClientAdapter_returnsDefaultInstance(): void { @@ -73,4 +90,37 @@ public function inMemoryStatsRecord_isSingleton(): void // Then self::assertSame($firstRecord, $secondRecord); } + + #[Test] + public function datadogConfigHasBatchSize_resolve_setsBufferSize(): void + { + // Given + Config::set('statsd-adapter.channels.datadog.batch_size', 2); + Config::set('statsd-adapter.default', 'datadog'); + + // When + $clientAdapter = $this->app->make(StatsDClientAdapter::class); + + // Then + self::assertInstanceOf(BatchedDogStatsd::class, $clientAdapter->getClient()); + self::assertEquals(2, BatchedDogStatsd::$maxBufferLength); + } + + #[Test] + public function batchedDogStats_terminatingApp_submitsStats(): void + { + // Given + Config::set('statsd-adapter.channels.datadog.batch_size', 2); + Config::set('statsd-adapter.default', 'datadog'); + + // And + $clientAdapter = $this->app->make(StatsDClientAdapter::class); + $clientAdapter->increment('testing'); + + // When + $this->app->terminate(); + + // Then + + } }