diff --git a/composer.json b/composer.json index 800495975d302ab95be370d11665abbb9ec75150..ed045f08b53d2ae82fb9a304c1451da18585c429 100644 --- a/composer.json +++ b/composer.json @@ -20,6 +20,9 @@ "open-telemetry/api": "^1.1", "open-telemetry/sem-conv": "^1.0" }, + "require-dev": { + "drupal/otunit": "@dev" + }, "suggest": { "open-telemetry/sdk": "To perform zero-code OpenTelemetry instrumentation" } diff --git a/tests/modules/otlrs_test/otlog_test.info.yml b/tests/modules/otlrs_test/otlog_test.info.yml new file mode 100644 index 0000000000000000000000000000000000000000..ceb8aa700c743fc337b54fc44fabd31db7b2b39b --- /dev/null +++ b/tests/modules/otlrs_test/otlog_test.info.yml @@ -0,0 +1,4 @@ +name: 'otlrs test' +type: module +description: 'Support module for otlrs testing.' +package: Testing diff --git a/tests/modules/otlrs_test/otlog_test.routing.yml b/tests/modules/otlrs_test/otlog_test.routing.yml new file mode 100644 index 0000000000000000000000000000000000000000..cd9d1e2fd6be44ff65ee8571447555e9b9c3e968 --- /dev/null +++ b/tests/modules/otlrs_test/otlog_test.routing.yml @@ -0,0 +1,13 @@ +otlog_test.debug: + path: '/otlog_test/debug' + defaults: + _controller: '\Drupal\otlog_test\TestControllers::debug' + requirements: + _access: 'TRUE' + +otlog_test.exception: + path: '/otlog_test/error' + defaults: + _controller: '\Drupal\otlog_test\TestControllers::exception' + requirements: + _access: 'TRUE' diff --git a/tests/modules/otlrs_test/src/TestControllers.php b/tests/modules/otlrs_test/src/TestControllers.php new file mode 100644 index 0000000000000000000000000000000000000000..2b58f29eaa951ae7629d1b13f1846e8a5228051a --- /dev/null +++ b/tests/modules/otlrs_test/src/TestControllers.php @@ -0,0 +1,32 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\otlog_test; + +use Drupal\Core\Controller\ControllerBase; +use Symfony\Component\HttpFoundation\Response; + +/** + * Controller routines for testing otlog module. + */ +class TestControllers extends ControllerBase { + + /** + * Returns test response. + */ + public function debug() { + $this->getLogger('test controller')->debug('test {level} message', [ + 'level' => 'debug', + ]); + return new Response('ok'); + } + + /** + * Throws test exception. + */ + public function exception() { + throw new \RuntimeException('test exception'); + } + +} diff --git a/tests/src/Functional/LogIntegrationTest.php b/tests/src/Functional/LogIntegrationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6043c7907aebc8853f17c8247b2305505e517216 --- /dev/null +++ b/tests/src/Functional/LogIntegrationTest.php @@ -0,0 +1,115 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\otlog\Functional; + +use Drupal\Component\OTUnit\FileExporterTrait; +use Drupal\Component\OTUnit\ProtoHelpersTrait; +use Drupal\Component\OTUnit\SdkAutoloadingTrait; +use Drupal\otlog\Logger\OtLog; +use Drupal\Tests\BrowserTestBase; +use Opentelemetry\Proto\Logs\V1\LogRecord; +use OpenTelemetry\SemConv\TraceAttributes; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Group; + +/** + * End-to-end test for OpenTelemetry SDK autoloading and configuration. + */ +#[Group('otlog')] +#[CoversClass(OtLog::class)] +final class LogIntegrationTest extends BrowserTestBase { + + use FileExporterTrait; + use ProtoHelpersTrait; + use SdkAutoloadingTrait; + + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + + /** + * {@inheritdoc} + */ + protected static $modules = ['otlog', 'otlog_test']; + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + + $this->setupSdkAutoloading($this->getFileExporterConfigurationVariables()); + } + + /** + * Tests a controller generating a debug message. + */ + public function testDebugMessage(): void { + $this->resetFileExporterResultFiles(); + $this->drupalGet('/otlog_test/debug'); + + [$logMessage] = $this->waitForLogs(); + + // Check resource attribute. + $traceResource = $this->getLogResource($logMessage); + $sdkName = $this->getAttributeValue( + TraceAttributes::TELEMETRY_SDK_NAME, + $traceResource->getAttributes() + ); + $this->assertNotNull($sdkName); + $this->assertTrue($sdkName->hasStringValue()); + $this->assertEquals('opentelemetry', $sdkName->getStringValue()); + + // Check scope. + $scope = $this->getLogScope($logMessage); + $this->assertEquals( + 'org.drupal.otlog', + $scope->getName() + ); + + $logs = $this->getLogRecords($logMessage); + assert($logs[0] instanceof LogRecord); + + $body = $logs[0]->getBody(); + $this->assertNotNull($body); + $this->assertTrue($body->hasStringValue()); + $this->assertEquals('[test controller] [debug] test debug message', $body->getStringValue()); + + $this->assertEquals(5, $logs[0]->getSeverityNumber()); + $this->assertEquals('debug', $logs[0]->getSeverityText()); + } + + /** + * Tests controller causing an uncaught exception. + */ + public function testException(): void { + $this->resetFileExporterResultFiles(); + $this->drupalGet('/otlog_test/error'); + + [$logMessage] = $this->waitForLogs(); + + $logs = $this->getLogRecords($logMessage); + assert($logs[0] instanceof LogRecord); + + $body = $logs[0]->getBody(); + $this->assertNotNull($body); + $this->assertTrue($body->hasStringValue()); + $this->assertStringStartsWith('[php] [error] RuntimeException: test exception in Drupal\otlog_test\TestControllers->exception() (line ', $body->getStringValue()); + $this->assertStringEndsWith('/otlrs_test/src/TestControllers.php).', $body->getStringValue()); + + $this->assertEquals(17, $logs[0]->getSeverityNumber()); + $this->assertEquals('error', $logs[0]->getSeverityText()); + + $codeStacktrace = $this->getAttributeValue( + TraceAttributes::CODE_STACKTRACE, + $logs[0]->getAttributes(), + ); + $this->assertNotNull($codeStacktrace); + $this->assertTrue($codeStacktrace->hasStringValue()); + $this->assertStringContainsString('TestControllers->exception()', $codeStacktrace->getStringValue()); + } + +}