Skip to content

experimental: map based classifier #2

@kamilsk

Description

@kamilsk
class ActionContext
{
    public function __construct(
        public readonly Flow $flow,
        public readonly Severity $severity,
        public readonly ?bool $useErrorMessage = null,
        public readonly ?string $message = null,
        public readonly ?string $metric = null,
    ) {
    }
}



class BaseClassifier implements \OctoLab\Observer\Payload\Classifier
{
    private array $actions = [];

    public function extend(string $fqcn, ActionContext $actionContext): void
    {
        if (!class_exists($fqcn) && !interface_exists($fqcn)) {
            throw new UnknownClassnameException($fqcn);
        }

        $this->actions[$fqcn] = $actionContext;
    }

    public function classify(\Throwable $error): Type\Action
    {
        return match (true) {
            $this->extendedActionExists($error) => $this->getExtendedAction($error),
            default => new Type\Action(
                $error,
                Type\Flow::throw,
                severity: Type\Severity::Error,
                message: $error->getMessage(),
                metric: Metrics::NOT_CLASSIFIED_ERROR,
            ),
        };
    }

    private function extendedActionExists(\Throwable $error): bool
    {
        return $this->getActionContext($error) !== null;
    }

    private function getActionContext(\Throwable $error): ?ActionContext
    {
        if (isset($this->actions[$error::class])) {
            return $this->actions[$error::class];
        }

        foreach (class_implements($error) as $interfaceName) {
            if (isset($this->actions[$interfaceName])) {
                return $this->actions[$interfaceName];
            }
        }

        return null;
    }

    private function getExtendedAction(\Throwable $error): Type\Action
    {
        $actionContext = $this->getActionContext($error);

        return new Type\Action(
            $error,
            $actionContext->flow,
            $actionContext->severity,
            $actionContext->useErrorMessage ? $error->getMessage() : $actionContext->message,
            $actionContext->metric,
        );
    }
}


class DomainClassifier implements \OctoLab\Observer\Payload\Classifier
{
    public function __construct(private BaseClassifier $classifier)
    {
        $this->classifier->extend(
            DomainException\Exception::class,
            new ActionContext(
                flow: Type\Flow::ignore,
                severity: Type\Severity::Info,
                useErrorMessage: true,
                metric: Metrics::GHERKIN_PARSER_ERROR,
            ),
        );
    }

    public function classify(\Throwable $error): Type\Action
    {
        return $this->classifier->classify($error);
    }
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions