PantherFlow (Beta)
PantherFlow is Panther's pipelined query language
Last updated
Was this helpful?
PantherFlow is Panther's pipelined query language
Last updated
Was this helpful?
PantherFlow is Panther's pipelined query language. It's designed to be simple to understand, yet powerful and expressive.
Use PantherFlow to explore and analyze your data in Panther. With its and , you can perform a variety of data operations, such as filtering, transformations, and aggregations—in addition to as a bar or line chart. PantherFlow is schema-flexible, meaning you can seamlessly search across multiple data sources (including those with different schemas) in a single query.
PantherFlow queries use pipes (|
) to delineate data operations, which are processed sequentially. This means the output of a query's first operator is passed as the input to the second operator, and so on. See an example query below:
Use PantherFlow to query data in Search. .
To assist your query writing, the PantherFlow code editor in Search has autocomplete, error underlining, hover tooltips, inlay hints, and function signature assistance.
If your PantherFlow query specifies a database/table, the in the upper-right corner of the Search page are ignored.
If your PantherFlow query does not specify a database/table, the database, table, and date range filters are all applied. In this scenario, if your PantherFlow query includes a date/time range (with a | where p_event_time ...
statement), both date/time ranges are applied—i.e., returned data must fall within the date/time range set in both the date range filter and the range defined by the | where p_event_time ...
statement.
Let's explore the following PantherFlow query:
In short, this query reads data from the aws_alb
table, filters out events that occurred before the last day, sorts remaining events by time, and returns the first 10 events.
Let's take a deeper look at each line:
panther_logs.public.aws_alb
This statement identifies the data source.
This query is reading from the panther_logs.public.aws_alb
table. If the query contained only this line, all data in the table would be returned.
| where p_event_time > time.ago(1d)
This query is requesting data where the p_event_time
field value is greater than the time one day ago. In other words, it's asking for events that occurred within the last day. The time.ago()
function subtracts from the current time, and its argument (1d
) is a timestamp constant representing one day.
| sort p_event_time
| limit 10
This query is requesting no more than 10 events.
See additional query examples:
In some cases, a PantherFlow query may run slower than an equivalent SQL query.
To ensure your PantherFlow query results return as quickly as possible (and to minimize Snowflake costs arising from the search), it's recommended to follow these best practices:
Use the limit
operator
Example: panther_logs.public.aws_alb | limit 100
Use a time range filter
Example: panther_logs.public.aws_alb | where p_event_time > time.ago(1d)
Use p_any
fields
During log ingestion, Panther extracts common security indicators into p_any
fields, which standardize attribute names across all data sources. The p_any
fields are stored in optimized columns. It's recommended to query p_any
fields instead of various differently named fields for multiple log types.
Example: panther_logs.public.aws_alb | '10.0.0.0' in p_any_ip_addresses
Use the project
operator
Example: panther_logs.public.aws_alb | project targetIp, targetPort
Summarize results
Summaries execute faster than queries fetching full log records. Using a summary is especially helpful when you're investigating logs over a long period of time, or when you don't know how much data volume exists for the time range you're investigating.
Example: panther_logs.public.aws_alb | summarize count=agg.count() by targetIp
Filter data early
Filter data before performing expensive operations, such as summarize
or join
, rather than after.
Example:
Instead of: panther_logs.public.aws_alb | summarize agg.count() by actor | where actor != nil
Use: panther_logs.public.aws_alb | where actor != nil | summarize agg.count() by actor
Avoid the search
operator, if possible
Example:
Instead of: | search 'alice'
Use: | where strings.contains(name, 'alice')
The term "PantherFlow query" typically refers to a , which retrieves a dataset and returns it in some form (in contrast to a .) A tabular expression statement usually contains separated by pipes (|
). Each operator performs some action on the data—i.e., filters or transforms it—before passing it on to the next operator. Operator order is important, as PantherFlow statements are read sequentially.
See an overview of PantherFlow syntax on , or explore syntax topics in more detail:
The takes an to filter the data.
The lets you order events by one or more field values.
This query orders data by p_event_time
. Because the is descending, the most recent event will be returned first.
The defines how many events you'd like returned, at most.
While you can using PantherFlow in the Panther Console, it's not possible to:
Schedule a Saved Search (i.e., create a )
Create a Saved Search using PantherFlow in the developer workflow (i.e., by uploading a saved_query
via the or by using the or APIs)
Aggregations (i.e., the ) do not show information on the .
In Search, the does not reflect fields that are added or removed when using operators like , , and .
The .
Use the to specify the maximum number of records your query will return.
Use the to filter by a time range (perhaps against p_event_time
). A query with a time range filter will access fewer , which returns results faster.
Learn more about .
Learn more on .
A query without a retrieves all columns, which can slow down queries. When possible, use project
to query only the fields you need to investigate.
Instead of querying the full data set, use the , which will execute faster and help you determine a narrower timeframe to query next.
Learn more about .
The can introduce slowness, and should be avoided unless necessary. If you know which column (or columns) might contain the text you'd like to search for, instead of searching across all columns in the specified database/table with search
, use with .