Skip to content

Commit 02efa28

Browse files
authored
collect action numbers metrics (#918)
* add areMetricsEqual method * use areMetricsEqual method * add WikiDailyMetricsTest * fix * add db migration * rebase de/dailyMetricsCompare * working query * query * query mediawiki db * typoe hinting * more tyoe hinting * improve test * fix tests
1 parent 962c691 commit 02efa28

File tree

5 files changed

+149
-6
lines changed

5 files changed

+149
-6
lines changed

app/Metrics/App/WikiMetrics.php

+65-4
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,49 @@
44

55
use App\Wiki;
66
use App\WikiDailyMetrics;
7+
use Illuminate\Support\Arr;
78

89
class WikiMetrics
910
{
11+
const INTERVAL_DAILY = 'INTERVAL 1 DAY';
12+
const INTERVAL_WEEKLY = ' INTERVAL 1 WEEK';
13+
const INTERVAL_MONTHLY = 'INTERVAL 1 MONTH';
14+
const INTERVAL_QUARTERLY = 'INTERVAL 3 MONTH';
15+
16+
protected $wiki;
17+
1018
public function saveMetrics(Wiki $wiki): void
1119
{
20+
$this->wiki = $wiki;
21+
1222
$today = now()->format('Y-m-d');
1323
$oldRecord = WikiDailyMetrics::where('wiki_id', $wiki->id)->latest('date')->first();
1424
$todayPageCount = $wiki->wikiSiteStats()->first()->pages ?? 0;
1525
$isDeleted = (bool)$wiki->deleted_at;
1626

27+
$dailyActions = $this->getNumberOfActions(self::INTERVAL_DAILY);
28+
$weeklyActions = $this->getNumberOfActions(self::INTERVAL_WEEKLY);
29+
$monthlyActions = $this->getNumberOfActions(self::INTERVAL_MONTHLY);
30+
$quarterlyActions = $this->getNumberOfActions(self::INTERVAL_QUARTERLY);
31+
1732
$dailyMetrics = new WikiDailyMetrics([
1833
'id' => $wiki->id . '_' . date('Y-m-d'),
1934
'pages' => $todayPageCount,
2035
'is_deleted' => $isDeleted,
2136
'date' => $today,
22-
'wiki_id' => $wiki->id
37+
'wiki_id' => $wiki->id,
38+
'daily_actions'=> $dailyActions,
39+
'weekly_actions'=> $weeklyActions,
40+
'monthly_actions'=> $monthlyActions,
41+
'quarterly_actions'=> $quarterlyActions,
2342
]);
24-
43+
44+
// compare current record to old record and only save if there is a change
2545
if ($oldRecord) {
2646
if ($oldRecord->is_deleted) {
2747
\Log::info("Wiki is deleted, no new record for WikiMetrics ID {$wiki->id}.");
2848
return;
2949
}
30-
3150
if (!$isDeleted) {
3251
if ($oldRecord->areMetricsEqual($dailyMetrics)) {
3352
\Log::info("Record unchanged for WikiMetrics ID {$wiki->id}, no new record added.");
@@ -38,6 +57,48 @@ public function saveMetrics(Wiki $wiki): void
3857

3958
$dailyMetrics->save();
4059

41-
\Log::info("New metric recorded for WikiMetrics ID {$wiki->id}");
60+
\Log::info("New metric recorded for Wiki ID {$wiki->id}");
61+
}
62+
63+
protected function getNumberOfActions(string $interval): null|int
64+
{
65+
$actions = null;
66+
67+
// safeguard
68+
if (false === in_array($interval,
69+
[
70+
self::INTERVAL_DAILY,
71+
self::INTERVAL_WEEKLY,
72+
self::INTERVAL_MONTHLY,
73+
self::INTERVAL_QUARTERLY
74+
]
75+
)) { return null; }
76+
77+
$wikiDb = $this->wiki->wikiDb;
78+
$tableRecentChanges = $wikiDb->name . '.' . $wikiDb->prefix . '_recentchanges';
79+
$tableActor = $wikiDb->name . '.' . $wikiDb->prefix . '_actor';
80+
81+
$query = "SELECT
82+
SUM(rc_timestamp >= DATE_FORMAT(DATE_SUB(NOW(), $interval), '%Y%m%d%H%i%S')) AS sum_actions
83+
FROM
84+
$tableRecentChanges AS rc
85+
INNER JOIN $tableActor AS a ON rc.rc_actor = a.actor_id
86+
WHERE
87+
/*
88+
Conditions below added for consistency with Wikidata: https://phabricator.wikimedia.org/diffusion/ADES/browse/master/src/wikidata/site_stats/sql/active_user_changes.sql
89+
*/
90+
a.actor_user != 0
91+
AND rc.rc_bot = 0
92+
AND ( rc.rc_log_type != 'newusers' OR rc.rc_log_type IS NULL)";
93+
94+
$manager = app()->db;
95+
$manager->purge('mw');
96+
$conn = $manager->connection('mw');
97+
$pdo = $conn->getPdo();
98+
$result = $pdo->query($query)->fetch();
99+
100+
$actions = Arr::get($result, 'sum_actions', null);
101+
102+
return $actions;
42103
}
43104
}

app/WikiDailyMetrics.php

+8
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,20 @@ class WikiDailyMetrics extends Model
2323
'date',
2424
'pages',
2525
'is_deleted',
26+
'daily_actions',
27+
'weekly_actions',
28+
'monthly_actions',
29+
'quarterly_actions',
2630
];
2731

2832
// list of properties which are actual wiki metrics
2933
public static $metricNames = [
3034
'pages',
3135
'is_deleted',
36+
'daily_actions',
37+
'weekly_actions',
38+
'monthly_actions',
39+
'quarterly_actions'
3240
];
3341

3442
public function areMetricsEqual(WikiDailyMetrics $wikiDailyMetrics): bool
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*/
12+
public function up(): void
13+
{
14+
Schema::table('wiki_daily_metrics', function (Blueprint $table) {
15+
$table->integer('daily_actions')->nullable();
16+
$table->integer('weekly_actions')->nullable();
17+
$table->integer('monthly_actions')->nullable();
18+
$table->integer('quarterly_actions')->nullable();
19+
});
20+
}
21+
22+
/**
23+
* Reverse the migrations.
24+
*/
25+
public function down(): void
26+
{
27+
Schema::table('wiki_daily_metric', function (Blueprint $table) {
28+
});
29+
}
30+
};

tests/Jobs/UpdateWikiDailyMetricJobTest.php

+27-2
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44

55
use App\Jobs\UpdateWikiDailyMetricJob;
66
use App\Wiki;
7+
use App\WikiDb;
78
use Carbon\Carbon;
89
use Illuminate\Foundation\Testing\RefreshDatabase;
910
use Illuminate\Support\Facades\Queue;
1011
use Tests\TestCase;
12+
use App\Jobs\ProvisionWikiDbJob;
1113

1214
class UpdateWikiDailyMetricJobTest extends TestCase
1315
{
@@ -33,18 +35,41 @@ public function testRunJobForAllWikisIncludingDeletedWikis()
3335
$deletedWiki = Wiki::factory()->create([
3436
'domain' => 'deletedwiki.wikibase.cloud',
3537
]);
38+
39+
$manager = $this->app->make('db');
40+
$job = new ProvisionWikiDbJob();
41+
$job2 = new ProvisionWikiDbJob();
42+
$job->handle($manager);
43+
$job2->handle($manager);
44+
45+
$wikiDbActive = WikiDb::whereDoesntHave('wiki')->first();
46+
$wikiDbActive->update( ['wiki_id' => $activeWiki->id] );
47+
48+
$wikiDbDeleted = WikiDb::whereDoesntHave('wiki')->first();
49+
$wikiDbDeleted->update( ['wiki_id' => $deletedWiki->id] );
50+
3651
$deletedWiki->delete();
3752

53+
54+
3855
(new UpdateWikiDailyMetricJob())->handle();
3956

4057
$this->assertDatabaseHas('wiki_daily_metrics', [
4158
'wiki_id' => $activeWiki->id,
42-
'date' => Carbon::today()->toDateString()
59+
'date' => Carbon::today()->toDateString(),
60+
'daily_actions' => null,
61+
'weekly_actions' => null,
62+
'monthly_actions' => null,
63+
'quarterly_actions' => null,
4364
]);
4465

4566
$this->assertDatabaseHas('wiki_daily_metrics', [
4667
'wiki_id' => $deletedWiki->id,
47-
'date' => Carbon::today()->toDateString()
68+
'date' => Carbon::today()->toDateString(),
69+
'daily_actions' => null,
70+
'weekly_actions' => null,
71+
'monthly_actions' => null,
72+
'quarterly_actions' => null,
4873
]);
4974
}
5075

tests/Metrics/WikiMetricsTest.php

+19
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
use App\Metrics\App\WikiMetrics;
66
use App\Wiki;
7+
use App\WikiDb;
78
use App\WikiDailyMetrics;
9+
use App\Jobs\ProvisionWikiDbJob;
810
use Carbon\Carbon;
911
use Illuminate\Foundation\Testing\RefreshDatabase;
1012
use Tests\TestCase;
@@ -13,13 +15,22 @@ class WikiMetricsTest extends TestCase
1315
{
1416
use RefreshDatabase;
1517

18+
public function setUp(): void {
19+
parent::setUp();
20+
$manager = $this->app->make('db');
21+
$job = new ProvisionWikiDbJob();
22+
$job->handle($manager);
23+
}
1624

1725
public function testSuccessfullyAddRecords()
1826
{
1927
$wiki = Wiki::factory()->create([
2028
'domain' => 'thisfake.wikibase.cloud'
2129
]);
2230

31+
$wikiDb = WikiDb::first();
32+
$wikiDb->update( ['wiki_id' => $wiki->id] );
33+
2334
(new WikiMetrics())->saveMetrics($wiki);
2435
// Assert the metric is updated in the database
2536
$this->assertDatabaseHas('wiki_daily_metrics', [
@@ -33,6 +44,10 @@ public function testDoesNotAddDuplicateRecordsWithOnlyDateChange()
3344
$wiki = Wiki::factory()->create([
3445
'domain' => 'thisfake.wikibase.cloud'
3546
]);
47+
48+
$wikiDb = WikiDb::first();
49+
$wikiDb->update( ['wiki_id' => $wiki->id] );
50+
3651
//Insert an old metric value for a wiki
3752
WikiDailyMetrics::create([
3853
'id' => $wiki->id. '_'. Carbon::yesterday()->toDateString(),
@@ -55,6 +70,10 @@ public function testAddRecordsWikiIsDeleted()
5570
$wiki = Wiki::factory()->create([
5671
'domain' => 'thisfake.wikibase.cloud'
5772
]);
73+
74+
$wikiDb = WikiDb::first();
75+
$wikiDb->update( ['wiki_id' => $wiki->id] );
76+
5877
//Insert an old metric value for a wiki
5978
WikiDailyMetrics::create([
6079
'id' => $wiki->id. '_'. Carbon::yesterday()->toDateString(),

0 commit comments

Comments
 (0)