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:
2025-08-11 20:13:26 +02:00
parent 59fd3dd3b1
commit 55a330b223
3683 changed files with 2956207 additions and 16948 deletions

View 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]
);
}
}

View 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) . '}';
}
}

View 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';
}
}