52 private const LEGACY_EVENTLOGGING_SCHEMA =
'MediaWikiPingback';
60 private const EVENT_PLATFORM_SCHEMA_ID =
'/analytics/legacy/mediawikipingback/1.0.0';
72 private const EVENT_PLATFORM_STREAM =
'eventlogging_MediaWikiPingback';
75 private const EVENT_PLATFORM_EVENT_INTAKE_SERVICE_URI =
76 'https://intake-analytics.wikimedia.org/v1/events?hasty=true';
106 string $eventIntakeUrl = self::EVENT_PLATFORM_EVENT_INTAKE_SERVICE_URI
114 $this->eventIntakeUri = $eventIntakeUrl;
123 public function run(): void {
128 if ( $this->wasRecentlySent() ) {
132 if ( !$this->acquireLock() ) {
133 $this->logger->debug( __METHOD__ .
": couldn't acquire lock" );
138 if ( !$this->postPingback( $data ) ) {
139 $this->logger->warning( __METHOD__ .
": failed to send; check 'http' log channel" );
145 $dbw = $this->dbProvider->getPrimaryDatabase();
146 $timestamp = ConvertibleTimestamp::time();
147 $dbw->newInsertQueryBuilder()
148 ->insertInto(
'updatelog' )
149 ->row( [
'ul_key' => $this->key,
'ul_value' => $timestamp ] )
150 ->onDuplicateKeyUpdate()
151 ->uniqueIndexFields( [
'ul_key' ] )
152 ->set( [
'ul_value' => $timestamp ] )
153 ->caller( __METHOD__ )->execute();
154 $this->logger->debug( __METHOD__ .
": pingback sent OK ({$this->key})" );
160 private function wasRecentlySent(): bool {
161 $timestamp = $this->dbProvider->getReplicaDatabase()->newSelectQueryBuilder()
162 ->select(
'ul_value' )
163 ->from(
'updatelog' )
164 ->where( [
'ul_key' => $this->key ] )
165 ->caller( __METHOD__ )->fetchField();
166 if ( $timestamp ===
false ) {
170 if ( ConvertibleTimestamp::time() - (
int)$timestamp > 60 * 60 * 24 * 30 ) {
184 private function acquireLock(): bool {
185 $cacheKey = $this->cache->makeKey(
'pingback', $this->key );
186 if ( !$this->cache->add( $cacheKey, 1, $this->cache::TTL_HOUR ) ) {
191 $dbw = $this->dbProvider->getPrimaryDatabase();
192 if ( !$dbw->lock( $this->key, __METHOD__, 0 ) ) {
210 $wiki = $this->fetchOrInsertId();
213 'event' => self::getSystemInfo( $this->config ),
214 'schema' => self::LEGACY_EVENTLOGGING_SCHEMA,
220 '$schema' => self::EVENT_PLATFORM_SCHEMA_ID,
221 'client_dt' => ConvertibleTimestamp::now( TS_ISO_8601 ),
227 'stream' => self::EVENT_PLATFORM_STREAM,
248 'PHP' => PHP_VERSION,
249 'OS' => PHP_OS .
' ' . php_uname(
'r' ),
250 'arch' => PHP_INT_SIZE === 8 ? 64 : 32,
251 'machine' => php_uname(
'm' ),
254 if ( isset( $_SERVER[
'SERVER_SOFTWARE'] ) ) {
255 $event[
'serverSoftware'] = $_SERVER[
'SERVER_SOFTWARE'];
258 $limit = ini_get(
'memory_limit' );
259 if ( $limit && $limit !==
"-1" ) {
260 $event[
'memoryLimit'] = $limit;
275 private function fetchOrInsertId(): string {
278 $id = $this->dbProvider->getReplicaDatabase()->newSelectQueryBuilder()
279 ->select(
'ul_value' )
280 ->from(
'updatelog' )
281 ->where( [
'ul_key' =>
'PingBack' ] )
282 ->caller( __METHOD__ )->fetchField();
283 if ( $id !==
false ) {
287 $dbw = $this->dbProvider->getPrimaryDatabase();
288 $id = $dbw->newSelectQueryBuilder()
289 ->select(
'ul_value' )
290 ->from(
'updatelog' )
291 ->where( [
'ul_key' =>
'PingBack' ] )
292 ->caller( __METHOD__ )->fetchField();
293 if ( $id !==
false ) {
298 $dbw->newInsertQueryBuilder()
299 ->insertInto(
'updatelog' )
300 ->row( [
'ul_key' =>
'PingBack',
'ul_value' => $id ] )
301 ->caller( __METHOD__ )->execute();
318 private function postPingback( array $data ): bool {
319 $request = $this->http->create( $this->eventIntakeUri, [
321 'postData' => FormatJson::encode( $data ),
323 $request->setHeader(
'Content-Type',
'application/json' );
325 $result = $request->execute();
327 return $result->isGood();