Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log Viewer now extracts the JSON context into more readable format #238

Merged
merged 4 commits into from
Jul 9, 2023
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
4 changes: 2 additions & 2 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: run-tests

on:
push:
branches: [main, 1.x]
branches: [main, 1.x, 2.x]
pull_request:
branches: [main, 1.x]
branches: [main, 1.x, 2.x]

jobs:
test:
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "opcodesio/log-viewer",
"version": "v2.4.1",
"version": "v2.5.0",
"description": "Fast and easy-to-use log viewer for your Laravel application",
"keywords": [
"arukompas",
Expand Down
2 changes: 1 addition & 1 deletion public/app.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/app.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions public/mix-manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"/app.js": "/app.js?id=2a99c3e02b0ac95a07b0b1ee6c098c2a",
"/app.css": "/app.css?id=2d577fa607de6eeef7cfb84d3b72b864",
"/app.js": "/app.js?id=2ca3fa12f273bd645611f1acf3d81355",
"/app.css": "/app.css?id=93151d8b186ef7758df8582425ff8082",
"/img/log-viewer-128.png": "/img/log-viewer-128.png?id=d576c6d2e16074d3f064e60fe4f35166",
"/img/log-viewer-32.png": "/img/log-viewer-32.png?id=f8ec67d10f996aa8baf00df3b61eea6d",
"/img/log-viewer-64.png": "/img/log-viewer-64.png?id=8902d596fc883ca9eb8105bb683568c6"
Expand Down
6 changes: 6 additions & 0 deletions resources/js/components/LogList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@
</div>
</div>
<pre class="log-stack" v-html="highlightSearchResult(log.full_text, searchStore.query)"></pre>
<template v-if="log.contexts && log.contexts.length > 0">
<p class="mx-2 lg:mx-8 pt-2 border-t font-semibold text-gray-700 dark:text-gray-400">Context:</p>
<template v-for="context in log.contexts">
<pre class="log-stack" v-html="JSON.stringify(context, null, 2)"></pre>
</template>
</template>
<div v-if="log.full_text_incomplete" class="py-4 px-8 text-gray-500 italic">
The contents of this log have been cut short to the first {{ LogViewer.max_log_size_formatted }}.
The full size of this log entry is <strong>{{ log.full_text_length_formatted }}</strong>
Expand Down
1 change: 1 addition & 0 deletions src/Http/Resources/LogResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public function toArray($request)
'level_class' => $this->level->getClass(),
'environment' => $this->environment,
'text' => $this->text,
'contexts' => $this->contexts,
'full_text' => $this->fullText,
'full_text_incomplete' => $this->fullTextIncomplete,
'full_text_length' => $this->fullTextLength,
Expand Down
28 changes: 28 additions & 0 deletions src/Log.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class Log

public string $fullText;

public array $contexts = [];

public bool $fullTextIncomplete = false;

public int $fullTextLength;
Expand Down Expand Up @@ -103,6 +105,8 @@ public function __construct(
}

$this->fullText = trim($text);

$this->extractContextsFromFullText();
}

public function fullTextMatches(string $query = null): bool
Expand All @@ -127,4 +131,28 @@ public function url(): string
{
return route('log-viewer.index', ['file' => $this->fileIdentifier, 'query' => 'log-index:'.$this->index]);
}

public function extractContextsFromFullText(): void
{
// The regex pattern to find JSON strings.
// $pattern = '~\{(?:[^{}]|(?R))*\}~';
$pattern = '/(\{(?:[^{}]|(?R))*\}|\[(?:[^\[\]]|(?R))*\])/';

// Find matches.
preg_match_all($pattern, $this->fullText, $matches);

if (! isset($matches[0])) {
return;
}

// Loop through the matches.
foreach ($matches[0] as $json_string) {
// Try to decode the JSON string. If it fails, json_last_error() will return a non-zero value.
$json_data = json_decode($json_string, true);
if (json_last_error() == JSON_ERROR_NONE) {
$this->contexts[] = $json_data;
$this->fullText = str_replace($json_string, '', $this->fullText);
}
}
}
}
22 changes: 19 additions & 3 deletions tests/Unit/LogTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
$logText = <<<'EOF'
Example log entry for the level debug
with multiple lines of content.
{"one":1,"two":"two","three":[1,2,3]}
can contain dumped objects or JSON as well - it's all part of the contents.
EOF;
$text = '[2022-08-25 11:16:17] local.DEBUG: '.$logText;
Expand All @@ -34,6 +33,23 @@
assertEquals($logText, $log->fullText);
});

it('extracts JSON from the log text', function () {
$logText = <<<'EOF'
Example log entry for the level debug
with multiple lines of content.
{"one":1,"two":"two","three":[1,2,3]}
can contain dumped objects or JSON as well - it's all part of the contents.
EOF;
$jsonString = '{"one":1,"two":"two","three":[1,2,3]}';
$text = '[2022-08-25 11:16:17] local.DEBUG: '.$logText;

$log = new Log(0, $text, 'laravel.log', 0);

assertEquals('Example log entry for the level debug', $log->text);
assertEquals(str_replace($jsonString, '', $logText), $log->fullText);
assertEquals(json_decode($jsonString, true), $log->contexts[0]);
});

it('can understand the optional microseconds in the timestamp', function () {
$text = '[2022-08-25 11:16:17.125000] local.DEBUG: Example log entry for the level debug';

Expand Down Expand Up @@ -61,8 +77,8 @@
});

it('can handle text in-between timestamp and environment/severity', function () {
$text = '[2022-08-25 11:16:17] some additional text [] and characters // !@#$ local.DEBUG: Example log entry for the level debug';
$expectedAdditionalText = 'some additional text [] and characters // !@#$';
$text = '[2022-08-25 11:16:17] some additional text [!@#$%^&] and characters // !@#$ local.DEBUG: Example log entry for the level debug';
$expectedAdditionalText = 'some additional text [!@#$%^&] and characters // !@#$';

$log = new Log(0, $text, 'laravel.log', 0);

Expand Down
Loading