The log direction. Top down or bottom up. And could also add another button for timestamps. I mean the data is there anyway, it's just how it is presented through Javascript and the browser.
Some code is needed to reverse sort the log lines...
Edit: the code nicely segfaulted logd
Thu Jan 9 17:49:41 2025 kern.info kernel: [17806.965809] Code: 48 01 45 08 eb 10 48 89 ee 4c 89 ff 4c 89 f5 e8 30 fc ff ff eb 9f 48 8b 83 b0 00 00 00 48 85 c0 74 08 44 89 e6 48 89 df ff d0 <80> bb e2 00 00 00 00 74 17 45 85 e4 74 12 83 7b 58 00 75 0c 48 8d
Thu Jan 9 17:49:41 2025 kern.info kernel: [17806.917414] logd[1315]: segfault at 7f23d33e7902 ip 00007f23d34d506c sp 00007ffcdcac35d0 error 4 in libubox.so.20240329[7f23d34d2000+7000] likely on CPU 0 (core 0, socket 0)
No, that is what I meant. It's all just client side business in the browser. Just visuals. There is no need to change anything in the system.
Edit: Haha, okay. I didn't know how ugly it actually looks. Textarea with its own vertical scrollbar, that's stuck to the bottom of the textarea and not the viewport.
No virtual line breaks.
No syntax highlighting - at least timestamp, log source. Bonus for mac addresses, ip addresses and such.
Ouch. I think I can fix that, if someone cares.
Edit: Just a question of how much it is allowed to cost, in terms of KB added to the package.
Hi,
Could you explain how you got it to work ?
I tried replacing the file and it still didn't change anything.
As for the features I think I'd put these in
toggle log order
toggle display of timestamps
toggle display severity string (daemon.info)
colorized based on severity
colorize syntax (MAC, IP, domains)
filter by severity level (info warn etc..)
include/exclude (and or not) subsystem (kernel, daemon etc.)
include/exclude (and or not) list process by name/processid (hostapd ddns-scripts dnsmasq-dhcp etc.. )
include/exclude (and or not) list any line containing string
auto update at interval (3 second default) without page reloads
make MAC/IP/domains clickable to copy
I think if it grows the file more than a few kb, then it could go in luci-syslog-viewer-upgrade instead being part of base
You either need to clear your cache, or check the "disable cache" option in developer tools-> network window.
This would basically require to parse all the log entries coming from the log. But since we get them all anyway, we have the resources of the client browser / machine.
- toggle log order -- just reverse the array, its there anyway in the code
- toggle display of timestamps -- bit more work, because actually need to parse each line into segments
- toggle display severity string (daemon.info) -- basically free with the work before
- filter by severity level (info warn etc..) -- partially done with the work before, just need a UI element(s)
- colorized based on severity -- partially done with the work before, need to rework output completely though, from textarea to modern approach (divs probably)
- colorize syntax (MAC, IP, domains) -- builds on the before, just needs the right pattern matching and some css for coloring
- include/exclude (and or not) subsystem (kernel, daemon etc.) -- could also work with the work done for task 2, hard part is figuring out a UI that doesn't have 1000 buttons
- include/exclude (and or not) list process by name/processid (hostapd ddns-scripts dnsmasq-dhcp etc.. ) -- could also work like above, hard part again is a usable UI
- include/exclude (and or not) list any line containing string -- much easier than the two above, but same tech. and just one input field with a toggle for include/exclude
- auto update at interval (3 second default) without page reloads -- mine doesn't do page reloads on SNAPSHOT
- make MAC/IP/domains clickable to copy -- bit more work, but pattern matching and some html should work, JS to clipboard is a bit ugly
That would have been me
About your big list of features, Have a look at syslog-ng
package, does almost everything that you want, in terms of filtering, adapting time stamps etc.
Auto refresh has been added already https://github.com/openwrt/luci/pull/7101.
Reversing the log order I would not support, it is just too different from how all logs on linux work. It is super confusing especially if people start removing time stamps and posting logs on this forum.
I dont get the point about the MAC/IP/domains clickable. You can just select the text and copy. How often do you need this anyway?
But it's not how normal people work. They expect the new stuff at the top, because it's new.
And if it's a toggle, why care?
The issue is that the viewport is not auto following. That it uses a textarea. Vertical scrolling. All bad UX stuff.
Also the question shouldn't be "why do you need it?", that's really bad. Just because you don't understand or share their needs, doesn't mean they are wrong.
The question instead should be "how many others need this as well?".
That is very much not the case.
Consider text on a page. You do not read from the end to the beginning.
You read the page from the beginning (top) to the end (bottom).
Typing this reply, each new line is at the bottom.
etc. etc.
I am always debugging by reading logs. Looking for a sequence usually.
Here is an example of odhcp6c output:
Sat Jan 11 19:37:31 2025 daemon.notice odhcp6c[2572]: Starting REQUEST transaction (timeout 4294967295s, max rc 10)
Sat Jan 11 19:37:31 2025 daemon.notice odhcp6c[2572]: Send REQUEST message (elapsed 0ms, rc 0)
Sat Jan 11 19:37:31 2025 daemon.notice odhcp6c[2572]: Got a valid REPLY after 14ms
Having to read it bottom up would be a PITA.
So no, reading upside down is not what normal people do at all....
I wrote that already: It is super confusing especially if people start removing time stamps and posting logs on this forum.
yep
It's not about reading. It's about having the new information at the top.
A simple JS autoscroller would probably solve the issue they actually have before they went into suggesting a solution.
The annoying part of the currently implementation is, that you have to scroll to the bottom to get the latest information.
you make it seem like everywhere on the planet all new information is at the top...
Im not that annoyed, 1 click is fine for me, but im also fine with an autoscroller especially if it is behind a checkmark which is saved.
But that is very much NOT normal.
Ok, may be so, BUT if syslogs mean anything to a user then they should be using an ssh terminal session and running logread with its various options.
Luci is a gui interface for the not so technical users to get going. It also helps with the learning curve for newcomers to get started.
Having a "window" into syslog displayed upside down will help no-one.
We're not talking about changing the default to reversed orientation.
Just a checkbox to toggle it.
This is why email replies also show the latest reply at the top.
We're never making the user scroll down to find the latest information.
Another approach would be to have the log in a textbox the size of the current display screen, that is already pre-scrolled to the end.
I think that's a good way to avoid the crazy idea of having the new stuff at the top which is so crazy it could make some people's head explode !
upside down, I should have done this years ago.
I can't believe how good it feels to have my mind
now, looking forward (sic) to how it used to be in the past,
something happened inside my head and
quite hard work, but very quickly
but I persevered. It started off being
it seemed to be very strange...
so I sat down and gave it a go. To begin with
at the top too. I don't like being accused of not liking new ideas,
I used to think it was a crazy idea to have new things
This is comment art, thank you so much
I played with GitHub Copilot for an hour. (And another half hour because I couldn't override the file in my browser directly at first).
Added a bit more than 2KB, but this is unoptimized and includes the new CSS, which can mostly be replaced by existing bootstrap
/ cbi
classes.
Just a proof of concept, that those changes can be added easily. If there is enough interest, I can make a proper PR for it.
PS. Claude chose the colors. Don't blame me
PPS. Another toggle could be to hide personal data for screenshots
"use strict";
"require view";
"require fs";
"require poll";
"require ui";
return L.view.extend({
handleSaveApply: null,
handleSave: null,
handleReset: null,
logReversed: true, // Add state for log order
parseLogLine: function (line) {
const match = line.match(
/^(\w+\s+\w+\s+\d+\s+\d+:\d+:\d+)\s+([^.]+)\.(\w+)\s+([^\[:\s]+(?:\[\d+\])?): (.*)$/
);
return match
? {
timestamp: match[1],
facility: match[2],
severity: match[3],
process: match[4],
message: match[5],
}
: { message: line };
},
highlightSyntax: function (text) {
return text
.replace(
/\b([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}\b/g,
'<span class="mac-address">$&</span>'
)
.replace(
/\b(?:\d{1,3}\.){3}\d{1,3}\b/g,
'<span class="ip-address">$&</span>'
)
.replace(
/\b(?:[a-z0-9]+\.)+[a-z]{2,}\b/gi,
'<span class="domain-name">$&</span>'
);
},
load: function () {
return Promise.all([
L.resolveDefault(fs.stat("/usr/libexec/syslog-wrapper"), null),
]).then((stat) => {
return this.retrieveLog();
});
},
retrieveLog: function () {
return L.resolveDefault(fs.stat("/usr/libexec/syslog-wrapper"), null).then(
function (stat) {
var logger = stat.path;
return fs
.exec_direct(logger)
.then((logdata) => {
return logdata.trim().split(/\n/);
})
.catch(function (err) {
ui.addNotification(
null,
E("p", {}, _("Unable to load log data: " + err.message))
);
return [];
});
}
);
},
render: function (loglines) {
// Inject CSS on first render
if (!document.getElementById("syslog-style")) {
const style = E("style", { id: "syslog-style" });
style.textContent = `
.log-container { font-family: Cascadia Code, monospace; font-size: 12px; background: #fff; padding: 10px; border: 1px solid #ccc; height: 500px; overflow-y: auto; }
.log-line { padding: 2px 0; white-space: pre-wrap; }
.log-timestamp { color: #666; margin-right: 10px; }
.log-facility { color: #555; margin-right: 4px; }
.log-severity { padding: 1px 5px; border-radius: 3px; margin-right: 10px; }
.log-severity.debug { background: #e9ecef; }
.log-severity.info { background: #d1ecf1; }
.log-severity.notice { background: #fff3cd; }
.log-severity.warning { background: #fff3cd; color: #856404; }
.log-severity.err, .log-severity.error { background: #f8d7da; color: #721c24; }
.log-process { color: #0056b3; margin-right: 10px; }
.log-message { color: #212529; }
.mac-address, .ip-address, .domain-name { background: #f8f9fa; padding: 1px 3px; border-radius: 2px; cursor: pointer; }
.mac-address:hover, .ip-address:hover, .domain-name:hover { background: #e9ecef; }
`;
document.head.appendChild(style);
}
const logContainer = E("div", {
id: "syslog",
class: "log-container",
});
this.updateLogDisplay(logContainer, loglines);
poll.add(L.bind(this.pollLog, this));
return E("div", { id: "content_syslog" }, [
E("h2", {}, [_("System Log")]),
E("div", { class: "cbi-section" }, [
E("div", { class: "cbi-section-node" }, [
E("div", { class: "cbi-value" }, [
E("label", { class: "cbi-value-title" }, _("Log Order")),
E("div", { class: "cbi-value-field" }, [
E(
"button",
{
class: "btn",
click: (ev) => {
this.logReversed = !this.logReversed;
ev.target.textContent = this.logReversed
? _("Newest First")
: _("Oldest First");
this.pollLog();
},
},
this.logReversed ? _("Newest First") : _("Oldest First")
),
]),
]),
]),
]),
logContainer,
]);
},
pollLog: function () {
const element = document.getElementById("syslog");
if (element) {
this.retrieveLog().then((loglines) => {
this.updateLogDisplay(element, loglines);
});
}
},
updateLogDisplay: function (container, loglines) {
let displayLines = this.logReversed ? [...loglines].reverse() : loglines;
let html = "";
for (let line of displayLines) {
const parsed = this.parseLogLine(line);
html += `<div class="log-line">`;
if (parsed.timestamp) {
html += `<span class="log-timestamp">${parsed.timestamp}</span>`;
html += `<span class="log-facility">${parsed.facility}</span>`;
html += `<span class="log-severity ${parsed.severity.toLowerCase()}">${
parsed.severity
}</span>`;
html += `<span class="log-process">${parsed.process}</span>`;
}
html += `<span class="log-message">${this.highlightSyntax(
parsed.message
)}</span>`;
html += "</div>";
}
container.innerHTML = html;
},
});
Not just email. Anything. News, at the top. Reddit, new at the top. Twitter, new at the top. LinkedIn, new at the top. Instagram. New at the top. It makes no sense to scroll down. That's probably legacy from they had no screen but just endless paper printers. But even the one I remember had the new lines at the top, but I might remember wrong.
You can open a PR on the LuCI repo but some quick pointers (I'm one of the most active maintainers atm), there's alot of weird stuff going on in that code:
- The added CSS needs to be theme compatible; this will need to work both in light- and dark mode for all themes if you're modifying a core component of LuCI. An option is to delete it all together and just use the current CSS.
- Don't modify the content itself that comes from the log (
parsed.severity.toLowerCase()
as an example) so there's parity between them - Duplicated code (specifically the invocation of
fs.stat("/usr/libexec/syslog-wrapper
) - Duplicated i18n strings
- Depending on size of configured log, the invocation of
[...loglines].reverse()
may increase runtime considerably due to being O(n) + O(n) added time complexity compared to the current code, you need to test this with a reasonable valid input forSystem log buffer size
inSystem
->System Properties
. - Where did the
Scroll to tail
andScroll to head
buttons go? Or is the reasoning that they won't be needed anymore? - I'm not a fan of the unreadable regex, it's bordering on being unmaintainable, especially if
highlightSyntax
needs to be fixed/extended
Thanks, but this was the most important part of my post you missed, which made you waste a lot of time on your reply:
and also this
I like that you are the first frontend developer to actually care about performance (and know the O notation), but with even smartphones having 10-100x the performance of an average Openwrt device and the log page not being a primary business function, I'd say yes, but no.
But now that you mentioned it, I wasted some more time on this. flex-direction: column-reversed
(or similar). No need to touch the log array.