Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bin/build-phar.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ composer config repositories.local-adapter-chartjs '{"type": "path", "url": "../
composer config repositories.local-openapi-specification '{"type": "path", "url": "../bridge/openapi/specification", "options": {"symlink": false}}' --working-dir="$CLI_DIR"
composer config repositories.local-parquet-viewer '{"type": "path", "url": "../lib/parquet-viewer", "options": {"symlink": false}}' --working-dir="$CLI_DIR"
composer config repositories.local-postgresql '{"type": "path", "url": "../lib/postgresql", "options": {"symlink": false}}' --working-dir="$CLI_DIR"
composer config repositories.local-telemetry '{"type": "path", "url": "../lib/telemetry", "options": {"symlink": false}}' --working-dir="$CLI_DIR"
composer config repositories.local-types '{"type": "path", "url": "../lib/types", "options": {"symlink": false}}' --working-dir="$CLI_DIR"
composer config repositories.local-array-dot '{"type": "path", "url": "../lib/array-dot", "options": {"symlink": false}}' --working-dir="$CLI_DIR"
composer config repositories.local-filesystem '{"type": "path", "url": "../lib/filesystem", "options": {"symlink": false}}' --working-dir="$CLI_DIR"
Expand Down
8 changes: 8 additions & 0 deletions src/core/etl/src/Flow/ETL/DSL/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
};
use Dom\{HTMLDocument, HTMLElement};
use Flow\Calculator\Rounding;
use Flow\Clock\SystemClock;
use Flow\ETL\{Analyze,
Attribute\DocumentationDSL,
Attribute\DocumentationExample,
Expand Down Expand Up @@ -243,6 +244,7 @@
};
use Flow\Types\Type\{TypeFactory, Types};
use Flow\Types\Value\Json;
use Psr\Clock\ClockInterface;
use UnitEnum;

/**
Expand Down Expand Up @@ -2607,3 +2609,9 @@ function write_with_retries(
) : RetryLoader {
return new RetryLoader($loader, $retry_strategy, $delay_factory, $sleep);
}

#[DocumentationDSL(module: Module::CORE, type: DSLType::HELPER)]
function clock(string $time_zone = 'UTC') : ClockInterface
{
return new SystemClock(new \DateTimeZone($time_zone));
}
71 changes: 64 additions & 7 deletions src/lib/telemetry/src/Flow/Telemetry/DSL/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
use Flow\Telemetry\Meter\Processor\{BatchingMetricProcessor, PassThroughMetricProcessor};
use Flow\Telemetry\Propagation\{ArrayCarrier, CompositePropagator, PropagationContext, Propagator, SuperglobalCarrier, W3CBaggage, W3CTraceContext};
use Flow\Telemetry\Provider\Clock\SystemClock;
use Flow\Telemetry\Provider\Console\{ConsoleLogExporter, ConsoleMetricExporter, ConsoleSpanExporter};
use Flow\Telemetry\Provider\Console\{ConsoleLogExporter, ConsoleLogOptions, ConsoleMetricExporter, ConsoleMetricOptions, ConsoleSpanExporter, ConsoleSpanOptions};
use Flow\Telemetry\Provider\Memory\{MemoryLogExporter, MemoryLogProcessor, MemoryMetricExporter, MemoryMetricProcessor, MemorySpanExporter, MemorySpanProcessor};
use Flow\Telemetry\Provider\Void\{VoidLogExporter, VoidLogProcessor, VoidMetricExporter, VoidMetricProcessor, VoidSpanExporter, VoidSpanProcessor};
use Flow\Telemetry\Resource\Detector\{CachingDetector, ChainDetector, ComposerDetector, EnvironmentDetector, HostDetector, ManualDetector, OsDetector, ProcessDetector};
Expand Down Expand Up @@ -628,11 +628,12 @@ function severity_filtering_log_processor(
* Useful for debugging and development.
*
* @param bool $colors Whether to use ANSI colors (default: true)
* @param ConsoleSpanOptions $options Display options for the exporter
*/
#[DocumentationDSL(module: Module::TELEMETRY, type: DSLType::HELPER)]
function console_span_exporter(bool $colors = true) : ConsoleSpanExporter
function console_span_exporter(bool $colors = true, ConsoleSpanOptions $options = new ConsoleSpanOptions()) : ConsoleSpanExporter
{
return new ConsoleSpanExporter($colors);
return new ConsoleSpanExporter($colors, null, $options);
}

/**
Expand All @@ -642,11 +643,12 @@ function console_span_exporter(bool $colors = true) : ConsoleSpanExporter
* Useful for debugging and development.
*
* @param bool $colors Whether to use ANSI colors (default: true)
* @param ConsoleMetricOptions $options Display options for the exporter
*/
#[DocumentationDSL(module: Module::TELEMETRY, type: DSLType::HELPER)]
function console_metric_exporter(bool $colors = true) : ConsoleMetricExporter
function console_metric_exporter(bool $colors = true, ConsoleMetricOptions $options = new ConsoleMetricOptions()) : ConsoleMetricExporter
{
return new ConsoleMetricExporter($colors);
return new ConsoleMetricExporter($colors, null, $options);
}

/**
Expand All @@ -657,11 +659,66 @@ function console_metric_exporter(bool $colors = true) : ConsoleMetricExporter
*
* @param bool $colors Whether to use ANSI colors (default: true)
* @param null|int $maxBodyLength Maximum length for body+attributes column (null = no limit, default: 100)
* @param ConsoleLogOptions $options Display options for the exporter
*/
#[DocumentationDSL(module: Module::TELEMETRY, type: DSLType::HELPER)]
function console_log_exporter(bool $colors = true, ?int $maxBodyLength = 100) : ConsoleLogExporter
function console_log_exporter(bool $colors = true, ?int $maxBodyLength = 100, ConsoleLogOptions $options = new ConsoleLogOptions()) : ConsoleLogExporter
{
return new ConsoleLogExporter($colors, $maxBodyLength);
return new ConsoleLogExporter($colors, $maxBodyLength, null, $options);
}

/**
* Create ConsoleSpanOptions with all display options enabled (default behavior).
*/
#[DocumentationDSL(module: Module::TELEMETRY, type: DSLType::HELPER)]
function console_span_options() : ConsoleSpanOptions
{
return ConsoleSpanOptions::default();
}

/**
* Create ConsoleSpanOptions with minimal display (legacy compact format).
*/
#[DocumentationDSL(module: Module::TELEMETRY, type: DSLType::HELPER)]
function console_span_options_minimal() : ConsoleSpanOptions
{
return ConsoleSpanOptions::minimal();
}

/**
* Create ConsoleLogOptions with all display options enabled (default behavior).
*/
#[DocumentationDSL(module: Module::TELEMETRY, type: DSLType::HELPER)]
function console_log_options() : ConsoleLogOptions
{
return ConsoleLogOptions::default();
}

/**
* Create ConsoleLogOptions with minimal display (legacy compact format).
*/
#[DocumentationDSL(module: Module::TELEMETRY, type: DSLType::HELPER)]
function console_log_options_minimal() : ConsoleLogOptions
{
return ConsoleLogOptions::minimal();
}

/**
* Create ConsoleMetricOptions with all display options enabled (default behavior).
*/
#[DocumentationDSL(module: Module::TELEMETRY, type: DSLType::HELPER)]
function console_metric_options() : ConsoleMetricOptions
{
return ConsoleMetricOptions::default();
}

/**
* Create ConsoleMetricOptions with minimal display (legacy compact format).
*/
#[DocumentationDSL(module: Module::TELEMETRY, type: DSLType::HELPER)]
function console_metric_options_minimal() : ConsoleMetricOptions
{
return ConsoleMetricOptions::minimal();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public function __construct(
bool $colors = true,
private ?int $maxBodyLength = null,
mixed $outputStream = null,
private ConsoleLogOptions $options = new ConsoleLogOptions(),
) {
/** @var null|resource $outputStream */
$this->output = new ConsoleOutput($colors, $outputStream);
Expand All @@ -53,19 +54,26 @@ public function export(array $entries) : bool
$formattedRecords = $this->formatEntries($entries);
$bodyWidth = $this->calculateBodyWidth($formattedRecords);
$hasTrace = $this->hasAnySpanContext($entries);
$resourceLine = $this->buildResourceLine($entries[0]->resource);
$resourceLines = $this->buildResourceLines($entries[0]->resource);
$scopeLine = $this->buildScopeLine($entries[0]);
$width = $this->calculateTotalWidth($bodyWidth, $hasTrace);

if ($resourceLine !== null) {
foreach ($resourceLines as $resourceLine) {
$resourceWidth = \mb_strlen($this->output->stripColors($resourceLine)) + 4;
$width = \max($width, $resourceWidth);
}

$buffer = $this->output->border($width) . PHP_EOL;
$buffer .= $this->output->row($this->output->bold('LOGS'), $width) . PHP_EOL;

if ($resourceLine !== null) {
$buffer .= $this->output->row($resourceLine, $width) . PHP_EOL;
if (\count($resourceLines) > 0) {
foreach ($resourceLines as $resourceLine) {
$buffer .= $this->output->row($resourceLine, $width) . PHP_EOL;
}
}

if ($scopeLine !== null) {
$buffer .= $this->output->row($scopeLine, $width) . PHP_EOL;
}

$buffer .= $this->output->border($width) . PHP_EOL;
Expand Down Expand Up @@ -110,7 +118,7 @@ private function buildHeaderLine(int $bodyWidth, bool $hasTrace) : string
}

/**
* @param array{timestamp: string, severity: string, severityRaw: Severity, body: string, trace: string} $record
* @param array{timestamp: string, severity: string, severityRaw: Severity, body: string, trace: string, droppedAttributeCount: int} $record
*/
private function buildLine(array $record, int $bodyWidth, bool $hasTrace) : string
{
Expand All @@ -123,6 +131,10 @@ private function buildLine(array $record, int $bodyWidth, bool $hasTrace) : stri
$line .= $this->colorBySeverity($severity, $record['severityRaw']) . ' | ';
$line .= $body;

if ($this->options->showDroppedAttributeCount && $record['droppedAttributeCount'] > 0) {
$line .= ' ' . $this->output->yellow('[dropped:' . $record['droppedAttributeCount'] . ']');
}

if ($hasTrace) {
$trace = $this->output->pad($record['trace'], self::TRACE_WIDTH);
$line .= ' | ' . ($record['trace'] !== '' ? $this->output->dim($trace) : $trace);
Expand All @@ -131,34 +143,68 @@ private function buildLine(array $record, int $bodyWidth, bool $hasTrace) : stri
return $line;
}

private function buildResourceLine(TelemetryResource $resource) : ?string
/**
* @return array<string>
*/
private function buildResourceLines(TelemetryResource $resource) : array
{
if ($resource->isEmpty()) {
return null;
return [];
}

$parts = [];
$serviceName = $resource->get('service.name');
if (!$this->options->showResourceAttributes) {
$parts = [];
$serviceName = $resource->get('service.name');

if (\is_string($serviceName)) {
$parts[] = $serviceName;
}

$serviceVersion = $resource->get('service.version');

if (\is_string($serviceVersion)) {
$parts[] = 'v' . $serviceVersion;
}

if (\is_string($serviceName)) {
$parts[] = $serviceName;
if (\count($parts) === 0) {
return [];
}

return ['Resource: ' . $this->output->dim(\implode(' ', $parts))];
}

$serviceVersion = $resource->get('service.version');
$lines = [];
$lines[] = $this->output->bold('Resource:');

if (\is_string($serviceVersion)) {
$parts[] = 'v' . $serviceVersion;
$attributes = $resource->all();
$maxKeyLength = 0;

foreach (\array_keys($attributes) as $key) {
$maxKeyLength = \max($maxKeyLength, \mb_strlen($key));
}

if (\count($parts) === 0) {
foreach ($attributes as $key => $value) {
$keyStr = $this->output->pad($key, $maxKeyLength);
$valueStr = $this->output->formatValue($value);
$lines[] = ' ' . $this->output->cyan($keyStr) . ' = ' . $valueStr;
}

return $lines;
}

private function buildScopeLine(LogEntry $entry) : ?string
{
if (!$this->options->showInstrumentationScope) {
return null;
}

return 'Resource: ' . $this->output->dim(\implode(' ', $parts));
$scope = $entry->scope;

return 'Scope: ' . $this->output->dim($scope->name . ' v' . $scope->version);
}

/**
* @param array<array{timestamp: string, severity: string, severityRaw: Severity, body: string, trace: string}> $records
* @param array<array{timestamp: string, severity: string, severityRaw: Severity, body: string, trace: string, droppedAttributeCount: int}> $records
*/
private function calculateBodyWidth(array $records) : int
{
Expand Down Expand Up @@ -225,7 +271,7 @@ private function formatAttributes(array $attributes) : string
/**
* @param array<LogEntry> $entries
*
* @return array<array{timestamp: string, severity: string, severityRaw: Severity, body: string, trace: string}>
* @return array<array{timestamp: string, severity: string, severityRaw: Severity, body: string, trace: string, droppedAttributeCount: int}>
*/
private function formatEntries(array $entries) : array
{
Expand All @@ -245,12 +291,19 @@ private function formatEntries(array $entries) : array
$trace = \mb_substr($entry->spanContext->traceId->toHex(), 0, 8) . '/' . \mb_substr($entry->spanContext->spanId->toHex(), 0, 8);
}

$timestamp = $entry->timestamp->format('Y-m-d H:i:s.u');

if ($this->options->showObservedTimestamp && $entry->record->observedTimestamp !== null) {
$timestamp .= ' (obs: ' . $entry->record->observedTimestamp->format('H:i:s.u') . ')';
}

$formatted[] = [
'timestamp' => $entry->timestamp->format('Y-m-d H:i:s.u'),
'timestamp' => $timestamp,
'severity' => $entry->record->severity->name,
'severityRaw' => $entry->record->severity,
'body' => $body,
'trace' => $trace,
'droppedAttributeCount' => $entry->droppedAttributeCount,
];
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace Flow\Telemetry\Provider\Console;

final readonly class ConsoleLogOptions
{
public function __construct(
public bool $showResourceAttributes = true,
public bool $showInstrumentationScope = true,
public bool $showObservedTimestamp = false,
public bool $showDroppedAttributeCount = false,
) {
}

public static function default() : self
{
return new self();
}

public static function minimal() : self
{
return new self(
showResourceAttributes: false,
showInstrumentationScope: false,
showObservedTimestamp: false,
showDroppedAttributeCount: false,
);
}

public function withDroppedAttributeCount(bool $show = true) : self
{
return new self($this->showResourceAttributes, $this->showInstrumentationScope, $this->showObservedTimestamp, $show);
}

public function withInstrumentationScope(bool $show = true) : self
{
return new self($this->showResourceAttributes, $show, $this->showObservedTimestamp, $this->showDroppedAttributeCount);
}

public function withObservedTimestamp(bool $show = true) : self
{
return new self($this->showResourceAttributes, $this->showInstrumentationScope, $show, $this->showDroppedAttributeCount);
}

public function withResourceAttributes(bool $show = true) : self
{
return new self($show, $this->showInstrumentationScope, $this->showObservedTimestamp, $this->showDroppedAttributeCount);
}
}
Loading
Loading