Berserk Docs

Compared to Microsoft KQL

Differences between Berserk's KQL and Microsoft's Kusto Query Language

Berserk implements the Kusto Query Language (KQL) as used in Azure Data Explorer, Azure Monitor, and Microsoft Sentinel. For the most part, queries that work in Azure Data Explorer will also work in Berserk. This page lists the places where Berserk diverges — either to better fit its internals and performance model, or to add features specific to observability workloads.

Schema and Field Resolution

The biggest difference from Microsoft KQL is how Berserk handles schema.

Microsoft Kusto requires fixed schemas — every column must be defined in advance, and referencing an unknown column is an error.

Berserk stores the full original record in a special $raw column (a dynamic value). Unknown column names are automatically resolved from $raw, so you can query nested fields like resource.attributes.service.name without declaring them first. This is called permissive mode and is the default. Strict mode (matching Microsoft behavior) is available but not the default.

Time-Bounded Queries

Microsoft Kusto does not require a time filter — queries can scan entire tables.

Berserk is a time-series database, and every query must be bounded by $time. When you select a range in the Time Picker or pass --since/--until to the CLI, Berserk inserts a where $time between (<START> .. <END>) clause into your query behind the scenes. If your query already includes an explicit time filter (e.g. | where $time > ago(1h)), that takes precedence over the time picker or CLI parameters.

Implicit Result Limit

Microsoft Kusto returns up to 500,000 records by default (configurable via set truncationmaxrecords).

Berserk applies an implicit | take 2000 to queries that have no operator limiting result size. This keeps queries fast by default. To retrieve more rows, add an explicit limit — for example | take 10000, | tail 100, or any aggregation like | summarize ... that naturally bounds the output.

Null Strings

Microsoft Kusto treats null and empty string ("") as distinct values — isnull("") returns false.

Berserk treats null and empty string as identical — isnull("") returns true. Strings can be null, and isnull(mystring) will return true for both null and empty values.

String Search Performance

Microsoft Kusto recommends has over contains because has uses a term index and is significantly faster.

Berserk uses bloom filters and columnar indexing to accelerate all string search operators. While case-sensitive variants (has_cs, contains_cs, ==) are still fastest, the performance gap between has and contains is much smaller than in Microsoft Kusto.

Berserk-Specific Functions and Operators

These functions and operators are Berserk extensions that do not exist in Microsoft KQL. This table is generated from the YAML function definitions — add custom: true to a function's YAML to include it here.

NameKindDescription
annotateoperatorAdds type annotations to dynamic columns, enabling forward-flow type inference
counter_rateaggregateComputes per-second rate from OpenTelemetry cumulative counters using start_time
current_tablescalarReturns the table name for the current row. Used internally by the search operator.
derivaggregateComputes the derivative (rate of change) for a gauge metric. Unlike rate(),
extract_log_templatescalarNormalizes a string into a structural template by replacing variable tokens (numbers, UUIDs, IPs, hex values, quoted strings) with typed placeholders. Useful for grouping log messages by structure.
fieldstatsoperatorAnalyzes dynamic column values to discover field paths and their statistics,
log_template_hashscalarComputes a hash of the structural log template, for grouping similar logs without allocating the template string. Equivalent to hashing the output of extract_log_template, but with zero heap allocations.
log_template_regexscalarGenerates a regex pattern that matches log lines with the same structural template. Variable tokens (numbers, UUIDs, IPs, hex, quoted strings) are replaced with regex wildcards while literal text is preserved. The output is designed for use with `matches regex` to leverage bloom filter optimization.
otel-log-statsoperatorSingle-pass OTEL log exploration: discovers attributes and computes
rateaggregateComputes the per-second rate of change for a counter metric, handling counter
trace-findoperator**Experimental**: This operator is experimental and its semantics may change.

Datetime Precision

Microsoft Kusto works primarily with microsecond-precision datetime and timespan types.

Berserk supports nanosecond precision internally and provides additional functions for working with Unix timestamps at different precisions: unixtime_seconds_todatetime, unixtime_milliseconds_todatetime, unixtime_microseconds_todatetime, and unixtime_nanoseconds_todatetime.

Unsupported Features

The following Microsoft KQL features are not yet available in Berserk:

  • Control commands — only .show tables, .show databases, and .show table <name> schema as json are supported
  • Materialized views
  • External tables
  • Stored functions (user-defined functions via .create function)
  • Cross-cluster and cross-database queries
  • Workbooks integration

Not Yet Implemented Functions

These are standard Microsoft KQL functions that Berserk recognizes but has not yet implemented. Using them produces a helpful error message. This list is generated from the engine source code.

array_concat, array_iff, array_index_of, array_reverse, array_rotate_left, array_rotate_right, array_shift_left, array_shift_right, array_slice, array_sort_asc, array_sort_desc, array_split, array_sum, bag_has_key, bag_merge, bag_pack_columns, bag_set_key, beta_cdf, beta_inv, beta_pdf, bitset_count_ones, column_ifexists, current_cluster_endpoint, current_database, current_principal, current_principal_details, current_principal_is_member_of, cursor_after, erf, erfc, extent_id, extent_tags, gamma, gettype, ingestion_time, jaccard_index, loggamma, max_of, min_of, next, pack_array, parse_command_line, parse_csv, percentile_array_tdigest, percentrank_tdigest, pi, prev, punycode_from_string, punycode_to_string, rand, rank_tdigest, repeat, row_cumsum, row_rank_dense, row_rank_min, series_acos, series_asin, series_atan, series_cos, series_cosine_similarity, series_decompose, series_decompose_forecast, series_dot_product, series_fit_2lines_dynamic, series_fit_line_dynamic, series_magnitude, series_product, series_sin, series_tan, set_difference, set_has_element, set_intersect, set_union, todecimal, treepath, welch_test, zip

On this page