Skip to content

Commit d80ee58

Browse files
committed
Massive refactor for better architecture
1 parent c34d7cd commit d80ee58

35 files changed

+2175
-1552
lines changed

dashboard/js/script.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ function populateRequestLog(requests) {
236236
const time = parseFloat(r.total_time) * 1000;
237237

238238
// Convert UTC timestamp to selected timezone
239-
const formattedTimestamp = formatTimestamp(r.timestamp);
239+
const formattedTimestamp = formatTimestamp(r.request_dt);
240240

241241
// Build details sections conditionally
242242
let detailSections = [];
@@ -364,7 +364,7 @@ function populateRequestLog(requests) {
364364
<h2 class="accordion-header" id="event-heading-${index}-${eventIndex}">
365365
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#event-collapse-${index}-${eventIndex}" aria-expanded="false" aria-controls="event-collapse-${index}-${eventIndex}">
366366
<span class="badge bg-info me-2">${event.type}</span>
367-
<small class="text-muted">${new Date(parseFloat(event.timestamp) * 1000).toISOString().split('T')[1].replace('Z', '')}</small>
367+
<small class="text-muted">${new Date(parseFloat(event.event_dt) * 1000).toISOString().split('T')[1].replace('Z', '')}</small>
368368
</button>
369369
</h2>
370370
<div id="event-collapse-${index}-${eventIndex}" class="accordion-collapse collapse" aria-labelledby="event-heading-${index}-${eventIndex}" data-bs-parent="#customEventsAccordion-${index}">
@@ -507,7 +507,7 @@ function drawLatencyChart(data) {
507507
latencyChart = new Chart(ctxLatency, {
508508
type: 'line',
509509
data: {
510-
labels: chartData.map(d => d.timestamp),
510+
labels: chartData.map(d => d.request_dt),
511511
datasets: [{
512512
label: 'Average Latency (ms)',
513513
data: chartData.map(d => d.average_time * 1000),
@@ -593,7 +593,7 @@ function updateResponseCodeChart(responseData) {
593593
}
594594

595595
// Extract all unique response codes
596-
const responseCodes = [...new Set(responseData.flatMap(d => Object.keys(d).filter(k => k !== 'timestamp')))];
596+
const responseCodes = [...new Set(responseData.flatMap(d => Object.keys(d).filter(k => k !== 'request_dt')))];
597597

598598
// Create datasets for each response code
599599
const datasets = responseCodes.map(code => {
@@ -620,7 +620,7 @@ function updateResponseCodeChart(responseData) {
620620
responseCodeChart = new Chart(ctxResponse, {
621621
type: 'bar',
622622
data: {
623-
labels: responseData.map(d => d.timestamp),
623+
labels: responseData.map(d => d.request_dt),
624624
datasets: datasets
625625
},
626626
options: {

dashboard/views/dashboard.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,6 @@
364364
<!-- Chart.js -->
365365
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
366366
<!-- Dashboard Logic -->
367-
<script src="/js/script.js?ver=3"></script>
367+
<script src="/js/script.js?ver=4"></script>
368368
</body>
369369
</html>

src/Apm.php

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,6 @@ public function __construct(LoggerInterface $logger, float $sampleRate = 1.0)
4848
$this->sampleRate = $sampleRate;
4949
}
5050

51-
/**
52-
* Generates a unique request ID.
53-
*
54-
* @return string
55-
*/
56-
public function generateRequestId(): string
57-
{
58-
return uniqid('req_', true);
59-
}
60-
6151
/**
6252
* Registers the events for the application performance monitoring (APM) system.
6353
*
@@ -92,14 +82,14 @@ public function bindEventsToFlightInstance(Engine $app): void
9282

9383
$dispatcher->on('flight.request.received', function (Request $request) use ($app) {
9484
// Generate request ID early and store it
95-
$requestId = $this->generateRequestId();
96-
$this->metrics['request_id'] = $requestId;
85+
$requestToken = $this->generateRequestToken();
86+
$this->metrics['request_token'] = $requestToken;
9787

9888
// Make request ID accessible on the request object
99-
$app->response()->setHeader('X-Flight-Request-Id', $requestId);
89+
$app->response()->setHeader('X-Flight-Request-Id', $requestToken);
10090

10191
// Register in Flight's shared variable space for easy access
102-
$app->set('apm.request_id', $requestId);
92+
$app->set('apm.request_id', $requestToken);
10393

10494
$this->metrics['start_time'] = microtime(true);
10595
$this->metrics['start_memory'] = memory_get_usage();
@@ -252,13 +242,23 @@ public function isBot(string $userAgent): bool
252242
return false;
253243
}
254244

245+
/**
246+
* Gets the current request ID.
247+
*
248+
* @return string|null The request ID or null if not set.
249+
*/
250+
public function generateRequestToken(): ?string
251+
{
252+
return $this->metrics['request_token'] ?? null;
253+
}
254+
255255
/**
256256
* Gets the current request ID.
257257
*
258258
* @return string|null The request ID or null if not set.
259259
*/
260260
public function getRequestId(): ?string
261261
{
262-
return $this->metrics['request_id'] ?? null;
262+
return $this->metrics['request_token'] ?? null;
263263
}
264264
}
Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,27 @@
1212
*
1313
* Handles storing application performance metrics in a database table
1414
*/
15-
abstract class DatabaseLoggerAbstract
15+
abstract class LoggerAbstract
1616
{
1717
/**
1818
* PDO database connection instance
1919
*
2020
* @var PDO
2121
*/
22-
protected PDO $pdo;
23-
24-
/**
25-
* Flag indicating whether the required database table exists
26-
*
27-
* @var bool
28-
*/
29-
protected bool $tableCreated = false;
22+
protected $pdo;
3023

31-
/**
32-
* Abstract method to ensure the metrics table exists
24+
/**
25+
* Constructor for the database logger
3326
*
34-
* Implementations should create the table if it doesn't exist
27+
* Initializes the PDO connection and ensures the required table exists
3528
*
36-
* @return void
29+
* @param PDO $pdo PDO database connection instance
3730
*/
38-
abstract protected function ensureTableExists(): void;
39-
31+
public function __construct(PDO $pdo)
32+
{
33+
$this->pdo = $pdo;
34+
}
35+
4036
/**
4137
* Logs performance metrics to the database
4238
*

src/apm/logger/LoggerFactory.php

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
use flight\apm\ApmFactoryAbstract;
66
use InvalidArgumentException;
7+
use flight\apm\logger\MysqlLogger;
8+
use flight\database\PdoWrapper;
9+
use PDO;
710

811
class LoggerFactory extends ApmFactoryAbstract
912
{
@@ -20,10 +23,22 @@ public static function create(?string $runwayConfigPath = null): LoggerInterface
2023
}
2124
$runwayConfig = self::loadConfig($runwayConfigPath);
2225

23-
$storageType = $runwayConfig['apm']['source_type'];
24-
switch($storageType) {
26+
$dsn = $runwayConfig['apm']['source_db_dsn'];
27+
$storageType = $runwayConfig['apm']['source_type'];
28+
$options = $runwayConfig['apm']['source_db_options'] ?: [
29+
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
30+
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
31+
PDO::ATTR_EMULATE_PREPARES => false,
32+
];
33+
switch ($storageType) {
2534
case 'sqlite':
26-
return new SqliteLogger($runwayConfig['apm']['dest_db_dsn']);
35+
$pdo = new PDO($dsn, null, null, $options);
36+
return new SqliteLogger($pdo);
37+
case 'mysql':
38+
$user = $runwayConfig['apm']['source_db_user'] ?? null;
39+
$pass = $runwayConfig['apm']['source_db_pass'] ?? null;
40+
$pdo = new PDO($dsn, $user, $pass, $options);
41+
return new MysqlLogger($pdo);
2742
default:
2843
throw new InvalidArgumentException("Unsupported storage type: $storageType");
2944
}

src/apm/logger/MysqlLogger.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace flight\apm\logger;
5+
6+
class MysqlLogger extends LoggerAbstract implements LoggerInterface
7+
{
8+
9+
}

src/apm/logger/SqliteLogger.php

Lines changed: 3 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,50 +4,7 @@
44

55
namespace flight\apm\logger;
66

7-
use PDO;
8-
use PDOException;
9-
10-
class SqliteLogger extends DatabaseLoggerAbstract implements LoggerInterface {
11-
12-
/**
13-
* Constructor for the database logger
14-
*
15-
* Initializes the PDO connection and ensures the required table exists
16-
*
17-
* @param string $dsn The Data Source Name (DSN) for the SQLite database
18-
*/
19-
public function __construct(string $dsn)
20-
{
21-
$this->pdo = new PDO($dsn, null, null, [
22-
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
23-
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
24-
PDO::ATTR_EMULATE_PREPARES => false,
25-
]);
26-
$this->ensureTableExists();
27-
}
28-
29-
/**
30-
* @inheritDoc
31-
*/
32-
protected function ensureTableExists(): void
33-
{
34-
if ($this->tableCreated) {
35-
return;
36-
}
37-
38-
try {
39-
$this->pdo->exec("
40-
CREATE TABLE IF NOT EXISTS apm_metrics_log (
41-
id INTEGER PRIMARY KEY AUTOINCREMENT,
42-
added_dt DATETIME DEFAULT CURRENT_TIMESTAMP,
43-
metrics_json TEXT NOT NULL
44-
)
45-
");
46-
$this->pdo->exec("CREATE INDEX IF NOT EXISTS idx_added_dt ON apm_metrics_log (added_dt)");
47-
$this->tableCreated = true;
48-
} catch (PDOException $e) {
49-
error_log("Failed to create apm_metrics_log table: " . $e->getMessage());
50-
throw $e;
51-
}
52-
}
7+
class SqliteLogger extends LoggerAbstract implements LoggerInterface
8+
{
9+
5310
}

src/apm/migration/mysql/0001-initial-schema.sql

Whitespace-only changes.

0 commit comments

Comments
 (0)