Aaron Schulz has uploaded a new change for review.
https://gerrit.wikimedia.org/r/56628
Change subject: Avoid sending multiple UDP packets for the same key in
wfIncrStats().
......................................................................
Avoid sending multiple UDP packets for the same key in wfIncrStats().
* This should help reduce collector data loss.
Change-Id: Ibe55648422d1b8aac86dd6fa83973d3c8715b0aa
(cherry picked from commit 5f1e95436eac69fb7d02a538ac20b4215391e2b6)
---
M includes/AutoLoader.php
M includes/GlobalFunctions.php
A includes/StatCounter.php
3 files changed, 145 insertions(+), 45 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core
refs/changes/28/56628/1
diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php
index 7136232..5bd057a 100644
--- a/includes/AutoLoader.php
+++ b/includes/AutoLoader.php
@@ -242,6 +242,7 @@
'SpecialRedirectToSpecial' => 'includes/SpecialPage.php',
'SquidPurgeClient' => 'includes/SquidPurgeClient.php',
'SquidPurgeClientPool' => 'includes/SquidPurgeClient.php',
+ 'StatCounter' => 'includes/StatCounter.php',
'Status' => 'includes/Status.php',
'StreamFile' => 'includes/StreamFile.php',
'StringUtils' => 'includes/StringUtils.php',
diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php
index e1e1234..6e79393 100644
--- a/includes/GlobalFunctions.php
+++ b/includes/GlobalFunctions.php
@@ -1177,6 +1177,8 @@
global $wgRequestTime, $wgDebugLogFile, $wgDebugRawPage, $wgRequest;
global $wgProfileLimit, $wgUser;
+ StatCounter::singleton()->flush();
+
$profiler = Profiler::instance();
# Profiling must actually be enabled...
@@ -1240,51 +1242,7 @@
* @return void
*/
function wfIncrStats( $key, $count = 1 ) {
- global $wgStatsMethod;
-
- $count = intval( $count );
- if ( $count == 0 ) {
- return;
- }
-
- if( $wgStatsMethod == 'udp' ) {
- global $wgUDPProfilerHost, $wgUDPProfilerPort,
$wgAggregateStatsID;
- static $socket;
-
- $id = $wgAggregateStatsID !== false ? $wgAggregateStatsID :
wfWikiID();
-
- if ( !$socket ) {
- $socket = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP );
- $statline = "stats/{$id} - 1 1 1 1 1 -total\n";
- socket_sendto(
- $socket,
- $statline,
- strlen( $statline ),
- 0,
- $wgUDPProfilerHost,
- $wgUDPProfilerPort
- );
- }
- $statline = "stats/{$id} - {$count} 1 1 1 1 {$key}\n";
- wfSuppressWarnings();
- socket_sendto(
- $socket,
- $statline,
- strlen( $statline ),
- 0,
- $wgUDPProfilerHost,
- $wgUDPProfilerPort
- );
- wfRestoreWarnings();
- } elseif( $wgStatsMethod == 'cache' ) {
- global $wgMemc;
- $key = wfMemcKey( 'stats', $key );
- if ( is_null( $wgMemc->incr( $key, $count ) ) ) {
- $wgMemc->add( $key, $count );
- }
- } else {
- // Disabled
- }
+ StatCounter::singleton()->incr( $key, $count );
}
/**
diff --git a/includes/StatCounter.php b/includes/StatCounter.php
new file mode 100644
index 0000000..30e5042
--- /dev/null
+++ b/includes/StatCounter.php
@@ -0,0 +1,141 @@
+<?php
+/**
+ * @defgroup StatCounter StatCounter
+ *
+ * StatCounter is used to increment arbitrary keys for profiling reasons.
+ * The key/values are persisted in several possible ways (see $wgStatsMethod).
+ */
+
+/**
+ * Aggregator for wfIncrStats() that batches updates per request.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup StatCounter
+ */
+
+/**
+ * Aggregator for wfIncrStats() that batches updates per request.
+ * This avoids spamming the collector many times for the same key.
+ *
+ * @ingroup StatCounter
+ */
+class StatCounter {
+ /** @var Array */
+ protected $deltas = array(); // (key => count)
+
+ protected function __construct() {}
+
+ public static function singleton() {
+ static $instance = null;
+ if ( !$instance ) {
+ $instance = new self();
+ }
+ return $instance;
+ }
+
+ /**
+ * Increment a key by delta $count
+ *
+ * @param string $key
+ * @param integer $count
+ * @return void
+ */
+ public function incr( $key, $count = 1 ) {
+ if ( PHP_SAPI === 'cli' ) {
+ $this->sendDelta( $key, $count );
+ } else {
+ if ( !isset( $this->deltas[$key] ) ) {
+ $this->deltas[$key] = 0;
+ }
+ $this->deltas[$key] += $count;
+ }
+ }
+
+ /**
+ * Flush all pending deltas to persistent storage
+ *
+ * @return void
+ */
+ public function flush() {
+ try {
+ foreach ( $this->deltas as $key => $count ) {
+ $this->sendDelta( $key, $count );
+ }
+ } catch ( MWException $e ) {
+ trigger_error( "Caught exception: {$e->getMessage()}");
+ }
+ $this->deltas = array();
+ }
+
+ /**
+ * @param string $key
+ * @param string $count
+ * @return void
+ */
+ protected function sendDelta( $key, $count ) {
+ global $wgStatsMethod;
+
+ $count = intval( $count );
+ if ( $count == 0 ) {
+ return;
+ }
+
+ if ( $wgStatsMethod == 'udp' ) {
+ global $wgUDPProfilerHost, $wgUDPProfilerPort,
$wgAggregateStatsID;
+ static $socket;
+
+ $id = $wgAggregateStatsID !== false ?
$wgAggregateStatsID : wfWikiID();
+
+ if ( !$socket ) {
+ $socket = socket_create( AF_INET, SOCK_DGRAM,
SOL_UDP );
+ $statline = "stats/{$id} - 1 1 1 1 1 -total\n";
+ socket_sendto(
+ $socket,
+ $statline,
+ strlen( $statline ),
+ 0,
+ $wgUDPProfilerHost,
+ $wgUDPProfilerPort
+ );
+ }
+ $statline = "stats/{$id} - {$count} 1 1 1 1 {$key}\n";
+ wfSuppressWarnings();
+ socket_sendto(
+ $socket,
+ $statline,
+ strlen( $statline ),
+ 0,
+ $wgUDPProfilerHost,
+ $wgUDPProfilerPort
+ );
+ wfRestoreWarnings();
+ } elseif ( $wgStatsMethod == 'cache' ) {
+ global $wgMemc;
+ $key = wfMemcKey( 'stats', $key );
+ if ( is_null( $wgMemc->incr( $key, $count ) ) ) {
+ $wgMemc->add( $key, $count );
+ }
+ } else {
+ // Disabled
+ }
+ }
+
+ function __destruct() {
+ $this->flush();
+ }
+}
--
To view, visit https://gerrit.wikimedia.org/r/56628
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibe55648422d1b8aac86dd6fa83973d3c8715b0aa
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: wmf/1.21wmf12
Gerrit-Owner: Aaron Schulz <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits