High-performance log viewer and processor that transforms logs in JSON and logfmt formats into a human-readable output. Built with efficiency in mind, it enables quick parsing and analysis of large log files with minimal overhead. Features overview Automatic Pager Integration: Automatically integrates with a pager for enhanced convenience, defaulting to less if available, but fully supporting any compatible pager…
High-performance log viewer and processor that transforms logs in JSON and logfmt formats into a human-readable output. Built with efficiency in mind, it enables quick parsing and analysis of large log files with minimal overhead.
Features overview
Automatic Pager Integration: Automatically integrates with a pager for enhanced convenience, defaulting to less if available, but fully supporting any compatible pager.
Log Streaming Mode: Enable log streaming with the -P flag, which disables the pager.
Field-Based Filtering: Filter log records by key/value pairs using the -f option, with support for hierarchical keys.
Level Filtering: Easily filter logs by level with the -l option.
Timestamp Range Filtering: Filter logs by timestamp range using the --since and --until options with intuitive formats:
RFC-3339 timestamp format.
Current configured timestamp output format (via the -t option or environment variable).
User-friendly shortcuts like today, yesterday, friday, or relative offsets such as -3h or -14d.
always: Expand all fields into structured multi-line format.
High-Speed Message Sorting: Achieve lightning-fast message sorting with automatic indexing via the -s flag.
Performs the initial scan at approximately 2 GiB/s, enabling rapid filtering by timestamp and level without re-scanning.
Efficiently handles hundreds of local files totaling hundreds of gigabytes.
Reindexes large, growing files at speeds up to roughly 10 GiB/s by skipping unmodified blocks.
Live Follow Mode: Use the -F flag for live, timestamp-sorted message updates across multiple sources, with a preview of recent messages via the --tail option.
Complex Query Support: Construct custom queries with logical conditions (AND/OR) and additional advanced filtering options.
Non-JSON Prefix Handling: Process logs with non-JSON prefixes using the --allow-prefix flag.
Timezone Flexibility: Displays timestamps in UTC by default while allowing effortless timezone switching with the -Z option or local timezone adjustments using the -L flag.
It is recommended to use Windows Terminal for better experience.
Tip 提示
To make mouse scrolling work in the less pager, set the LESS environment variable to -R --mouse.
[!IMPORTANT]
Currently, hl does not provide a built-in pager and relies on external pagers such as less.
However, the build for Windows referenced on the original download page and distributed in the WinGet package manager does not work as expected.
The authors state that they have not tested or verified this build and suggest that you use it at your own risk.
Unfortunately, this build breaks some ANSI escape sequences and does not work properly with hl and many other programs that use ANSI escape sequences for colors and styles.
It is recommended to install less from the Scoop or Chocolatey package manager.
If you are using Scoop and install hl by running scoop install hl, it already installs less automatically as a dependency. Just make sure you do not have any other conflicting installations by running where less in cmd or Get-Command less in powershell.
Displays only messages where the component field exists and has a value other than tsdb or uninteresting.
Command
hl example.log -f provider~=string
Displays only messages where the provider field contains the string sub-string.
Command
hl example.log -f 'provider!~=string'
Displays only messages where the provider field exists and does not contain the string sub-string.
Command
hl example.log -f 'request.method?!=GET'
Displays only messages where the request.method field does not exist or exists and is not equal to GET. In JSON messages, this also matches composite fields, e.g., {"request":{"method":"POST"}}.
Command
hl example.log -f 'span.[].name=sp0001'
Displays only messages where the span field is an array that contains an object with a name field equal to sp0001.
Command
hl example.log -f 'span.[1].name=sp0001'
Displays only messages where the span field is an array with at least two elements, and the element at index 1 (i.e., the second element) is an object with a name field equal to sp0001.
Performing complex queries
Command
hl my-service.log --query 'level > info or status-code >= 400 or duration > 0.5'
Displays messages that either have a level higher than info (i.e. warning or error) or have a status code field with a numeric value >= 400 or a duration field with a numeric value >= 0.5.
Command
hl my-service.log -q '(request in (95c72499d9ec, 9697f7aa134f, bc3451d0ad60)) or (method != GET)'
Displays all messages that have the ‘request’ field with one of these values, or the ‘method’ field with a value other than ‘GET’.
Command
hl my-service.log -q '.price?=3'
Displays messages where the price field equals 3 OR the price field is absent. The ? modifier after a field name includes records that don’t have that field. Without the ? modifier, filtering on a missing field will skip the record.
Command
hl my-service.log -q '.status?!=error'
Displays messages where the status field is not equal to error OR the status field is absent. This is useful to include records that may not have a status field at all.
Command
hl my-service.log -q 'exists(.price)'
Displays only messages that have the price field, regardless of its value. The exists() operator tests for field presence without any value comparison.
Command
hl my-service.log -q 'exists(msg) and msg~=warning'
Displays messages that have a msg field that exists AND contains the substring warning. This combines field existence checking with value matching.
Command
hl my-service.log -q 'not exists(.internal)'
Displays messages that do NOT have an internal field, effectively filtering out records with that field.
Wildcard characters are: * for zero or more characters and ? for a single character
Regular expression match - (match, ~~=), (not match, !~~=)
Operators with sets
Test if a value is one of the values in a set - in (v1, v2), not in (v1, v2)
Test if a value is one of the values in a set loaded from a file - in @filename, not in @filename, assuming that each element is a line in the file, which can be either a simple string or a JSON string
Test if a value is one of the values in a set loaded from stdin - in @-, not in @-
Field existence operators
Test if a field exists - exists(.field) or exist(.field) (both forms are supported)
Notes
Include Absent Modifier (?): When appending ? to a field name (e.g., .field?=value), the filter will match both:
Records where the field exists and matches the condition
Records where the field is absent (does not exist)
This is useful in logfmt or similar formats where fields may be optional. Without the ? modifier, records with a non-existent field are excluded from the results.
Special field names that are reserved for filtering by predefined fields regardless of the actual source field names used to load the corresponding value: level, message, caller and logger.
To address a source field with one of these names instead of predefined fields, add a period before its name, i.e., .level will perform a match against the “level” source field.
To address a source field by its exact name, use a JSON-formatted string, i.e. -q '".level" = info'.
To specify special characters in field values, also use a JSON-formatted string, i.e.
Displays only messages that occurred after Jun 19 11:22:33 UTC of the current year (or the previous year if the current date is less than Jun 19 11:22:33) and before yesterday midnight.
Runs without a pager in follow mode by merging messages from the outputs of these 2 commands and sorting them chronologically within a custom 500ms interval.
Command
hl -F --tail 100 app1.log app2.log app3.log
Runs without a pager in follow mode, following the changes in three log files in the current directory and sorting them chronologically at a default interval of 100ms.
Preloads 100 lines from the end of each file before filtering.
Configuration files
Configuration files are automatically loaded if found in predefined platform-specific locations.
The path to the configuration file can be overridden using the HL_CONFIG environment variable or the --config command-line option.
The order in which the configuration files are searched and loaded is as follows:
The system-wide location.
The user profile location.
The location specified by the HL_CONFIG environment variable (unless the --config option is used).
The locations specified by the --config option (can be specified multiple times).
If a configuration file is found in multiple locations, the file in each subsequent location overrides only the parameters it contains.
If HL_CONFIG or --config specifies - or an empty string, all default locations and any locations specified by previous --config options are discarded. The search for the configuration file locations starts over.
To disable loading of configuration files and use the built-in defaults, --config - can be used.
All parameters in the configuration file are optional and can be omitted. In this case, default values are used.
Using environment variable, i.e. HL_THEME=classic, overrides the value specified in configuration file.
Using command-line argument, i.e. --theme classic, overrides all other values.
Theme overlays
Theme overlays allow you to apply multiple theme modifications on top of your base theme and main configured theme, enabling compositional theming. Overlays are merged in order: @base → configured theme → overlays (in list order).
Configure overlays in your configuration file using the theme-overlays setting:
theme: "uni"
theme-overlays: ["@accent-italic"]
Overlays are regular theme files that can customize specific aspects without replacing the entire theme
Overlays are applied in the specified order, allowing fine-grained control over theme composition
Empty array [] or omitting theme-overlays means no overlays are applied
Overlay themes are typically tagged with overlay and excluded from default theme listings (use --list-themes=overlay to view them)
Selecting themes with preview
To select themes with preview fzf tool can be used like this:
$ time humanlog <example.log --color always >/dev/null
humanlog --color always < example.log > /dev/null 136.18s user 7.17s system 116% cpu 2:03.25 total
评论