MediaWiki REL1_31
TransactionProfilerTest.php
Go to the documentation of this file.
1<?php
2
4use Psr\Log\LoggerInterface;
5
9class TransactionProfilerTest extends PHPUnit\Framework\TestCase {
10
11 use MediaWikiCoversValidator;
12
13 public function testAffected() {
14 $logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
15 $logger->expects( $this->exactly( 3 ) )->method( 'warning' );
16
17 $tp = new TransactionProfiler();
18 $tp->setLogger( $logger );
19 $tp->setExpectation( 'maxAffected', 100, __METHOD__ );
20
21 $tp->transactionWritingIn( 'srv1', 'db1', '123' );
22 $tp->recordQueryCompletion( "SQL 1", microtime( true ) - 3, true, 200 );
23 $tp->recordQueryCompletion( "SQL 2", microtime( true ) - 3, true, 200 );
24 $tp->transactionWritingOut( 'srv1', 'db1', '123', 1, 400 );
25 }
26
27 public function testReadTime() {
28 $logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
29 // 1 per query
30 $logger->expects( $this->exactly( 2 ) )->method( 'warning' );
31
32 $tp = new TransactionProfiler();
33 $tp->setLogger( $logger );
34 $tp->setExpectation( 'readQueryTime', 5, __METHOD__ );
35
36 $tp->transactionWritingIn( 'srv1', 'db1', '123' );
37 $tp->recordQueryCompletion( "SQL 1", microtime( true ) - 10, false, 1 );
38 $tp->recordQueryCompletion( "SQL 2", microtime( true ) - 10, false, 1 );
39 $tp->transactionWritingOut( 'srv1', 'db1', '123', 0, 0 );
40 }
41
42 public function testWriteTime() {
43 $logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
44 // 1 per query, 1 per trx, and one "sub-optimal trx" entry
45 $logger->expects( $this->exactly( 4 ) )->method( 'warning' );
46
47 $tp = new TransactionProfiler();
48 $tp->setLogger( $logger );
49 $tp->setExpectation( 'writeQueryTime', 5, __METHOD__ );
50
51 $tp->transactionWritingIn( 'srv1', 'db1', '123' );
52 $tp->recordQueryCompletion( "SQL 1", microtime( true ) - 10, true, 1 );
53 $tp->recordQueryCompletion( "SQL 2", microtime( true ) - 10, true, 1 );
54 $tp->transactionWritingOut( 'srv1', 'db1', '123', 20, 1 );
55 }
56
57 public function testAffectedTrx() {
58 $logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
59 $logger->expects( $this->exactly( 1 ) )->method( 'warning' );
60
61 $tp = new TransactionProfiler();
62 $tp->setLogger( $logger );
63 $tp->setExpectation( 'maxAffected', 100, __METHOD__ );
64
65 $tp->transactionWritingIn( 'srv1', 'db1', '123' );
66 $tp->transactionWritingOut( 'srv1', 'db1', '123', 1, 200 );
67 }
68
69 public function testWriteTimeTrx() {
70 $logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
71 // 1 per trx, and one "sub-optimal trx" entry
72 $logger->expects( $this->exactly( 2 ) )->method( 'warning' );
73
74 $tp = new TransactionProfiler();
75 $tp->setLogger( $logger );
76 $tp->setExpectation( 'writeQueryTime', 5, __METHOD__ );
77
78 $tp->transactionWritingIn( 'srv1', 'db1', '123' );
79 $tp->transactionWritingOut( 'srv1', 'db1', '123', 10, 1 );
80 }
81
82 public function testConns() {
83 $logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
84 $logger->expects( $this->exactly( 2 ) )->method( 'warning' );
85
86 $tp = new TransactionProfiler();
87 $tp->setLogger( $logger );
88 $tp->setExpectation( 'conns', 2, __METHOD__ );
89
90 $tp->recordConnection( 'srv1', 'db1', false );
91 $tp->recordConnection( 'srv1', 'db2', false );
92 $tp->recordConnection( 'srv1', 'db3', false ); // warn
93 $tp->recordConnection( 'srv1', 'db4', false ); // warn
94 }
95
96 public function testMasterConns() {
97 $logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
98 $logger->expects( $this->exactly( 2 ) )->method( 'warning' );
99
100 $tp = new TransactionProfiler();
101 $tp->setLogger( $logger );
102 $tp->setExpectation( 'masterConns', 2, __METHOD__ );
103
104 $tp->recordConnection( 'srv1', 'db1', false );
105 $tp->recordConnection( 'srv1', 'db2', false );
106
107 $tp->recordConnection( 'srv1', 'db1', true );
108 $tp->recordConnection( 'srv1', 'db2', true );
109 $tp->recordConnection( 'srv1', 'db3', true ); // warn
110 $tp->recordConnection( 'srv1', 'db4', true ); // warn
111 }
112
113 public function testReadQueryCount() {
114 $logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
115 $logger->expects( $this->exactly( 2 ) )->method( 'warning' );
116
117 $tp = new TransactionProfiler();
118 $tp->setLogger( $logger );
119 $tp->setExpectation( 'queries', 2, __METHOD__ );
120
121 $tp->recordQueryCompletion( "SQL 1", microtime( true ) - 0.01, false, 0 );
122 $tp->recordQueryCompletion( "SQL 2", microtime( true ) - 0.01, false, 0 );
123 $tp->recordQueryCompletion( "SQL 3", microtime( true ) - 0.01, false, 0 ); // warn
124 $tp->recordQueryCompletion( "SQL 4", microtime( true ) - 0.01, false, 0 ); // warn
125 }
126
127 public function testWriteQueryCount() {
128 $logger = $this->getMockBuilder( LoggerInterface::class )->getMock();
129 $logger->expects( $this->exactly( 2 ) )->method( 'warning' );
130
131 $tp = new TransactionProfiler();
132 $tp->setLogger( $logger );
133 $tp->setExpectation( 'writes', 2, __METHOD__ );
134
135 $tp->recordQueryCompletion( "SQL 1", microtime( true ) - 0.01, false, 0 );
136 $tp->recordQueryCompletion( "SQL 2", microtime( true ) - 0.01, false, 0 );
137 $tp->recordQueryCompletion( "SQL 3", microtime( true ) - 0.01, false, 0 );
138 $tp->recordQueryCompletion( "SQL 4", microtime( true ) - 0.01, false, 0 );
139
140 $tp->transactionWritingIn( 'srv1', 'db1', '123' );
141 $tp->recordQueryCompletion( "SQL 1w", microtime( true ) - 0.01, true, 2 );
142 $tp->recordQueryCompletion( "SQL 2w", microtime( true ) - 0.01, true, 5 );
143 $tp->recordQueryCompletion( "SQL 3w", microtime( true ) - 0.01, true, 3 );
144 $tp->recordQueryCompletion( "SQL 4w", microtime( true ) - 0.01, true, 1 );
145 $tp->transactionWritingOut( 'srv1', 'db1', '123', 1, 1 );
146 }
147}
\Wikimedia\Rdbms\TransactionProfiler
Helper class that detects high-contention DB queries via profiling calls.