PantherFlow Functions

Use these functions in your PantherFlow query statements

PantherFlow is in open beta starting with Panther version 1.110, and is available to all customers. Please share any bug reports and feature requests with your Panther support team.

Aggregations

agg.avg()

agg.avg(column: any) -> float

Returns the average of the values in the aggregation.

Example:

panther_logs.public.aws_alb
| summarize agg.avg(receivedBytes) by ip_address

agg.count()

agg.count([column: any]) -> int

Returns the number of values in the aggregation.

Example:

panther_logs.public.aws_alb
| summarize agg.count() by ip_address

agg.count_distinct()

agg.count_distinct(column: any) -> int

Returns the number of unique values in the aggregation.

Example:

panther_logs.public.aws_alb
| summarize agg.count_distinct(targetStatusCode) by ip_address

agg.make_set()

agg.make_set(column: any) -> any

Returns a set of unique values from the column.

Example:

panther_logs.public.aws_alb
| summarize agg.make_set(targetStatusCode) by ip_address

agg.max()

agg.max(column: any) -> float

Returns the maximum value in the aggregation.

Example:

panther_logs.public.aws_alb
| summarize agg.max(receivedBytes) by ip_address

agg.min()

agg.min(column: any) -> float

Returns the minimum value in the aggregation.

Example:

panther_logs.public.aws_alb
| summarize agg.min(receivedBytes) by ip_address

agg.stddev()

agg.stddev(column: [number]) -> float

Returns the sample standard deviation (square root of sample variance) of non-null values.

Example:

panther_logs.public.aws_alb
| summarize agg.stddev(receivedBytes) by ip_address

agg.sum()

agg.sum(column: [any]) -> float

Returns the sum of the values in the aggregation.

Example:

panther_logs.public.aws_alb
| summarize agg.sum(receivedBytes) by ip_address

agg.take_any()

agg.take_any(column: [any]) -> any

Returns any value from the aggregation.

Example:

panther_logs.public.aws_alb
| summarize agg.take_any(targetGroupArn) by ip_address

Date/time

time.ago()

time.ago(span: timespan) -> timestamp

Returns the timestamp that is span ago.

Example:

panther_logs.public.aws_alb
| where p_event_time > time.ago(1d)

time.diff()

time.diff(unit: string, timestamp1: timestamp, timestamp2: timestamp) -> int

Calculates the difference between two timestamp expressions based on the date or time unitrequested. The function returns the result of subtracting timestamp1 from timestamp2 (i.e. timestamp2 - timestamp1).

Example:

panther_logs.public.aws_alb
| extend hoursToParse=time.diff('h', p_event_time, p_parse_time)
| extend minutesToParse=time.diff('m', p_event_time, p_parse_time)
| project hoursToParse, minutesToParse

time.now()

time.now() -> timestamp

Returns the current timestamp.

Example:

panther_logs.public.aws_alb
| where p_event_time > time.now() - 1d

time.parse_timespan()

time.parse_timespan(str: string) -> timespan

Returns the timespan representation of the duration string.

Example:

panther_logs.public.aws_alb
| where p_event_time > time.now() - time.parse_timespan('24h')

time.parse_timestamp()

time.parse_timestamp(str: string) -> timestamp

Returns the timestamp representation of the timestamp string.

Example:

panther_logs.public.aws_alb
| where p_event_time > time.parse_timestamp('2023-01-01T00:00:00')

time.slice()

time.slice(time: timestamp, slice_length: int, slice_unit: string) -> timestamp

Returns the timestamp that time resides in, given chunks of slice_unit and slice_length. For example, if slice_length is 1 and slice_unit is "hour", the time is truncated to the hour it belongs to. Slices are calculated relative to midnight January 1, 1970. slice_unit can be:

  • year, y

  • month

  • day, d

  • hour, h

  • minute, m

  • second, s

More values may be accepted, but are not guaranteed to be supported in future releases.

Example:

panther_logs.public.aws_alb
| where p_event_time > time.ago(1d)
| summarize count=agg.count() by bucket=time.slice(p_event_time, 10, 'm')
| sort bucket asc
| visualize

time.trunc()

time.trunc(unit: string, timestamp: timestamp) -> timestamp

Returns the timestamp truncated to the specified unit. unit can be:

  • year, y

  • month

  • day, d

  • hour, h

  • minute, m

  • second, s

More values may be accepted, but are not guaranteed to be supported in future releases.

Example:

panther_logs.public.aws_alb
| where p_event_time > time.ago(1d)
| extend minuteEventHappened=time.trunc('m', p_event_time)
| summarize eventsPerMinute=agg.count() by minuteEventHappened

Strings

strings.cat()

strings.cat(str: string, str: string, ... ) -> string

Concatenates strings.

Example:

panther_logs.public.aws_alb
| project clientAddr=strings.cat(clientIp, ':', clientPort)

strings.contains()

strings.contains(str: any, substr: string) -> bool

Returns true if str contains substr. If str is not a string, it is stringified first.

Example:

panther_logs.public.aws_alb
| project usingMozilla=strings.contains(userAgent, "Mozilla")

strings.ends_with()

strings.ends_with(str: string, postfix: string) -> bool

Returns true if str ends with postfix.

Example:

panther_logs.public.aws_alb
| project usingSHA256=strings.ends_with(sslCipher, "SHA256")

strings.ilike()

strings.ilike(str: any, substr: string) -> bool

Returns true if str contains substr with SQL LIKE semantics ignoring case.

Example:

panther_logs.public.aws_alb
| project usingSHA=strings.ilike(sslCipher, "%sha%")

strings.join()

strings.join(elements: [string], sep: string) -> string

Returns elements joined together with sep between each element.

Example:

panther_logs.public.aws_alb
| project same=strings.join(strings.split(domainName, "."), ".")

strings.len()

strings.len(str: any) -> int

Returns the length of str. If str is not a string, it is stringified first.

Example:

panther_logs.public.aws_alb
| project keyLen=strings.len(p_source_file.aws_s3_key)

strings.like()

strings.like(str: any, substr: string) -> bool

Returns true if str contains substr with SQL LIKE semantics.

Example:

panther_logs.public.aws_alb
| project usingSHA=strings.like(sslCipher, "%SHA%")

strings.lower()

strings.lower(str: string) -> string

Returns str converted to lower case.

Example:

panther_logs.public.aws_alb
| project action=strings.cat(strings.lower(requestHttpMethod), " a letter")

strings.split()

strings.split(str: any, sep: string) -> [string]

Returns a list of substrings of str separated by sep.

Example:

panther_logs.public.aws_alb
| project ip_parts=strings.split(clientIp, ".")

strings.starts_with()

strings.starts_with(str: string, prefix: string) -> bool

Returns true if str starts with prefix.

Example:

panther_logs.public.aws_alb
| project targetingLoadBalancer=strings.starts_with(targetGroupArn, "arn:aws:elasticloadbalancing")

strings.upper()

strings.upper(str: string) -> string

Returns str converted to upper case.

Example:

panther_logs.public.aws_alb
| project bigDomain=strings.upper(domainName)

Arrays

arrays.difference()

arrays.difference(arr: [any], excluded_arr: [any]) -> [any]

Returns an array that contains the elements from arr that are not in excluded_arr.

Example:

panther_logs.public.aws_alb
| project ips=arrays.difference(p_any_ip_addresses, p_any_trace_ids)

arrays.intersection()

arrays.intersection(arr1: [any], arr2: [any]) -> [any]

Returns an array that contains only the elements that are in both arr1 and arr2.

Example:

panther_logs.public.aws_alb
| project ips=arrays.intersection(p_any_ip_addresses, p_any_trace_ids)

arrays.len()

arrays.len(arr: [any]) -> int

Returns the length of arr. If arr is not an array it is jsonified first.

Example:

panther_logs.public.aws_alb
| project ipsFound=arrays.len(p_any_ip_addresses)

arrays.overlap()

arrays.overlap(arr1: [any], arr2: [any]) -> bool

Returns true if arr1 and arr2 have any elements in common.

Example:

panther_logs.public.aws_alb
| project tracesHadIps=arrays.overlap(p_any_ip_addresses, p_any_trace_ids)

arrays.sort()

arrays.sort(arr: [any] [, sort_asc: bool] [, nulls_first: bool]) -> [any]

Returns an array that contains the elements of the input array arr sorted in ascending or descending order. Defaults to ascending order. You can specify whether or not null elements are sorted before or after non-null elements. Defaults to nulls last in ascending order and null first in descending order.

Example:

panther_logs.public.aws_alb
| project tracesSorted=arrays.sort(p_any_trace_ids, false)

arrays.union()

arrays.union(arr1: [any], arr2: [any]) -> [any]

Returns an array that contains all deduplicated elements of arr1 and arr2.

Example:

panther_logs.public.aws_alb
| project ips=arrays.union(p_any_ip_addresses, p_any_trace_ids)

Math

math.round()

math.round(value: number [, precision: int]) -> float

Returns the value rounded to the specified precision.

Example:

panther_logs.public.aws_alb
| summarize avg=agg.avg(receivedBytes) by ip_address
| project avg=math.round(avg, 2)

Control flow

case()

case(condition1: bool, value1: any [, condition2: bool, value2: any, ... ] [, else: any]) -> any

Returns the first value for which the corresponding condition is true. If no condition is true, returns null.

Example:

panther_logs.public.aws_alb
| extend avg=toscalar(panther_logs.public.aws_alb | summarize agg.avg(receivedBytes) by clientIp)
| project bytesSize=case(receivedBytes > avg, "larger", receivedBytes < avg, "smaller", "same")

Regular expressions

re.count()

re.count(stringable: any, regex: string) -> int

Returns the number of times that regex occurs in stringable, or null if any value is null.

Example:

panther_logs.public.aws_alb
| project tripleDigitBlocks=re.count(clientIp, "[0-9][0-9][0-9]")

re.matches()

re.matches(stringable: any, regex: string) -> bool

Returns true if stringable matches the regular expression regex.

Example:

panther_logs.public.aws_alb
| project inCidr=re.matches(clientIp, '^192\\.168\\.1\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})$'), clientIp

re.replace()

re.replace(stringable: any, regex: string, replacement: string) -> string

Returns stringable with the specified pattern regex (or all occurrences of the pattern) either removed or replaced by replacement, or null if any value is null.

Example:

panther_logs.public.aws_alb
| project traceId=re.replace(connTraceId, "^(TID_)", "")

re.substr()

re.substr(stringable: any, regex: string) -> string

Returns the first substring that matches regex within stringable, or null if any value is null.

Example:

panther_logs.public.aws_alb
| project tripleDigitBlocks=re.count(clientIp, "[0-9][0-9][0-9]")

Snowflake

snowflake.func()

snowflake.func(func_name: string [, arg1: any, ... ]) -> any

Call any function in Snowflake. This function simply acts as a passthrough.

Example:

panther_logs.public.aws_alb
| project inCidr=snowflake.func("REGEXP_LIKE", clientIp, "^192\\.168\\.1\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})$")

Data types

array()

array(value1: any, value2: any, valueN: any, ... ) -> array

Returns an array with the given values.

Example:

panther_logs.public.aws_alb
| project myArray=array(receivedBytes, true, 4, "oops")

object()

object([key1: string, value1: any, ... ]) -> object

Returns an object with the given key-value pairs.

Example:

panther_logs.public.aws_alb
| project myObject=object("bytes", receivedBytes, "static", true)

Other

coalesce()

coalesce(value1: any, value2: any, valueN: any, ... ) -> any

Returns the first non-null value in the list of arguments.

Example:

panther_logs.public.aws_alb
| project firstArn=coalesce(targetGroupArn, chosenCertArn)

toscalar()

toscalar(query: tabular) -> any

Converts a query to a scalar value. If the row contains more than one value it randomly selects one of the values. If the query returns more than one row, it selects the first row.

Example:

panther_logs.public.aws_alb
| extend avgBytes = toscalar(panther_logs.public.aws_alb | summarize agg.avg(receivedBytes) by ip_address)
| project biggerMsg = receivedBytes - avgBytes > 0, receivedBytes

Last updated