Skip to content

Commit

Permalink
feat(statistics): data collect
Browse files Browse the repository at this point in the history
Signed-off-by: Luka Trovic <[email protected]>
  • Loading branch information
luka-nextcloud committed Dec 17, 2024
1 parent b76a132 commit f798049
Show file tree
Hide file tree
Showing 17 changed files with 184 additions and 46 deletions.
4 changes: 4 additions & 0 deletions appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ The official whiteboard app for Nextcloud. It allows users to create and share w
<nextcloud min-version="28" max-version="30"/>
</dependencies>

<background-jobs>
<job>OCA\Whiteboard\BackgroundJob\WatchActiveUsers</job>
</background-jobs>

<settings>
<admin>OCA\Whiteboard\Settings\Admin</admin>
<admin-section>OCA\Whiteboard\Settings\Section</admin-section>
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"license": "AGPL",
"require": {
"php": "^8.0",
"firebase/php-jwt": "^6.10"
"firebase/php-jwt": "^6.10",
"ext-curl": "*"
},
"require-dev": {
"nextcloud/coding-standard": "^1.0",
Expand Down
65 changes: 65 additions & 0 deletions lib/BackgrounJob/WatchActiveUsers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Whiteboard\BackgroundJob;

use OCA\Whiteboard\Service\ConfigService;
use OCA\Whiteboard\Service\StatsService;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\TimedJob;

class WatchActiveUsers extends TimedJob {
public function __construct(
ITimeFactory $time,
protected bool $isCLI,
protected StatsService $statsService,
protected ConfigService $configService,
) {
parent::__construct($time);
$this->setInterval(300);
}

protected function run($argument) {
$metricsData = $this->getMetricsData();
$activeUsers = $metricsData['totalUsers'] ?? 0;
$this->statsService->insertActiveUsersCount($activeUsers);
}

private function getMetricsData(): array {
$serverUrl = $this->configService->getCollabBackendUrl();
$metricToken = $this->configService->getCollabBackendMetricsToken();

if (!$serverUrl || !$metricToken) {
return [];
}

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $serverUrl . '/metrics');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $metricToken,
]);
$response = curl_exec($curl);
curl_close($curl);

$metrics = [
'totalUsers' => 0,
];

foreach (explode("\n", $response) as $line) {
if (strpos($line, 'whiteboard_room_stats{stat="totalUsers"}') === false) {
continue;
}
$parts = explode(' ', $line);
$metrics['totalUsers'] = (int) $parts[1];
}

return $metrics;
}
}
5 changes: 5 additions & 0 deletions lib/Controller/SettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public function update(): DataResponse {
$serverUrl = $this->request->getParam('serverUrl');
$secret = $this->request->getParam('secret');
$enableStatistics = $this->request->getParam('enableStatistics');
$metricsToken = $this->request->getParam('metricsToken');

if ($serverUrl !== null) {
$this->configService->setCollabBackendUrl($serverUrl);
Expand All @@ -49,6 +50,10 @@ public function update(): DataResponse {
$this->configService->setWhiteboardEnableStatistics($enableStatistics);
}

if ($metricsToken !== null) {
$this->configService->setCollabBackendMetricsToken($metricsToken);
}

return new DataResponse([
'jwt' => $this->jwtService->generateJWTFromPayload([ 'serverUrl' => $serverUrl ])
]);
Expand Down
4 changes: 2 additions & 2 deletions lib/Controller/WhiteboardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ public function update(int $fileId, array $data): DataResponse {

$this->contentService->updateContent($file, $data);

$event = new WhiteboardUpdatedEvent($file, $user, $data);
$this->dispatcher->dispatchTyped($event);
$event = new WhiteboardUpdatedEvent($file, $user, $data);
$this->dispatcher->dispatchTyped($event);

return new DataResponse(['status' => 'success']);
} catch (Exception $e) {
Expand Down
2 changes: 2 additions & 0 deletions lib/Events/AbstractWhiteboardEvent.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Whiteboard\Events;

use OCA\Whiteboard\Model\User;
Expand Down
2 changes: 2 additions & 0 deletions lib/Events/WhiteboardOpenedEvent.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Whiteboard\Events;

class WhiteboardOpenedEvent extends AbstractWhiteboardEvent {
Expand Down
2 changes: 2 additions & 0 deletions lib/Events/WhiteboardUpdatedEvent.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Whiteboard\Events;

class WhiteboardUpdatedEvent extends AbstractWhiteboardEvent {
Expand Down
6 changes: 3 additions & 3 deletions lib/Listener/FileCreatedListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/
namespace OCA\Whiteboard\Listener;

use OCA\Whiteboard\Service\EventsService;
use OCA\Whiteboard\Service\StatsService;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Files\Events\Node\NodeCreatedEvent;
Expand All @@ -20,7 +20,7 @@
*/
final class FileCreatedListener implements IEventListener {
public function __construct(
protected EventsService $eventsService,
protected StatsService $statsService,
protected IUserSession $userSession,
) {
}
Expand All @@ -38,7 +38,7 @@ public function handle(Event $event): void {

$currentUser = $this->userSession->getUser();

$this->eventsService->insertEvent([
$this->statsService->insertEvent([
'user' => $currentUser ? $currentUser->getUID() : $node->getOwner()->getUID(),
'type' => 'created',
'share_token' => '',
Expand Down
8 changes: 5 additions & 3 deletions lib/Listener/WhiteboardOpenedListener.php
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Whiteboard\Listener;

use OCA\Whiteboard\Events\WhiteboardOpenedEvent;
use OCA\Whiteboard\Model\PublicSharingUser;
use OCA\Whiteboard\Service\EventsService;
use OCA\Whiteboard\Service\StatsService;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Files\Events\Node\NodeCreatedEvent;
Expand All @@ -21,7 +23,7 @@
*/
final class WhiteboardOpenedListener implements IEventListener {
public function __construct(
protected EventsService $eventsService,
protected StatsService $statsService,
) {
}

Expand All @@ -34,7 +36,7 @@ public function handle(Event $event): void {
$file = $event->getFile();
$data = $event->getData();

$this->eventsService->insertEvent([
$this->statsService->insertEvent([
'user' => $user->getUID(),
'type' => 'opened',
'share_token' => $user instanceof PublicSharingUser ? $user->getPublicSharingToken() : '',
Expand Down
8 changes: 5 additions & 3 deletions lib/Listener/WhiteboardUpdatedListener.php
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Whiteboard\Listener;

use OCA\Whiteboard\Events\WhiteboardUpdatedEvent;
use OCA\Whiteboard\Model\PublicSharingUser;
use OCA\Whiteboard\Service\EventsService;
use OCA\Whiteboard\Service\StatsService;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Files\Events\Node\NodeCreatedEvent;
Expand All @@ -21,7 +23,7 @@
*/
final class WhiteboardUpdatedListener implements IEventListener {
public function __construct(
protected EventsService $eventsService,
protected StatsService $statsService,
) {
}

Expand All @@ -34,7 +36,7 @@ public function handle(Event $event): void {
$file = $event->getFile();
$data = $event->getData();

$this->eventsService->insertEvent([
$this->statsService->insertEvent([
'user' => $user->getUID(),
'type' => 'opened',
'share_token' => $user instanceof PublicSharingUser ? $user->getPublicSharingToken() : '',
Expand Down
19 changes: 19 additions & 0 deletions lib/Migration/Version1000Date20241213132620.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,25 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt
$table->addIndex(['fileid'], 'fileid_index');
}

if (!$schema->hasTable('whiteboard_active_users')) {
$table = $schema->createTable('whiteboard_active_users');
$table->addColumn('id', Types::BIGINT, [
'autoincrement' => true,
'notnull' => true,
'length' => 20,
]);
$table->addColumn('total_users', Types::INTEGER, [
'notnull' => false,
'length' => 11,
'default' => 0,
]);
$table->addColumn('timestamp', Types::INTEGER, [
'notnull' => true,
'length' => 11,
'default' => 0,
]);
}

return $schema;
}

Expand Down
17 changes: 17 additions & 0 deletions lib/Service/ConfigService.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,21 @@ public function getWhiteboardEnableStatistics(): bool {
public function setWhiteboardEnableStatistics(bool $enableStatistics): void {
$this->appConfig->setAppValueBool('enable_statistics', $enableStatistics);
}

public function getCollabBackendMetricsToken(): string {
if (!method_exists($this->appConfig, 'getAppValueString')) {
return $this->appConfig->getAppValue('collabBackendMetricsToken');
}

return $this->appConfig->getAppValueString('collabBackendMetricsToken');
}

public function setCollabBackendMetricsToken(string $collabBackendMetricsToken): void {
if (!method_exists($this->appConfig, 'setAppValueString')) {
$this->appConfig->setAppValue('collabBackendMetricsToken', $collabBackendMetricsToken);
return;
}

$this->appConfig->setAppValueString('collabBackendMetricsToken', $collabBackendMetricsToken);
}
}
34 changes: 0 additions & 34 deletions lib/Service/EventsService.php

This file was deleted.

44 changes: 44 additions & 0 deletions lib/Service/StatsService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Whiteboard\Service;

use OCP\IDBConnection;

final class StatsService {
public function __construct(
protected IDBConnection $connection,
) {
}

public function insertEvent(array $data): void {
$queryBuilder = $this->connection->getQueryBuilder();
$queryBuilder->insert('whiteboard_events')
->values([
'user' => $queryBuilder->createNamedParameter($data['user']),
'type' => $queryBuilder->createNamedParameter($data['type']),
'share_token' => $queryBuilder->createNamedParameter($data['share_token']),
'fileid' => $queryBuilder->createNamedParameter($data['fileid']),
'elements' => $queryBuilder->createNamedParameter($data['elements']),
'size' => $queryBuilder->createNamedParameter($data['size']),
'timestamp' => $queryBuilder->createNamedParameter($data['timestamp']),
])
->executeStatement();
}

public function insertActiveUsersCount(int $count): void {
$queryBuilder = $this->connection->getQueryBuilder();
$queryBuilder->insert('whiteboard_active_users')
->values([
'total_users' => $queryBuilder->createNamedParameter($count),
'timestamp' => $queryBuilder->createNamedParameter(time()),
])
->executeStatement();
}
}
1 change: 1 addition & 0 deletions lib/Settings/Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function getForm(): TemplateResponse {
$this->initialState->provideInitialState('secret', $this->configService->getWhiteboardSharedSecret());
$this->initialState->provideInitialState('jwt', $this->jwtService->generateJWTFromPayload([]));
$this->initialState->provideInitialState('enable_statistics', $this->configService->getWhiteboardEnableStatistics());
$this->initialState->provideInitialState('metrics_token', $this->configService->getCollabBackendMetricsToken());
$response = new TemplateResponse(
'whiteboard',
'admin',
Expand Down
Loading

0 comments on commit f798049

Please sign in to comment.