angle-grinder

repository·main·Indexed 26 days ago

https://github.com/rcoh/angle-grinder

A high-performance command-line tool (agrind) for parsing and aggregating log files. It features a functional query language with filters and operators for real-time data analysis, supporting JSON and logfmt extraction, regex parsing, and various aggregation functions (sum, average, percentiles). It can process over 1M rows per second and provides a live-updating terminal UI.

Tokens
9.8K
Snippets
23
Records
80
Agent score
84%

What's inside angle-grinder

  1. Overview of angle-grinder

    main
    angle-grinder (agrind) is a command-line tool designed to slice and dice log files. It allows for high-performance parsing, aggregation (sum, average, min/max, percentile, etc.), and sorting of data directly in your terminal with a live-updating UI. It is capable of processing over 1M rows per second, making it suitable for large-scale data analytics when traditional observability platforms are unavailable.
  2. Understand angle-grinder query syntax

    main

    An angle-grinder query consists of filters followed by a series of operators separated by pipes (|).

    1. Filters: Select lines from the input stream. Only lines matching all filters are passed to operators.
    2. Operators: Transform the data. Initial operators typically parse fields or JSON. Subsequent operators can aggregate or group data (e.g., sum, average).

    Basic structure:

    agrind '<filter1> [... <filterN>] | operator1 | operator2 | operator3 | ...'
    agrind '* | json | count by log_level'
  3. Install angle-grinder

    main

    You can install agrind using various package managers depending on your operating system. The resulting binary is named agrind. Starting from v0.9.0, you can update the binary using the --self-update flag.

    ### macOS
    
    **Brew**
    ```bash
    brew install angle-grinder

    Macports

    sudo port selfupdate
    sudo port install angle-grinder

    FreeBSD

    pkg install angle-grinder

    Linux (any MUSL compatible variant)

    curl -L https://github.com/rcoh/angle-grinder/releases/download/v0.18.0/agrind-x86_64-unknown-linux-musl.tar.gz \
      | tar Ozxf - \
      | sudo tee /usr/local/bin/agrind > /dev/null && sudo chmod +x /usr/local/bin/agrind
    
    agrind --self-update

    Cargo (most platforms)

    cargo install ag
  4. Configure and use Aliases

    main

    Aliases allow you to use pre-built pipelines for common tasks or formats.

    Angle-grinder looks for an .agrind-aliases directory in your current working directory or any parent directories. Alias files use TOML format.

    Example Alias File (.agrind-aliases/apache.toml):

    keyword = "apache"
    template = """
    parse "* - * [*] \"* * *\" * *" as ip, name, timestamp, method, url, protocol, status, contentlength
    """

    Usage:

    agrind '* | apache | count by status
  5. Define and add new aliases

    main

    Aliases allow you to replace a specific keyword with a predefined pipeline of operators. To add a new alias to the project's built-in collection:

    1. Create a new file in the aliases directory.
    2. Name the file the exact string you want to be replaced (the keyword).
    3. Inside the file, provide a TOML configuration containing the keyword and the template (the pipeline to be used as the replacement).

    Example alias file content (my-alias.toml):

    keyword = "my-alias"
    template = "field | stats count"
  6. Use logical operators in queries

    main

    Angle-grinder supports logical operators to combine search terms or field expressions. You can use AND (or &&) and OR (or ||) to build complex search logic. These can be used in the search part of the query or within field expressions.

    Examples:

    • abc AND def or abc def (implicit AND)
    • (abc AND def) OR xyz
    • k1&&k2&&k3 and k4 as value
    (abc AND def) OR xyz
    * | k1&&k2&&k3 and k4 as value
  7. Use arithmetic and comparison operators in field expressions

    main

    You can perform arithmetic and comparison operations on fields within a pipe expression.

    Arithmetic Operators:

    • + (Add)
    • - (Subtract)
    • * (Multiply)
    • / (Divide)

    Comparison Operators:

    • > (Gt)
    • < (Lt)

    Example: * | k1 + 0 > 2 or k3 > 4 and k5 < 6 as value

    * | k1 + 0 > 2 or k3 > 4 and k5 < 6 as value
  8. Parse text with `parse` and `parse regex`

    main

    parse "<pattern>" [from field] as a,b,c [nodrop] [noconvert]

    Matches text patterns using * (greedy, equivalent to .*).

    • nodrop: Keeps lines that don't match.
    • noconvert: Keeps parsed fields as strings instead of attempting structured data conversion.

    parse regex "<regex>" [from field] [nodrop]

    Matches text using Rust regular expression syntax with named captures.

    • Requirement: Only named captures are supported; unnamed captures will cause an error.
    • nodrop: Keeps lines that don't match.
  9. Split fields with the `split` operator

    main

    The split[(input_field)] [on separator] [as new_field] operator splits input into an array.

    • Default separator: , (comma).
    • Default target: If no input_field or new_field is provided, the result is stored in the _split key.
    • Behavior: If input_field is used without new_field, the original field is overridden with the new array.
  10. Sort and Timeslice aggregate data

    main

    sort by a, [b, c] [asc|desc]

    Sorts aggregate data by columns or expressions. Defaults to asc.

    timeslice(<timestamp>) <duration> [as <field>]

    Truncates a timestamp to a specific duration to partition data into time slices.

    Supported Durations: ns, us, ms, s, m, h, d, w.

    Example:

    agrind '* | json | timeslice(parseDate(ts)) 5m
  11. Extract JSON data with the `json` operator

    main

    The json [from other_field] operator extracts JSON-serialized rows into fields. If a row is not valid JSON, it is dropped.

    • Supports nested structures via dot notation (e.g., .key[index]).
    • Supports negative indexing.
    • Optionally specify a field to parse JSON from using from <field>.
  12. Aggregate data with Aggregate Operators

    main

    Aggregate operators group and combine data using the syntax: (operator [as renamed_column])+ [by key_col1, key_col2].

    Available Operators:

    • count[(condition)] [as col]: Counts rows (optionally filtered by condition).
    • sum(column) [as col]
    • min(column) [as col]
    • average(column) [as col]
    • max(column) [as col]
    • pXX(column): Calculates the XXth percentile (e.g., p50, p90).
    • count_distinct(column): Counts unique values (Warning: high memory usage).
    • total(column) [as col]: Computes a running total (does not support grouping).