Skip to content

Piped Processing Language (PPL)

Piped Processing Language (PPL) is the native query language of the OpenSearch Observability Stack. Every log query, every trace investigation, and every pattern analysis flows through PPL - a pipe-delimited language designed for the way operators and engineers actually think about data.

Try PPL now in the live playground →

source = logs-otel-v1*
| where severityNumber >= 17
| stats count() as errors by `resource.attributes.service.name`
| sort - errors

Try in playground →

That query finds every error log, counts them by service, and sorts by severity - all in four lines you can read aloud. No JSON nesting, no callback syntax, no query DSL to memorize.

PPL follows the natural mental model of data investigation: start with a data source, progressively filter, transform, and aggregate. Each pipe (|) represents a single, composable operation. Reading a PPL query from top to bottom tells you exactly what happens at every step.

source = otel-v1-apm-span-*
| where serviceName = 'frontend'
| where durationInNanos > 2000000000
| stats avg(durationInNanos) as avg_latency by name
| sort - avg_latency
| head 10

Unlike platforms that require different query dialects for different signal types, PPL works across both logs and traces in the Observability Stack. The same syntax, the same commands, the same muscle memory - whether you are triaging an incident in logs or profiling latency in traces.

SignalQuery LanguageIndex Pattern
LogsPPLlogs-otel-v1*
TracesPPLotel-v1-apm-span-*
MetricsPromQLPrometheus time-series

PPL is not a general-purpose query language bolted onto a search engine. It was designed from the ground up for the workflows observability engineers perform daily:

  • Pattern discovery - the patterns command automatically extracts log patterns and clusters similar entries, replacing hours of manual regex work
  • Field extraction on the fly - parse, grok, and rex let you extract structured fields from unstructured log text without re-indexing
  • Statistical analysis - stats, eventstats, streamstats, and trendline cover everything from simple counts to rolling window calculations
  • Deduplication and ranking - dedup, top, and rare surface the signal in noisy data
  • Machine learning built in - ml and kmeans run anomaly detection and clustering directly in your query pipeline
  • Join and correlate - join, lookup, append, and subquery combine data from multiple indices for cross-signal investigation

PPL provides a comprehensive command set that covers the full spectrum of data exploration:

CategoryCommands
Search & filtersearch, where, regex, subquery
Field selectionfields, table, rename, eval
Aggregationstats, eventstats, streamstats, chart, timechart, bin
Sorting & limitingsort, head, reverse
Dedup & rankingdedup, top, rare
Text extractionparse, grok, rex, spath, patterns
Data enrichmentjoin, lookup, append, appendcol, multisearch
Transformationfillnull, expand, flatten, replace, convert
Trend & MLtrendline, ml, kmeans
Metadatadescribe, explain, showdatasources

For the full command reference, see Commands. For function reference, see Functions.

PPL is woven into every investigation surface of the stack:

The Discover interface for Logs and Traces uses PPL as its primary query language. Type PPL directly in the query bar, with autocomplete for field names, commands, and functions.

The Claude Code observability plugin generates PPL queries from natural language. Ask “show me the slowest traces from the frontend service” and the plugin produces the PPL query, runs it, and returns results - all powered by PPL templates.

PPL queries can drive alerts and anomaly detection monitors. Define alert conditions using the same query language you use for ad-hoc investigation.

PPL query results can be saved to dashboards as live visualizations - line charts, bar charts, heatmaps, and more - all driven by PPL.

The fastest way to learn PPL is to use it. Open the [live playground](https://observability.playground.opensearch.org/w/19jD-R/app/explore/logs/#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-6h,to:now))&_q=(dataset:(id:d1f424b0-2655-11f1-8baa-d5b726b04d73,timeFieldName:time,title:‘logs-otel-v1*‘,type:INDEX_PATTERN),language:PPL,query:”)&_a=(legacy:(columns:!(body,severityText,resource.attributes.service.name),interval:auto,isDirty:!f,sort:!()),tab:(logs:(),patterns:(usingRegexPatterns:!f)),ui:(activeTabId:logs,showHistogram:!t)) and try these queries against live OpenTelemetry data:

Count logs by service:

| stats count() as log_count by `resource.attributes.service.name`

Try in playground →

Find error logs:

| where severityText = 'ERROR' or severityText = 'FATAL'

Try in playground →

GenAI operations breakdown:

| stats count() as operations by `resource.attributes.service.name`, `attributes.gen_ai.operation.name`

Try in playground →

PPL belongs to the family of pipe-based query languages used in modern observability platforms. If you have experience with Kusto Query Language (KQL) or Elastic Event Query Language (EQL), PPL will feel immediately familiar - with key advantages:

CapabilityPPLKQL (Kusto)EQL (Elastic)
Pipe-based syntaxYesYesLimited
Log pattern discoveryBuilt-in (patterns)Requires external toolingNo
Machine learning in-queryml, kmeansSeparate serviceSeparate service
Field extraction on-the-flyparse, grok, rexparse, extractLimited
Join across indicesjoin, lookup, subqueryjoin, lookupSequence only
Rolling statisticsstreamstats, trendlinescan, window functionsNo
Open sourceFully open source (Apache 2.0)ProprietaryProprietary (SSPL)
OpenTelemetry-nativeFirst-class OTel supportVia connectorVia integration