Merge pull request #4512 from philipheinser/logs-for-tasks
Logs for tasks
This commit is contained in:
@@ -24,6 +24,14 @@ class Executions extends Component
|
|||||||
#[Locked]
|
#[Locked]
|
||||||
public ?string $serverTimezone = null;
|
public ?string $serverTimezone = null;
|
||||||
|
|
||||||
|
public $currentPage = 1;
|
||||||
|
|
||||||
|
public $logsPerPage = 100;
|
||||||
|
|
||||||
|
public $selectedExecution = null;
|
||||||
|
|
||||||
|
public $isPollingActive = false;
|
||||||
|
|
||||||
public function getListeners()
|
public function getListeners()
|
||||||
{
|
{
|
||||||
$teamId = Auth::user()->currentTeam()->id;
|
$teamId = Auth::user()->currentTeam()->id;
|
||||||
@@ -54,16 +62,79 @@ class Executions extends Component
|
|||||||
public function refreshExecutions(): void
|
public function refreshExecutions(): void
|
||||||
{
|
{
|
||||||
$this->executions = $this->task->executions()->take(20)->get();
|
$this->executions = $this->task->executions()->take(20)->get();
|
||||||
|
if ($this->selectedKey) {
|
||||||
|
$this->selectedExecution = $this->task->executions()->find($this->selectedKey);
|
||||||
|
if ($this->selectedExecution && $this->selectedExecution->status !== 'running') {
|
||||||
|
$this->isPollingActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function selectTask($key): void
|
public function selectTask($key): void
|
||||||
{
|
{
|
||||||
if ($key == $this->selectedKey) {
|
if ($key == $this->selectedKey) {
|
||||||
$this->selectedKey = null;
|
$this->selectedKey = null;
|
||||||
|
$this->selectedExecution = null;
|
||||||
|
$this->currentPage = 1;
|
||||||
|
$this->isPollingActive = false;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$this->selectedKey = $key;
|
$this->selectedKey = $key;
|
||||||
|
$this->selectedExecution = $this->task->executions()->find($key);
|
||||||
|
$this->currentPage = 1;
|
||||||
|
|
||||||
|
// Start polling if task is running
|
||||||
|
if ($this->selectedExecution && $this->selectedExecution->status === 'running') {
|
||||||
|
$this->isPollingActive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function polling()
|
||||||
|
{
|
||||||
|
if ($this->selectedExecution && $this->isPollingActive) {
|
||||||
|
$this->selectedExecution->refresh();
|
||||||
|
if ($this->selectedExecution->status !== 'running') {
|
||||||
|
$this->isPollingActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadMoreLogs()
|
||||||
|
{
|
||||||
|
$this->currentPage++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLogLinesProperty()
|
||||||
|
{
|
||||||
|
if (! $this->selectedExecution) {
|
||||||
|
return collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $this->selectedExecution->message) {
|
||||||
|
return collect(['Waiting for task output...']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$lines = collect(explode("\n", $this->selectedExecution->message));
|
||||||
|
|
||||||
|
return $lines->take($this->currentPage * $this->logsPerPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function downloadLogs()
|
||||||
|
{
|
||||||
|
return response()->streamDownload(function () {
|
||||||
|
echo $this->selectedExecution->message;
|
||||||
|
}, 'task-execution-'.$this->selectedExecution->id.'.log');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasMoreLogs()
|
||||||
|
{
|
||||||
|
if (! $this->selectedExecution || ! $this->selectedExecution->message) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$lines = collect(explode("\n", $this->selectedExecution->message));
|
||||||
|
|
||||||
|
return $lines->count() > ($this->currentPage * $this->logsPerPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function formatDateInServerTimezone($date)
|
public function formatDateInServerTimezone($date)
|
||||||
|
|||||||
@@ -1,4 +1,17 @@
|
|||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4" x-data="{
|
||||||
|
init() {
|
||||||
|
let interval;
|
||||||
|
$wire.$watch('isPollingActive', value => {
|
||||||
|
if (value) {
|
||||||
|
interval = setInterval(() => {
|
||||||
|
$wire.polling();
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
if (interval) clearInterval(interval);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}">
|
||||||
@forelse($executions as $execution)
|
@forelse($executions as $execution)
|
||||||
<a wire:click="selectTask({{ data_get($execution, 'id') }})" @class([
|
<a wire:click="selectTask({{ data_get($execution, 'id') }})" @class([
|
||||||
'flex flex-col border-l-2 transition-colors p-4 cursor-pointer',
|
'flex flex-col border-l-2 transition-colors p-4 cursor-pointer',
|
||||||
@@ -23,9 +36,29 @@
|
|||||||
</a>
|
</a>
|
||||||
@if (data_get($execution, 'id') == $selectedKey)
|
@if (data_get($execution, 'id') == $selectedKey)
|
||||||
<div class="p-4 mb-2 bg-gray-100 dark:bg-coolgray-200 rounded">
|
<div class="p-4 mb-2 bg-gray-100 dark:bg-coolgray-200 rounded">
|
||||||
@if (data_get($execution, 'message'))
|
@if (data_get($execution, 'status') === 'running')
|
||||||
|
<div class="flex items-center gap-2 mb-2">
|
||||||
|
<span>Task is running...</span>
|
||||||
|
<x-loading class="w-4 h-4" />
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@if ($this->logLines->isNotEmpty())
|
||||||
<div>
|
<div>
|
||||||
<pre class="whitespace-pre-wrap">{{ data_get($execution, 'message') }}</pre>
|
<pre class="whitespace-pre-wrap">
|
||||||
|
@foreach ($this->logLines as $line)
|
||||||
|
{{ $line }}
|
||||||
|
@endforeach
|
||||||
|
</pre>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
@if ($this->hasMoreLogs())
|
||||||
|
<x-forms.button wire:click.prevent="loadMoreLogs" isHighlighted>
|
||||||
|
Load More
|
||||||
|
</x-forms.button>
|
||||||
|
@endif
|
||||||
|
<x-forms.button wire:click.prevent="downloadLogs" isHighlighted>
|
||||||
|
Download
|
||||||
|
</x-forms.button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
<div>No output was recorded for this execution.</div>
|
<div>No output was recorded for this execution.</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user