let
The let statement assigns a name to a value, expression, or an entire query.
You can then reference that name in the context of the same search. This allows you to write more complex queries that consist of several stages and can reuse their results.
let statements are often used together with the join and union operators.
You can also perform unions and joins by using inline subqueries.
Syntax
let Name = Expression;
Each let statement needs to end with a semicolon (;).
Arguments
- Name: String. The name to assign to the Expression. Spaces (
), and the keywordrootare not allowed. - Expression: The value to assign to the Name. Can be a single value, an expression, or an entire query.
A let variable must resolve to a scalar (such as a number or string) to be referenced in most query positions. The
exception is in in, !in, in~, and !in~ lists, where a let variable bound
to a dynamic(...) value is also allowed. For details, see Dynamic Values in in Operators.
Examples
Return no more than 1000 events.
let x = 1000;
dataset="cribl_search_sample"
| limit xFind all VPC flow logs in the cribl_search_sample Dataset that are DNS-related requests.
// returns 1 record (a scalar)
let dns = dataset="cribl_lookups" lookup_table="service_names_port_numbers" service_name="domain" transport="tcp";
dataset="cribl_search_sample" dataSource='vpcflowlogs'
| where dstport == dns.port_numberJoin internal Cribl logs related to HTTP requests with a Dataset containing HTTP status codes.
let codeMap = dataset=$vt_dummy event < 4
| extend x =
case(event == 0, dynamic({"status": 200, "text": 'OK'}),
event == 1, dynamic({"status": 308, "text": 'Redirect'}),
event == 2, dynamic({"status": 404, "text": 'Not found'}),
dynamic({"status": 500, "text": 'Internal Error'}))
| project status=x.status, statusText=x.text;
dataset="cribl_internal_logs" method status
| where isnotnull(status)
| join kind=leftouter codeMap on statusCalculate the 95th percentile of requests in the Cribl internal logs.
let num_percentile = 95;
let response_time_percentile = dataset="cribl_internal_logs" method status response_time
| summarize total=count(), response_time=percentile(response_time, num_percentile);
let long_responses = dataset="cribl_internal_logs" method status response_time
| where response_time > response_time_percentile.response_time
| summarize count=count(), maxResponseTime=max(response_time);
print strcat('There are ', long_responses.count, ' requests in the ', num_percentile, ' percentile. Total requests were: ', response_time_percentile.total, '. Highest response time was: ', long_responses.maxResponseTime, 'ms');Dynamic Values in in Operators
You can bind a let variable to a dynamic(...) array or scalar and reference it in the value list of
in, !in, in~, or !in~. This lets you build reusable allow lists and block
lists without retyping the values.
The variable must be a simple identifier (no field paths or function calls), and its value must be a dynamic(...)
literal or another let variable that resolves to a scalar literal.
Filter on a list of values stored in a let variable:
let allowedMethods = dynamic(["GET", "POST", "PUT"]);
dataset="cribl_search_sample"
| where method in (allowedMethods)Use a numeric array with !in to exclude specific status codes:
let errorStatuses = dynamic([404, 500]);
dataset="cribl_search_sample"
| where status !in (errorStatuses)Mix a let variable with literal values in the same list:
let extraMethods = dynamic(["GET"]);
dataset="cribl_search_sample"
| where method in (extraMethods, "POST", "PUT")Use case-insensitive matching with in~. The let value is lowercase, but in~ still matches uppercase field values
such as GET and POST:
let allowedMethods = dynamic(["get", "post"]);
dataset="cribl_search_sample"
| where method in~ (allowedMethods)