Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
117
src/Framework/Telemetry/ValueObjects/Event.php
Normal file
117
src/Framework/Telemetry/ValueObjects/Event.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Telemetry\ValueObjects;
|
||||
|
||||
use DateTimeImmutable;
|
||||
|
||||
/**
|
||||
* Represents a telemetry event (a discrete occurrence)
|
||||
*/
|
||||
final class Event
|
||||
{
|
||||
/**
|
||||
* @param string $name Name of the event
|
||||
* @param DateTimeImmutable $timestamp Time when the event occurred
|
||||
* @param string $severity Severity level of the event (info, warning, error)
|
||||
* @param array<string, mixed> $attributes Additional attributes for the event
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $name,
|
||||
public readonly DateTimeImmutable $timestamp = new DateTimeImmutable(),
|
||||
public readonly string $severity = 'info',
|
||||
public readonly array $attributes = []
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the event to an array
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->name,
|
||||
'timestamp' => $this->timestamp->format('Y-m-d\TH:i:s.uP'),
|
||||
'severity' => $this->severity,
|
||||
'attributes' => $this->attributes,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance with additional attributes
|
||||
*
|
||||
* @param array<string, mixed> $attributes
|
||||
*/
|
||||
public function withAttributes(array $attributes): self
|
||||
{
|
||||
return new self(
|
||||
$this->name,
|
||||
$this->timestamp,
|
||||
$this->severity,
|
||||
array_merge($this->attributes, $attributes)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an info event
|
||||
*/
|
||||
public static function info(string $name, array $attributes = []): self
|
||||
{
|
||||
return new self(
|
||||
$name,
|
||||
new DateTimeImmutable(),
|
||||
'info',
|
||||
$attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a warning event
|
||||
*/
|
||||
public static function warning(string $name, array $attributes = []): self
|
||||
{
|
||||
return new self(
|
||||
$name,
|
||||
new DateTimeImmutable(),
|
||||
'warning',
|
||||
$attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an error event
|
||||
*/
|
||||
public static function error(string $name, array $attributes = []): self
|
||||
{
|
||||
return new self(
|
||||
$name,
|
||||
new DateTimeImmutable(),
|
||||
'error',
|
||||
$attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the formatted name for metrics
|
||||
*/
|
||||
public function getMetricName(): string
|
||||
{
|
||||
return "event_{$this->severity}_total";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get attributes with event name added
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getMetricAttributes(): array
|
||||
{
|
||||
return array_merge(
|
||||
$this->attributes,
|
||||
['event_name' => $this->name]
|
||||
);
|
||||
}
|
||||
}
|
||||
167
src/Framework/Telemetry/ValueObjects/Metric.php
Normal file
167
src/Framework/Telemetry/ValueObjects/Metric.php
Normal file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Telemetry\ValueObjects;
|
||||
|
||||
use DateTimeImmutable;
|
||||
|
||||
/**
|
||||
* Represents a telemetry metric (a measurable value)
|
||||
*/
|
||||
final class Metric
|
||||
{
|
||||
/**
|
||||
* @param string $name Name of the metric
|
||||
* @param float $value Value of the metric
|
||||
* @param string $unit Unit of measurement (e.g., ms, bytes, count)
|
||||
* @param string $type Type of metric (counter, gauge, histogram)
|
||||
* @param DateTimeImmutable $timestamp Time when the metric was recorded
|
||||
* @param array<string, mixed> $attributes Additional attributes for the metric
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $name,
|
||||
public readonly float $value,
|
||||
public readonly string $unit = '',
|
||||
public readonly string $type = 'gauge',
|
||||
public readonly DateTimeImmutable $timestamp = new DateTimeImmutable(),
|
||||
public readonly array $attributes = []
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the metric to an array
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->name,
|
||||
'value' => $this->value,
|
||||
'unit' => $this->unit,
|
||||
'type' => $this->type,
|
||||
'timestamp' => $this->timestamp->format('Y-m-d\TH:i:s.uP'),
|
||||
'attributes' => $this->attributes,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance with additional attributes
|
||||
*
|
||||
* @param array<string, mixed> $attributes
|
||||
*/
|
||||
public function withAttributes(array $attributes): self
|
||||
{
|
||||
return new self(
|
||||
$this->name,
|
||||
$this->value,
|
||||
$this->unit,
|
||||
$this->type,
|
||||
$this->timestamp,
|
||||
array_merge($this->attributes, $attributes)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a counter metric
|
||||
*/
|
||||
public static function counter(string $name, float $value, array $attributes = []): self
|
||||
{
|
||||
return new self(
|
||||
$name,
|
||||
$value,
|
||||
'count',
|
||||
'counter',
|
||||
new DateTimeImmutable(),
|
||||
$attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a gauge metric
|
||||
*/
|
||||
public static function gauge(string $name, float $value, string $unit = '', array $attributes = []): self
|
||||
{
|
||||
return new self(
|
||||
$name,
|
||||
$value,
|
||||
$unit,
|
||||
'gauge',
|
||||
new DateTimeImmutable(),
|
||||
$attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a histogram metric
|
||||
*/
|
||||
public static function histogram(string $name, float $value, string $unit = '', array $attributes = []): self
|
||||
{
|
||||
return new self(
|
||||
$name,
|
||||
$value,
|
||||
$unit,
|
||||
'histogram',
|
||||
new DateTimeImmutable(),
|
||||
$attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the formatted name for Prometheus
|
||||
*/
|
||||
public function getPrometheusName(): string
|
||||
{
|
||||
// Convert to Prometheus naming convention (lowercase with underscores)
|
||||
return strtolower(str_replace(['.', '-', ' '], '_', $this->name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Prometheus metric type
|
||||
*/
|
||||
public function getPrometheusType(): string
|
||||
{
|
||||
return match($this->type) {
|
||||
'counter' => 'counter',
|
||||
'gauge' => 'gauge',
|
||||
'histogram' => 'histogram',
|
||||
default => 'untyped'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Prometheus help text
|
||||
*/
|
||||
public function getPrometheusHelp(): string
|
||||
{
|
||||
$unitText = $this->unit ? " in {$this->unit}" : '';
|
||||
|
||||
return "{$this->name}{$unitText}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the attributes as Prometheus labels
|
||||
*/
|
||||
public function getPrometheusLabels(): string
|
||||
{
|
||||
if (empty($this->attributes)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$labels = [];
|
||||
foreach ($this->attributes as $key => $value) {
|
||||
// Skip non-scalar values
|
||||
if (is_scalar($value)) {
|
||||
$escapedValue = str_replace(['\\', '"', "\n"], ['\\\\', '\\"', '\\n'], (string)$value);
|
||||
$labels[] = "{$key}=\"{$escapedValue}\"";
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($labels)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return '{' . implode(',', $labels) . '}';
|
||||
}
|
||||
}
|
||||
117
src/Framework/Telemetry/ValueObjects/Operation.php
Normal file
117
src/Framework/Telemetry/ValueObjects/Operation.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Telemetry\ValueObjects;
|
||||
|
||||
use DateTimeImmutable;
|
||||
|
||||
/**
|
||||
* Represents a telemetry operation (similar to a span in OpenTelemetry)
|
||||
*/
|
||||
final class Operation
|
||||
{
|
||||
public ?DateTimeImmutable $endTime = null;
|
||||
|
||||
public string $status = 'pending';
|
||||
|
||||
public ?string $errorMessage = null;
|
||||
|
||||
/**
|
||||
* @param string $id Unique identifier for the operation
|
||||
* @param string|null $parentId Parent operation ID if this is a child operation
|
||||
* @param string $name Name of the operation
|
||||
* @param string $type Type of operation (e.g., http, database, custom)
|
||||
* @param DateTimeImmutable $startTime Start time of the operation
|
||||
* @param array<string, mixed> $attributes Additional attributes for the operation
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $id,
|
||||
public readonly ?string $parentId,
|
||||
public readonly string $name,
|
||||
public readonly string $type,
|
||||
public readonly DateTimeImmutable $startTime,
|
||||
public array $attributes = []
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the duration of the operation in milliseconds
|
||||
*/
|
||||
public function getDuration(): ?float
|
||||
{
|
||||
if ($this->endTime === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ($this->endTime->getTimestamp() - $this->startTime->getTimestamp()) * 1000 +
|
||||
($this->endTime->format('u') - $this->startTime->format('u')) / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the operation to an array
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'parent_id' => $this->parentId,
|
||||
'name' => $this->name,
|
||||
'type' => $this->type,
|
||||
'start_time' => $this->startTime->format('Y-m-d\TH:i:s.uP'),
|
||||
'end_time' => $this->endTime?->format('Y-m-d\TH:i:s.uP'),
|
||||
'duration_ms' => $this->getDuration(),
|
||||
'status' => $this->status,
|
||||
'error_message' => $this->errorMessage,
|
||||
'attributes' => $this->attributes,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an attribute to the operation
|
||||
*/
|
||||
public function addAttribute(string $key, mixed $value): self
|
||||
{
|
||||
$this->attributes[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* End the operation with the given status and error message
|
||||
*/
|
||||
public function end(string $status = 'success', ?string $errorMessage = null): self
|
||||
{
|
||||
$this->endTime = new DateTimeImmutable();
|
||||
$this->status = $status;
|
||||
$this->errorMessage = $errorMessage;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the operation as failed with the given error message
|
||||
*/
|
||||
public function fail(string $errorMessage): self
|
||||
{
|
||||
return $this->end('error', $errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the operation is completed
|
||||
*/
|
||||
public function isCompleted(): bool
|
||||
{
|
||||
return $this->endTime !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the operation was successful
|
||||
*/
|
||||
public function isSuccessful(): bool
|
||||
{
|
||||
return $this->isCompleted() && $this->status === 'success';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user