Skip to content

Commit

Permalink
Merge pull request #238 from opcodesio/log-context-decoded
Browse files Browse the repository at this point in the history
Log Viewer now extracts the JSON context into more readable format
  • Loading branch information
arukompas authored Jul 9, 2023
2 parents 5ed339d + 0abeb0f commit 30a53d5
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 10 deletions.
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

0 comments on commit 30a53d5

Please sign in to comment.