Show HN:Nerdlog——快速、多主机 TUI 日志查看器,带时间线直方图
Show HN: Nerdlog – Fast, multi-host TUI log viewer with timeline histogram

原始链接: https://github.com/dimonomid/nerdlog

Nerdlog是一款快速、远程优先的TUI日志查看器,旨在高效查询跨多个远程机器的日志,无需中心服务器。受Graylog等工具启发,它避免了臃肿,安装配置也极简。它通过SSH连接到远程主机,在远程端分析日志,仅下载相关数据,例如直方图数据和每个日志流每查询250条日志消息,并通过gzip压缩节省带宽。 主要功能包括:用于快速可视化分析的时间轴直方图;使用正则表达式的日志过滤;以及用于浏览大型日志的分页功能。Nerdlog支持多种导航方式,包括类似Vim的按键绑定和命令行界面,允许用户复制查询命令以便共享。它需要`gawk`和到远程主机的SSH连接。日志流可以通过UI或YAML文件配置,支持glob模式和自定义主机/端口/用户配置。Nerdlog提供命令行界面,允许用户通过命令行共享和加载查询,或调整设置,例如“numlines”和“timezone”。

Hacker News 最新 | 过去 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 Show HN:Nerdlog – 快速的多主机 TUI 日志查看器,带时间线直方图 (github.com/dimonomid) 15 分 dimonomid 1小时前 | 隐藏 | 过去 | 收藏 | 讨论 更多背景和技术细节,我也写在了这里:https://dmitryfrank.com/projects/nerdlog/article 加入我们 6 月 16-17 日在旧金山举办的 AI 初创公司学校! 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请 YC | 联系我们 搜索:

原文

Nerdlog is a fast, remote-first, multi-host TUI log viewer with timeline histogram and no central server. Loosely inspired by Graylog/Kibana, but without the bloat. Pretty much no setup needed, either.

It's laser-focused on being efficient while querying logs from multiple remote machines simultaneously, filtering them by time range and patterns, while also drawing a timeline histogram for quick visual insight:

Nerdlog

Primary use case: reading system logs (/var/log/messages or /var/log/syslog) from one or more remote hosts. Very efficient even on large log files (like 1GB or more).

It does support some other log formats and can use any log files, but that was the primary use case which was driving the implementation: we were having our web service backend running as systemd services on a bunch of Linux instances, printing a lot of logs, and wanted to be able to read these logs efficiently and having the timeline histogram, much like tools like Graylog have.

  • No centralized server required; nerdlog establishes an ssh connection to every node that the user wants to collect logs from, and keeps them idle in the background (although a separate server to store the log files might still help in some cases; see the Requirements and limitations sections in the article);
  • Logs are not downloaded to the local machine in full: all the log analysis is done on the remote nodes, and on each query, only the following data is downloaded from each node: up to 250 messages from every logstream (configurable), and data for the timeline histogram. It's obviously possible to paginate over the logs, to get the next bunch of messages, etc. Nerdlog then merges the responses from all nodes together, and presents to the user in a unified form;
  • Most of the data is gzipped in transit, thus saving the bandwidth as well.

Here’s a quick demo showing how Nerdlog works across four remote nodes:

Nerdlog

It might be useful to know the history to understand the project motivation and overall direction, you can read it here in the full article.

Originally hacked together in 2022 to replace painfully slow Splunk setups. Revisited in 2025 to clean it up to a certain extent, and open source it.

It's still kinda in a proof-of-concept stage though. Implemented as fast as possible, spaghetti code abounds, could be covered with more tests, a lot more features could be implemented, etc. Was only tested for real on Linux, and with Linux hosts to get the logs from.

But it works. It's pretty usable and surprisingly fast.

To build it, you need Go. Having it installed:

To install nerdlog binary to your /usr/local/bin:

Or to build and run without installing:

When you open the app (nerdlog binary), it'll show a query edit form with a few fields:

Nerdlog

Time range is self-explanatory.

Next one is "Logstreams": shortly, a logstream means one or more consecutive logfiles like /var/log/syslog, /var/log/syslog.1 etc, on a particular server accessible via ssh. If you have a server like myserver.com accessible via ssh on port 22, then the logstream to read its /var/log/syslog (or /var/log/messages) file could be:

If you need a different port and/or different log files, then a more explicit form is:

[email protected]:1234:/some/other/logfile

Multiple logstreams can be provided separated by commas, like this:

[email protected], [email protected]:1234:/some/other/logfile

Nerdlog also reads ssh config (~/.ssh/config) and can take the port, username and hostname from there. It supports globs too, so e.g. in your ssh config you have two hosts like myhost-01 and myhost-02, then instead of specifying your logstreams as myhost-01,myhost-02 it can be simply myhost-*.

Obviously though, we can't specify the log files in the ssh config, so if you need to configure a logstream for non-default log file on some host(s), you can use the nerdlog's own logstreams config file ~/.config/nerdlog/logstreams.yaml, which can look like this:

log_streams:
  myhost-01:
    hostname: actualhost1.com
    port: 1234
    user: myuser
    log_files:
      - /some/custom/logfile
  myhost-02:
    hostname: actualhost2.com
    port: 7890
    user: myuser
    log_files:
      - /some/custom/logfile

The last thing on that query form is the "Select field expression", it looks like this:

time STICKY, lstream, message, *

It only affects the presentation of the logs in the UI. The syntax somewhat resembles the SQL SELECT syntax, although a lot more limited.

The STICKY here just means that when the table is scrolled to the right, these sticky columns will remain visible at the left side.

Another supported keyword here is AS, so e.g. message AS msg is a valid syntax.

For a more extensive discussion on the logstreams and other core concepts, consider reading the Core concepts section in the article.

  • SSH access to the remote hosts is required. You can read about the related limitations and possible workarounds here: Consequences of requiring SSH access;
  • SSH agent must be running locally;
  • Gawk (GNU awk) is a requirement on the hosts, since nerlog relies on the -b option. So notably, mawk will not work. You need gawk;
  • If you're going to read system logs (those accessible via journalctl), make sure that you have rsyslog or similar system installed; otherwise, nobody is writing to these log files. Notably, on latest Fedora and Debian, rsyslog is not installed by default.

For more extensive discussion about these requirements, the consequent limitations, and possible ways to address them, see the Requirements and Limitations sections in the article.

UI consists of a few key elements:

  • Awk pattern input: just a filter for logs. Empty filter obviously means no filter, and some examples of valid filters are:

    • Simple regexp: /foo bar/
    • Regexps with complex conditions: ( /foo bar/ || /other stuff/ ) && !/baz/
  • Edit button: opens a complete query edit form discussed above.

  • Menu button: just opens a menu with a few extra items:

    • Back: Go to the previous query, just like in the browser
    • Forward: Go to the next query, just like in the browser
    • Copy query command: It's the equivalent of copying an URL in the browser, containing the link to the current logs query. See the :xc[lip] command below for more details on that.
  • Time range histogram: similarly to some web-based log viewers, like Graylog or Kibana, Nerdlog also shows a timeline histogram, so you can quickly glance at the intensiveness of the logs accordingly to the current query. It's also easy to visually select and apply timerange (using arrow / PgUp / PgDown / Home / End / Enter keys or vim-like bindings)

  • Logs table: obviously contains the actual logs. Like in the normal, old-school logs, the latest message is on the bottom. I don't know why modern web tools do it the other way around (latest message being on the top), to me it's nonsense. But let me know if you prefer it this modern way; it shouldn't be too hard to make it configurable.

    Every line shows the timestamp and the message, and it can also be scrolled to the right to show the context tags parsed from a log line.

  • Status line. On the left side, there are a few computer icons with numbers:

    • Green: number of lstreams which we're fully connected to and which are idle
    • Orange: number of lstreams which we're fully connected to and which are executing a query
    • Red: number of lstreams which we're trying to connect to

    And on the right side, there are 3 numbers like 1201 / 1455 / 2948122. The rightmost number (2948122) is the total number of log messages that matched the query and the timerange (and included in the timeline histogram above). The next number (1455) is the number of actual log lines currently loaded in the nerdlog app, and the leftmost (1201) is just the cursor within those available logs.

  • Command line: Vim-like command line. Hit : to enter command mode.

There are multiple ways to navigate the app, and you can mix them as you wish.

The most conventional one is to just use Tab and Shift+Tab to switch between widgets (logs table, query input, Edit and Menu buttons, timeline histogram), arrows and keys like Home / End / PgUp / PgDn to move around within a widget, Enter to apply things, Escape to cancel things.

If you know Vim though, you'll feel right at home in nerdlog too since it supports a bunch of Vim-like keybindings:

  • Keys h, j, k, l, g, G, Ctrl+U, Ctrl+D, etc move cursor whenever you're not in some text-editing field, like query input or others
  • Hitting Escape eventually brings you to the "Normal mode", which means that the logs table is focused (and all of those h, j, k, l, etc work there)
  • : focuses the command line where you can input some commands (see below)
  • i or a focuses the main query input field

When in an input field (command line, query input, etc), you can go through input history using Up / Down or Ctrl+P / Ctrl+N.

In the query edit form (the Edit button on the UI, or the :e[dit] command), the Ctrl+K / Ctrl+J iterates "full" query history (affecting not only one field like query, but all of them: time range, logstreams filter, query).

In addition to the UI which is self-discoverable, there is a vim-like command line with a few commands supported.

:xc[lip] Copies to clipboard a command string which would open nerdlog with the current logstreams filter, time range and query. This can be done from the Menu too (Menu -> Copy query command)

This is the equivalent of URL sharing for web-based logging tools: when you'd normally copy the graylog URL and paste it in slack somewhere, with nerdlog you can do the same by sharing this string.

The string would look like this:

nerdlog --lstreams 'localhost' --time -3h --pattern '/something/'

And it can be used in either the shell (which would open a new instance of nerdlog), OR it can also be used in a currently running nerdlog instance: just type : to go to the command mode, copypaste this command above, and nerdlog will parse it and apply the query.

:back or :prev Go to the previous query, just like in the browser. This can be done from the Menu too (Menu -> Back)

:fwd or :next Go to the next query, just like in the browser. This can be done from the Menu too (Menu -> Forward)

:e[dit] Open query edit form; you can do the same if you just use Tab to navigate to the Edit button in the UI.

:w[rite] [filename] Write all currently loaded log lines to the filename. If filename is omitted, /tmp/last_nerdlog is used.

:reconnect Reconnect to all logstreams

:disconnect Disconnect from all logstreams

:set option=value Set option to the new value

:set option? Get current value of an option

Currently supported options are:

  • numlines: the number of log messages loaded from every logstream on every request. Default: 250.
  • timezone: the timezone to format the timestamps on the UI. By default, Local is used, but you can specify UTC or America/New_York etc.

:q[uit] Quit the app.

Check out the Nerdlog article for more in-depth look at the core concepts, limitations and workarounds, and implementation details.

联系我们 contact @ memedata.com