Initial commit
This commit is contained in:
69
src/Client/LogDbClient.php
Normal file
69
src/Client/LogDbClient.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace LogDb\LogQuery\Client;
|
||||
|
||||
use Symfony\Component\HttpClient\HttpClient;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
class LogDbClient
|
||||
{
|
||||
private HttpClientInterface $client;
|
||||
|
||||
public function __construct(
|
||||
string $server,
|
||||
?string $token = null,
|
||||
)
|
||||
{
|
||||
$this->client = HttpClient::createForBaseUri($server, [
|
||||
'headers' => ($token ? [
|
||||
'x-token' => $token,
|
||||
] : [])
|
||||
]);
|
||||
}
|
||||
|
||||
public function queryLogs(array $params): array
|
||||
{
|
||||
$query = http_build_query($params);
|
||||
$result = $this->client->request("GET", "/api/logdb/v1/events?{$query}");
|
||||
$body = $result->getContent();
|
||||
$json = json_decode($body);
|
||||
return $json;
|
||||
}
|
||||
|
||||
public function queryScopes(): array
|
||||
{
|
||||
$result = $this->client->request("GET", "/api/logdb/v1/scopes");
|
||||
$body = $result->getContent();
|
||||
$json = (array)json_decode($body);
|
||||
return $json;
|
||||
}
|
||||
|
||||
public function deleteScope(string $scope): void
|
||||
{
|
||||
$result = $this->client->request("DELETE", "/api/logdb/v1/scope/{$scope}");
|
||||
$body = $result->getContent();
|
||||
$json = json_decode($body);
|
||||
if ($json === false) {
|
||||
throw new \Exception("Unable to delete scope {$scope}");
|
||||
}
|
||||
}
|
||||
|
||||
public function querySources(): array
|
||||
{
|
||||
$result = $this->client->request("GET", "/api/logdb/v1/sources");
|
||||
$body = $result->getContent();
|
||||
$json = (array)json_decode($body);
|
||||
return $json;
|
||||
}
|
||||
|
||||
public function deleteSource(string $source): void
|
||||
{
|
||||
$result = $this->client->request("DELETE", "/api/logdb/v1/source/{$source}");
|
||||
$body = $result->getContent();
|
||||
$json = json_decode($body);
|
||||
if ($json === false) {
|
||||
throw new \Exception("Unable to delete source {$scope}");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
84
src/Command/EventCommand.php
Normal file
84
src/Command/EventCommand.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace LogDb\LogQuery\Command;
|
||||
|
||||
use LogDb\LogQuery\Client\LogDbClient;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
#[AsCommand(name:"events", description:"Query events")]
|
||||
class EventCommand extends Command
|
||||
{
|
||||
public function __construct(private readonly LogDbClient $client)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->addOption("short", "S", InputOption::VALUE_NONE, "Only produce one line of output for every event")
|
||||
->addOption("detail", "d", InputOption::VALUE_NONE, "Include extra detail (if not short output)")
|
||||
->addOption("json", "j", InputOption::VALUE_NONE, "Dump events as JSON")
|
||||
->addOption("scope", "s", InputOption::VALUE_REQUIRED, "Query events in scope")
|
||||
->addOption("source", "r", InputOption::VALUE_REQUIRED, "Query events with source")
|
||||
->addOption("limit", "l", InputOption::VALUE_REQUIRED, "Set number of results", 25)
|
||||
->addOption("level", "L", InputOption::VALUE_REQUIRED, "Minimum level of event to return");
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$params = [
|
||||
'count' => intval($input->getOption('limit')),
|
||||
'scope' => $input->getOption("scope"),
|
||||
'source' => $input->getOption("source"),
|
||||
'level' => $input->getOption("level"),
|
||||
];
|
||||
$events = $this->client->queryLogs($params);
|
||||
|
||||
if ($input->getOption("json")) {
|
||||
$output->writeln(\json_encode($events, \JSON_PRETTY_PRINT|\JSON_UNESCAPED_SLASHES));
|
||||
} elseif ($input->getOption("short")) {
|
||||
$this->dumpShort($output, $events);
|
||||
} else {
|
||||
$detail = $input->getOption("detail");
|
||||
$this->dumpLong($output, $events, $detail);
|
||||
}
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
private function dumpShort(OutputInterface $output, array $events): void
|
||||
{
|
||||
$batchId = null;
|
||||
foreach ($events as $event) {
|
||||
if ($batchId && $batchId == ($event->batch ?? null)) {
|
||||
$head = "\u{251c}\u{2574}";
|
||||
} elseif ($event->batch ?? null) {
|
||||
$head = "\u{250c}\u{2500}";
|
||||
} else {
|
||||
$head = " ";
|
||||
}
|
||||
$batchId = $event->batch ?? null;
|
||||
$line = sprintf("%s<comment>%s</> <options=bold>%s</>: %s <fg=gray>%s</> (<info>%s</>:<fg=cyan>%s</>)", $head, $event->datetime, $event->level, $event->brief, ($event->context?json_encode($event->context,JSON_UNESCAPED_SLASHES):null), $event->scope, $event->origin);
|
||||
$output->writeln($line);
|
||||
}
|
||||
}
|
||||
|
||||
private function dumpLong(OutputInterface $output, array $events, bool $detail): void
|
||||
{
|
||||
$bar = function(int $len) { return str_repeat("\u{2500}", $len); };
|
||||
foreach ($events as $event) {
|
||||
$output->writeln($bar(3)." <options=bold>Event</> <comment>{$event->uuid}</> (<info>{$event->id}</>) ".$bar(10));
|
||||
$ev = (array)$event;
|
||||
$keys = $detail ? array_keys($ev) : [ "datetime", "level", "brief", "scope" ];
|
||||
foreach ($keys as $k) {
|
||||
$v = $ev[$k] ?? null;
|
||||
$output->writeln(sprintf(" <info>%10s</>: %s", $k, strtr(json_encode($v,JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT),["\n"=>"\n "])));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
52
src/Command/ScopeCommand.php
Normal file
52
src/Command/ScopeCommand.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace LogDb\LogQuery\Command;
|
||||
|
||||
use LogDb\LogQuery\Client\LogDbClient;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
#[AsCommand(name:"scopes", description:"Enumerate or query scopes")]
|
||||
class ScopeCommand extends Command
|
||||
{
|
||||
public function __construct(private readonly LogDbClient $client)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->addOption("delete", null, InputOption::VALUE_REQUIRED, "Delete a scope");
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
|
||||
if ($scopeToDelete = $input->getOption("delete")) {
|
||||
try {
|
||||
$this->client->deleteScope($scopeToDelete);
|
||||
return self::SUCCESS;
|
||||
} catch (\Exception $e) {
|
||||
$output->writeln("<error>{$e->getMessage()}</>");
|
||||
return self::FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
$scopes = $this->client->queryScopes();
|
||||
|
||||
$table = new Table($output);
|
||||
$table->setStyle("box");
|
||||
$table->setHeaders([ "Scope", "Events", "Latest" ]);
|
||||
foreach ($scopes as $scope) {
|
||||
$table->addRow([ $scope->name, $scope->events, $scope->latest ]);
|
||||
}
|
||||
$table->render();
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
39
src/Command/SourceCommand.php
Normal file
39
src/Command/SourceCommand.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace LogDb\LogQuery\Command;
|
||||
|
||||
use LogDb\LogQuery\Client\LogDbClient;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
#[AsCommand(name:"sources", description:"Enumerate or query sources")]
|
||||
class SourceCommand extends Command
|
||||
{
|
||||
public function __construct(private readonly LogDbClient $client)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
|
||||
$sources = $this->client->querySources();
|
||||
|
||||
$table = new Table($output);
|
||||
$table->setStyle("box");
|
||||
$table->setHeaders([ "Source", "Events", "Latest" ]);
|
||||
foreach ($sources as $source) {
|
||||
$table->addRow([ $source->name, $source->events, $source->latest ]);
|
||||
}
|
||||
$table->render();
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
22
src/LogQueryApplication.php
Normal file
22
src/LogQueryApplication.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace LogDb\LogQuery;
|
||||
|
||||
use LogDb\LogQuery\Client\LogDbClient;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
class LogQueryApplication extends Application
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct("LogQuery", "0.0.0");
|
||||
|
||||
$server = getenv("LOGQUERY_SERVER") ?: "http://127.0.0.1:7000";
|
||||
$token = getenv("LOGQUERY_TOKEN") ?: null;
|
||||
|
||||
$client = new LogDbClient($server, $token);
|
||||
$this->add(new Command\EventCommand($client));
|
||||
$this->add(new Command\ScopeCommand($client));
|
||||
$this->add(new Command\SourceCommand($client));
|
||||
}
|
||||
}
|
||||
8
src/logquery.php
Normal file
8
src/logquery.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
use LogDb\LogQuery\LogQueryApplication;
|
||||
|
||||
require_once __DIR__."/../vendor/autoload.php";
|
||||
|
||||
$app = new LogQueryApplication();
|
||||
$app->run();
|
||||
Reference in New Issue
Block a user