Файловый менеджер - Редактировать - /var/www/html/mediawiki-1.43.1/tests/phpunit/unit/includes/libs/Stats/MetricTest.php
Ðазад
<?php namespace Wikimedia\Tests\Stats; use PHPUnit\Framework\TestCase; use Psr\Log\NullLogger; use Wikimedia\Stats\IBufferingStatsdDataFactory; use Wikimedia\Stats\Metrics\BaseMetric; use Wikimedia\Stats\Metrics\CounterMetric; use Wikimedia\Stats\Metrics\NullMetric; use Wikimedia\Stats\OutputFormats; use Wikimedia\Stats\StatsCache; use Wikimedia\Stats\StatsFactory; use Wikimedia\TestingAccessWrapper; /** * @covers \Wikimedia\Stats\Metrics\NullMetric * @covers \Wikimedia\Stats\Metrics\CounterMetric * @covers \Wikimedia\Stats\Metrics\GaugeMetric * @covers \Wikimedia\Stats\Metrics\TimingMetric * @covers \Wikimedia\Stats\StatsUtils */ class MetricTest extends TestCase { public const FORMATS = [ 'statsd', 'dogstatsd' ]; public const TYPES = [ 'counter', 'gauge', 'timing' ]; public const TESTS = [ 'basic' => [ 'config' => [ 'name' => 'test.unit', 'component' => 'testComponent', ], 'value' => 2, 'labels' => [], ], 'invalidLabel' => [ 'config' => [ 'name' => 'test.unit', 'component' => 'testComponent', ], 'value' => 2, 'labels' => [ ': x' => 'labelOne' ], ], 'oneLabel' => [ 'config' => [ 'name' => 'test.unit', 'component' => 'testComponent', ], 'value' => 2, 'labels' => [ 'x' => 'labelOne' ], ], 'multiLabel' => [ 'config' => [ 'name' => 'test.unit', 'component' => 'testComponent', ], 'value' => 2, 'labels' => [ 'x' => 'labelOne', 'y' => 'labelTwo' ], ], 'noComponent' => [ 'config' => [ 'name' => 'test.unit', 'component' => null, ], 'value' => 2, 'labels' => [], ] ]; public const RESULTS = [ 'statsd.counter.basic' => [ 'mediawiki.testComponent.test_unit:2|c' ], 'statsd.counter.invalidLabel' => [ 'mediawiki.testComponent.test_unit.labelOne:2|c' ], 'statsd.counter.oneLabel' => [ 'mediawiki.testComponent.test_unit.labelOne:2|c' ], 'statsd.counter.multiLabel' => [ 'mediawiki.testComponent.test_unit.labelOne.labelTwo:2|c' ], 'statsd.counter.noComponent' => [ 'mediawiki.test_unit:2|c' ], 'statsd.gauge.basic' => [ 'mediawiki.testComponent.test_unit:2|g' ], 'statsd.gauge.invalidLabel' => [ 'mediawiki.testComponent.test_unit.labelOne:2|g' ], 'statsd.gauge.oneLabel' => [ 'mediawiki.testComponent.test_unit.labelOne:2|g' ], 'statsd.gauge.multiLabel' => [ 'mediawiki.testComponent.test_unit.labelOne.labelTwo:2|g' ], 'statsd.gauge.noComponent' => [ 'mediawiki.test_unit:2|g' ], 'statsd.timing.basic' => [ 'mediawiki.testComponent.test_unit:2|ms' ], 'statsd.timing.invalidLabel' => [ 'mediawiki.testComponent.test_unit.labelOne:2|ms' ], 'statsd.timing.oneLabel' => [ 'mediawiki.testComponent.test_unit.labelOne:2|ms' ], 'statsd.timing.multiLabel' => [ 'mediawiki.testComponent.test_unit.labelOne.labelTwo:2|ms' ], 'statsd.timing.noComponent' => [ 'mediawiki.test_unit:2|ms' ], 'dogstatsd.counter.basic' => [ 'mediawiki.testComponent.test_unit:2|c' ], 'dogstatsd.counter.invalidLabel' => [ 'mediawiki.testComponent.test_unit:2|c|#x:labelOne' ], 'dogstatsd.counter.oneLabel' => [ 'mediawiki.testComponent.test_unit:2|c|#x:labelOne' ], 'dogstatsd.counter.multiLabel' => [ 'mediawiki.testComponent.test_unit:2|c|#x:labelOne,y:labelTwo' ], 'dogstatsd.counter.noComponent' => [ 'mediawiki.test_unit:2|c' ], 'dogstatsd.gauge.basic' => [ 'mediawiki.testComponent.test_unit:2|g' ], 'dogstatsd.gauge.invalidLabel' => [ 'mediawiki.testComponent.test_unit:2|g|#x:labelOne' ], 'dogstatsd.gauge.oneLabel' => [ 'mediawiki.testComponent.test_unit:2|g|#x:labelOne' ], 'dogstatsd.gauge.multiLabel' => [ 'mediawiki.testComponent.test_unit:2|g|#x:labelOne,y:labelTwo' ], 'dogstatsd.gauge.noComponent' => [ 'mediawiki.test_unit:2|g' ], 'dogstatsd.timing.basic' => [ 'mediawiki.testComponent.test_unit:2|ms' ], 'dogstatsd.timing.invalidLabel' => [ 'mediawiki.testComponent.test_unit:2|ms|#x:labelOne' ], 'dogstatsd.timing.oneLabel' => [ 'mediawiki.testComponent.test_unit:2|ms|#x:labelOne' ], 'dogstatsd.timing.multiLabel' => [ 'mediawiki.testComponent.test_unit:2|ms|#x:labelOne,y:labelTwo' ], 'dogstatsd.timing.noComponent' => [ 'mediawiki.test_unit:2|ms' ], ]; /** @var StatsCache */ private $cache; public function handleTest( $test, $type, $format ) { $config = self::TESTS[$test]; $name = implode( '.', [ $format, $type, $test ] ); $this->setName( $name ); $this->cache->clear(); $formatter = OutputFormats::getNewFormatter( OutputFormats::getFormatFromString( $format ) ); $emitter = OutputFormats::getNewEmitter( 'mediawiki', $this->cache, $formatter ); $statsFactory = new StatsFactory( $this->cache, $emitter, new NullLogger ); if ( $config['config']['component'] !== null ) { $statsFactory = $statsFactory->withComponent( $config['config']['component'] ); } switch ( $type ) { case 'counter': $metric = $statsFactory->getCounter( $config['config']['name'] ); $metric->setLabels( $config['labels'] ); $metric->incrementBy( $config['value'] ); break; case 'gauge': $metric = $statsFactory->getGauge( $config['config']['name'] ); $metric->setLabels( $config['labels'] ); $metric->set( $config['value'] ); break; case 'timing': $metric = $statsFactory->getTiming( $config['config']['name'] ); $metric->setLabels( $config['labels'] ); $metric->observe( $config['value'] ); break; case 'default': break; } $this->assertEquals( self::RESULTS[$name], TestingAccessWrapper::newFromObject( $emitter )->render() ); } public function handleType( $type, $format ) { foreach ( self::TESTS as $test => $_ ) { $this->handleTest( $test, $type, $format ); } } public function handleFormat( $format ) { $this->cache = new StatsCache(); foreach ( self::TYPES as $type ) { $this->handleType( $type, $format ); } } public function testMetrics() { foreach ( self::FORMATS as $format ) { $this->handleFormat( $format ); } } public function testSampledMetrics() { $rounds = 10; $m = StatsFactory::newNull(); $ten_percent_metrics = $m->getCounter( 'test.sampled.ten' )->setSampleRate( 0.1 ); $m = StatsFactory::newNull(); $all_metrics = $m->getCounter( 'test.sampled.hundred' )->setSampleRate( 1.0 ); $m = StatsFactory::newNull(); $zero_metrics = $m->getCounter( 'test.sampled.zero' )->setSampleRate( 0.0 ); for ( $i = 0; $i < $rounds; $i++ ) { $ten_percent_metrics->increment(); $all_metrics->increment(); $zero_metrics->increment(); } $this->assertLessThan( $rounds, count( $ten_percent_metrics->getSamples() ) ); // random $this->assertCount( $rounds, $all_metrics->getSamples() ); $this->assertCount( 0, $zero_metrics->getSamples() ); # getSampleCount() should count all samples regardless of sample rate $this->assertEquals( 10, $ten_percent_metrics->getSampleCount() ); $this->assertEquals( 10, $all_metrics->getSampleCount() ); $this->assertEquals( 10, $zero_metrics->getSampleCount() ); } public function testTimerNotStarted() { $m = StatsFactory::newNull(); $this->expectPHPWarning( 'Stats: stop() called before start() for metric \'test\'', static function () use ( $m ) { $m->getTiming( 'test' )->stop(); } ); } public function testChangingLabelsToUsedMetric() { $m = StatsFactory::newNull(); $m->getCounter( 'testMetricCounter' )->setLabel( 'labelOne', 'a' )->increment(); $counter = @$m->getCounter( 'testMetricCounter' )->setLabel( 'labelTwo', 'b' ); $this->assertInstanceOf( NullMetric::class, $counter ); $m->getGauge( 'testMetricGauge' )->setLabel( 'labelOne', 'a' )->set( 1 ); $gauge = @$m->getGauge( 'testMetricGauge' )->setLabel( 'labelTwo', 'b' ); $this->assertInstanceOf( NullMetric::class, $gauge ); $m->getTiming( 'testMetricTiming' )->setLabel( 'labelOne', 'a' )->observe( 1 ); $timer = @$m->getTiming( 'testMetricTiming' )->setLabel( 'labelTwo', 'b' ); $this->assertInstanceOf( NullMetric::class, $timer ); } public function testCounterHandleNotAllLabelsHaveValues() { $m = StatsFactory::newNull(); $m->getCounter( 'testMetricCounter' )->setLabel( 'labelOne', 'a' )->increment(); $this->expectPHPWarning( 'Stats: Cannot associate label keys with label values: Not all initialized labels have an assigned value.', static function () use ( $m ) { $m->getCounter( 'testMetricCounter' )->increment(); } ); } public function testGaugeHandleNotAllLabelsHaveValues() { $m = StatsFactory::newNull(); $m->getGauge( 'testMetricGauge' )->setLabel( 'labelOne', 'a' )->set( 1 ); $this->expectPHPWarning( 'Stats: Cannot associate label keys with label values: Not all initialized labels have an assigned value.', static function () use ( $m ) { $m->getGauge( 'testMetricGauge' )->set( 1 ); } ); } public function testTimingHandleNotAllLabelsHaveValues() { $m = StatsFactory::newNull(); $m->getTiming( 'testMetricTiming' )->setLabel( 'labelOne', 'a' )->observe( 1 ); $this->expectPHPWarning( 'Stats: Cannot associate label keys with label values: Not all initialized labels have an assigned value.', static function () use ( $m ) { $m->getTiming( 'testMetricTiming' )->observe( 1 ); } ); } public function testSampleRateOOB() { $m = StatsFactory::newNull(); $metric = @$m->getCounter( 'testMetricCounter' )->setSampleRate( 1.1 ); $this->assertInstanceOf( NullMetric::class, $metric ); $metric = @$m->getGauge( 'testMetricGauge' )->setSampleRate( -1 ); $this->assertInstanceOf( NullMetric::class, $metric ); $metric = @$m->getTiming( 'testMetricTimer' )->setSampleRate( 20 ); $this->assertInstanceOf( NullMetric::class, $metric ); } public function testSampleRateDisallowed() { $m = StatsFactory::newNull(); $m->getCounter( 'testMetric' )->increment(); $metric = @$m->getCounter( 'testMetric' )->setSampleRate( 0.5 ); $this->assertInstanceOf( NullMetric::class, $metric ); $m->getGauge( 'testMetricGauge' )->set( 1 ); $metric = @$m->getGauge( 'testMetricGauge' )->setSampleRate( 0.5 ); $this->assertInstanceOf( NullMetric::class, $metric ); $m->getTiming( 'testMetricTiming' )->observe( 1 ); $metric = @$m->getTiming( 'testMetricTiming' )->setSampleRate( 0.5 ); $this->assertInstanceOf( NullMetric::class, $metric ); } public function testCopyToStatsdAtEmptyArrayResetsValue() { $baseMetric = new BaseMetric( '', 'testMetric' ); $metric = new CounterMetric( $baseMetric->withStatsdDataFactory( $this->createMock( IBufferingStatsdDataFactory::class ) ), new NullLogger ); $metric->copyToStatsdAt( 'test' ); $this->assertEquals( [ 'test' ], $baseMetric->getStatsdNamespaces() ); $metric->copyToStatsdAt( [] ); $this->assertEquals( [], $baseMetric->getStatsdNamespaces() ); } public function testStatsdDataFactoryCopyToStatsdAtWithGauge() { $statsFactory = StatsFactory::newNull(); $gaugeArgs = [ 'test.gauge.1', 'test.gauge.2' ]; $statsdMock = $this->createMock( IBufferingStatsdDataFactory::class ); $statsdMock->expects( $this->exactly( 2 ) ) ->method( 'gauge' ) ->with( $this->callback( static function ( $key ) use ( &$gaugeArgs ) { $nextKey = array_shift( $gaugeArgs ); return $nextKey === $key; } ) ); $statsFactory = $statsFactory->withStatsdDataFactory( $statsdMock ); $statsFactory->getGauge( 'testMetricGauge' ) ->copyToStatsdAt( [ 'test.gauge.1', 'test.gauge.2' ] ) ->set( 1 ); } public function testHandleInvalidStatsdNamespace() { $m = StatsFactory::newNull(); $m = $m->withStatsdDataFactory( $this->createMock( IBufferingStatsdDataFactory::class ) ); $this->expectPHPWarning( 'Stats: StatsD namespace must be a string.', function () use ( $m ) { $metric = $m->getCounter( 'testMetricCounter' )->copyToStatsdAt( null ); $this->assertInstanceOf( NullMetric::class, $metric ); } ); } public function testHandleEmptyStatsdNamespace() { $m = StatsFactory::newNull(); $m = $m->withStatsdDataFactory( $this->createMock( IBufferingStatsdDataFactory::class ) ); $this->expectPHPWarning( 'Stats: StatsD namespace cannot be empty.', function () use ( $m ) { $metric = $m->getCounter( 'testMetricCounter' )->copyToStatsdAt( '' ); $this->assertInstanceOf( NullMetric::class, $metric ); } ); } public function testHandleNonStringStatsdNamespaceInArray() { $m = StatsFactory::newNull(); $m = $m->withStatsdDataFactory( $this->createMock( IBufferingStatsdDataFactory::class ) ); $this->expectPHPWarning( 'Stats: StatsD namespace must be a string.', function () use ( $m ) { $metric = $m->getCounter( 'testMetricCounter' )->copyToStatsdAt( [ null ] ); $this->assertInstanceOf( NullMetric::class, $metric ); } ); } public function testCanChangeLabelsWhileTimerIsStarted() { $cache = new StatsCache; $formatter = OutputFormats::getNewFormatter( OutputFormats::getFormatFromString( 'dogstatsd' ) ); $emitter = OutputFormats::getNewEmitter( 'mediawiki', $cache, $formatter ); $statsFactory = new StatsFactory( $cache, $emitter, new NullLogger ); $timer = $statsFactory->getTiming( 'test', )->setLabel( 'foo', 'bar' ); // start() and stop() called so close together here should be fractions of a millisecond $timer->start(); $timer->setLabel( 'foo', 'baz' )->stop(); $this->assertMatchesRegularExpression( '/^mediawiki\.test:(0\.[0-9]+)\|ms\|#foo:baz$/', TestingAccessWrapper::newFromObject( $emitter )->render()[0] ); } public function testStatsdDataFactoryPersistsWithComponent() { $statsFactory = StatsFactory::newNull(); $timingArgs = [ 'test.timing.1', 'test.timing.2' ]; $statsdMock = $this->createMock( IBufferingStatsdDataFactory::class ); $statsdMock->expects( $this->exactly( 2 ) ) ->method( 'timing' ) ->with( $this->callback( static function ( $key ) use ( &$timingArgs ) { $nextKey = array_shift( $timingArgs ); return $nextKey === $key; }, 1.0 ) ); $statsFactory = $statsFactory->withStatsdDataFactory( $statsdMock ); // withComponent() returns a whole new StatsFactory instance $componentStatsFactory = $statsFactory->withComponent( 'TestComponent' ); $componentStatsFactory->getTiming( 'testMetricTiming' ) ->copyToStatsdAt( [ 'test.timing.1', 'test.timing.2' ] ) ->observe( 1 ); } public function testWithComponentStatsdFactoryChanges() { $statsFactory = StatsFactory::newNull(); // statsdDataFactory should be null if withComponent called prior to calling withStatsdDataFactory() $noStatsd = TestingAccessWrapper::newFromObject( $statsFactory->withComponent( 'foo' ) ); $this->assertNull( $noStatsd->statsdDataFactory ); // call withStatsdDataFactory $statsFactory = $statsFactory->withStatsdDataFactory( $this->createMock( IBufferingStatsdDataFactory::class ) ); // statsdDataFactory should be an instance of IBufferingStatsdDataFactory $yesStatsd = TestingAccessWrapper::newFromObject( $statsFactory->withComponent( 'foo' ) ); $this->assertInstanceOf( IBufferingStatsdDataFactory::class, $yesStatsd->statsdDataFactory ); // disable statsdDataFactory $statsFactory = $statsFactory->withStatsdDataFactory( null ); // statsdDataFactory should be null again $noStatsdAgain = TestingAccessWrapper::newFromObject( $statsFactory->withComponent( 'foo' ) ); $this->assertNull( $noStatsdAgain->statsdDataFactory ); } /** * PHPUnit 10 compatible replacement for expectWarning(). * * @param string $msg * @param callable $callback * @return void */ private function expectPHPWarning( string $msg, callable $callback ): void { try { $errorEmitted = false; set_error_handler( function ( $_, $actualMsg ) use ( $msg, &$errorEmitted ) { $this->assertStringContainsString( $msg, $actualMsg ); $errorEmitted = true; }, E_USER_WARNING ); $callback(); $this->assertTrue( $errorEmitted, "No PHP warning was emitted." ); } finally { restore_error_handler(); } } public function testMsConversion() { $statsFactory = StatsFactory::newNull(); $statsFactory->getTiming( 'test_seconds' )->observeSeconds( 1 ); $statsFactory->getTiming( 'test_seconds' )->observeNanoseconds( 1000000 ); $samples = $statsFactory->getTiming( 'test_seconds' )->getSamples(); $this->assertEquals( [ 1000, 1 ], array_map( static function ( $sample ) { return $sample->getValue(); }, $samples ) ); } }
| ver. 1.1 | |
.
| PHP 8.4.18 | Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñтраницы: 0 |
proxy
|
phpinfo
|
ÐаÑтройка