Google Cloud Logs Explorer Guide: LQL Queries and Examples

Google Cloud Logs Explorer is the Cloud Logging interface for finding and inspecting individual log entries. When an alert fires or a service starts returning errors, Logs Explorer is where you go to read the actual logs and diagnose what happened. It filters entries using the Logging Query Language (LQL), a purpose-built filter syntax that is not SQL. The faster you can write the right LQL filter, the faster you close the incident.

Logs Explorer in simple terms

Cloud Monitoring gives you metrics: numbers over time that tell you when something went wrong. Logs Explorer gives you the raw evidence: the actual messages your services wrote at the moment something failed.

This is the tool you open when a metric chart shows a spike in error rate but does not tell you why. A spike in 500s is a signal. The log entry that says “db connection pool exhausted, 48/48 connections in use” is the answer.

One important distinction upfront: Logs Explorer is not the right tool for aggregation or trend analysis. For that, use Log Analytics. Both tools are covered in a comparison section below.

Analogy

Think of metrics as the warning lights on a car dashboard, and Logs Explorer as the black box flight recorder. The warning light tells you something is wrong. The recorder tells you exactly what the engine was doing at 14:32:07 when the fault occurred, event by event, in sequence. You need both, but when you need to find the cause, you open the recorder.

When to use Logs Explorer

Open Logs Explorer when:

  • A Cloud Run service is returning 500s and you need to read the actual error messages, not just the error count. See Monitoring Cloud Run for the signals to watch before reaching for Logs Explorer.
  • A pod in GKE is crashing or behaving unexpectedly and you need container logs to understand the cause. See Monitoring GKE for the broader observability picture.
  • A VM or Compute Engine service fails and you need to read system logs, startup script output, or application logs from the instance.
  • An alert fired and you are in an active incident. See Incident Response with Monitoring for a structured workflow that includes Logs Explorer as a key step.
  • You suspect an IAM or admin change caused a problem and need to see who changed what and when. See Cloud Audit Logs for the log types involved and how to query them.
  • You are investigating suspicious activity and want to correlate access patterns across services. See Detecting Suspicious Activity with Logs for that specific workflow.
  • After an incident, you are looking for a pattern that should have triggered an alert earlier. This often leads directly to creating log-based metrics from the filter you just wrote.

How Logs Explorer works

A typical investigation follows this sequence:

  1. Choose your project and scope. Logs Explorer queries the log buckets in the current project. In multi-project setups, logs for a Cloud Run service in project A are not visible when you are viewing project B. Verify the project in the top nav before writing any queries.
  2. Set the time range. The default is the last hour. If you are investigating a past incident, set a custom range first. Wrong time range is the most common reason queries return nothing.
  3. Start with broad filters. Begin with a resource type and severity. Do not over-constrain from the start. Let Logs Explorer show you what is there before you narrow further.
  4. Inspect a matching entry. Expand any log entry in the results. This shows the full JSON structure and reveals what fields are available for filtering. The field names you see here are the ones you use in LQL.
  5. Refine with LQL. Add conditions based on what you found in step 4. Filter by specific field values, message substrings, or request IDs to isolate the relevant entries.
  6. Act on what you find. Save useful queries, share them with teammates via a shareable link, or convert a recurring filter into a log-based metric so you can alert on it in the future.

The Logs Explorer interface

The interface has five main areas. Understanding what each one does saves time during an incident.

Query pane. Where you write LQL filter expressions. The query runs when you press Run Query or Shift+Enter. Dropdowns above the pane let you filter by resource type, log name, and severity without writing LQL by hand.

Timeline / histogram. A bar chart showing log volume over the current time range. Use it to spot the exact moment traffic spiked or dropped. Clicking a bar narrows the time range to that interval.

Log fields panel. A sidebar showing the top values for fields like severity, resource.type, and any jsonPayload fields. Clicking a value injects the correct LQL expression into your query automatically. This is the fastest way to discover what fields your logs actually contain.

Query results pane. The list of matching log entries in reverse chronological order. Expand any entry to read its full JSON structure. Every field you see there is queryable with LQL.

Saved queries and shareable links. Save queries you use repeatedly. Shareable links carry the full query, time range, and project scope so you can hand off an investigation without losing context.

Logging Query Language (LQL) basics

LQL is a filter language. You write conditions directly, and Logs Explorer returns every log entry that matches all of them.

Note

LQL is not SQL. There is no SELECT, no FROM, no WHERE. If you catch yourself typing SQL syntax in the query bar, stop. Switch to Log Analytics, which does support GROUP BY and COUNT. Logs Explorer does not.

Core operators

  • = for exact match: severity=“ERROR”
  • != for not equal: severity!=“DEBUG”
  • : for substring contains: jsonPayload.message:“connection refused”
  • =~ for regex match: jsonPayload.message=~“timeout.*database”
  • >= and <= for comparison, used with severity levels and timestamps

Combining conditions

Use AND, OR, and NOT to combine conditions. Multiple conditions on separate lines are implicitly ANDed. A bare string with no operator is a substring search across all fields.

Resource scoping

Always scope to a specific resource type when you can. resource.type=“cloud_run_revision” limits results to Cloud Run and makes queries significantly faster. Without a resource type filter, Logs Explorer searches across all log sources in the project.

Timestamps

Use timestamp>=“2026-03-18T03:00:00Z” and timestamp<“2026-03-18T04:00:00Z” to pin a query to an exact window. This is more reliable than the time range selector for incident investigations because it persists when you share a query link.

Tip

LQL severity levels have a hierarchy: DEFAULT < DEBUG < INFO < NOTICE < WARNING < ERROR < CRITICAL < ALERT < EMERGENCY. Using severity>=ERROR returns ERROR, CRITICAL, ALERT, and EMERGENCY entries all at once. Using severity>=WARNING adds WARNING and NOTICE to that set.

Real LQL queries you will use

These are the queries that come up in almost every investigation. Use the Log Fields panel to verify field names before typing them manually.

Cloud Run service errors

# All errors from a specific Cloud Run service
resource.type="cloud_run_revision"
resource.labels.service_name="api-service"
severity>=ERROR

# HTTP 5xx responses
resource.type="cloud_run_revision"
resource.labels.service_name="api-service"
httpRequest.status>=500

# Find a specific error message across all revisions
resource.type="cloud_run_revision"
jsonPayload.message:"database connection failed"

# Errors from one specific revision
resource.type="cloud_run_revision"
resource.labels.revision_name="api-service-00042-abc"
severity>=ERROR

GKE container and pod logs

# Errors from a specific container in GKE
resource.type="k8s_container"
resource.labels.cluster_name="prod-cluster"
resource.labels.namespace_name="default"
resource.labels.container_name="api"
severity>=ERROR

# Find crash or OOMKilled messages
resource.type="k8s_container"
jsonPayload.message=~"OOMKilled|crashed|panic"

# Logs from pods with a specific label
resource.type="k8s_container"
labels."k8s-pod/app"="checkout-service"
severity>=WARNING

Compute Engine VM troubleshooting

# System logs from a specific VM instance
resource.type="gce_instance"
resource.labels.instance_id="1234567890123456789"
severity>=ERROR

# Startup script output from any GCE instance
resource.type="gce_instance"
logName=~"startupscript"

# SSH login events on a specific VM
resource.type="gce_instance"
resource.labels.instance_id="1234567890123456789"
jsonPayload.message:"Accepted publickey"

Cloud Audit Logs and IAM investigation

Audit logs live in the _Required bucket. Use them to see who changed what and when. See Cloud Audit Logs for a full breakdown of the audit log types available.

# All Admin Activity audit logs in a project
logName="projects/my-project/logs/cloudaudit.googleapis.com%2Factivity"

# IAM policy changes only
logName="projects/my-project/logs/cloudaudit.googleapis.com%2Factivity"
protoPayload.methodName=~"SetIamPolicy|ModifyIamPolicy"

# Actions by a specific user or service account
logName="projects/my-project/logs/cloudaudit.googleapis.com%2Factivity"
protoPayload.authenticationInfo.principalEmail="user@example.com"

Exact time-window filtering during incidents

# Pin to the window when the incident occurred
resource.type="cloud_run_revision"
resource.labels.service_name="api-service"
timestamp>="2026-03-18T03:10:00Z"
timestamp<"2026-03-18T03:25:00Z"
severity>=ERROR

Regex and structured-field filtering

# Match any of several keywords in a message field
jsonPayload.message=~"timeout|refused|unavailable"

# Filter on a custom structured field value
jsonPayload.user_id="u-98765"

# Combine a custom field with severity
resource.type="cloud_run_revision"
jsonPayload.request_id="req-abc-123"
severity>=WARNING
Tip

When in doubt about a field name, expand a log entry in the results pane and find the field you want. The path shown in the JSON tree is exactly what you put in the LQL filter. Clicking a value from the Log Fields panel does this automatically.

jsonPayload vs textPayload

When your application writes plain text logs, Cloud Logging stores them in textPayload. When your application writes structured JSON logs, they land in jsonPayload. This distinction has a large practical impact on what you can filter.

With textPayload, you can only substring-search the whole string. There is no way to filter by a specific field because plain text has no structure. With structured JSON logs, every field is independently queryable.

Here is what the difference looks like when you need to find one user’s failed checkout:

Plain text log (textPayload), substring only:

textPayload:"user u-98765 checkout failed payment_error"

Structured JSON log (jsonPayload), filter on individual fields:

jsonPayload.user_id="u-98765"
jsonPayload.event="checkout_failed"
jsonPayload.error_code="payment_error"

The structured version lets you isolate one user’s request across thousands of entries instantly. Without structure, you are scanning text and hoping the substring matches what you actually need.

Tip

Not sure which type your app uses? Expand any log entry and look at the top-level fields. A textPayload string means plain text. A jsonPayload object with nested keys means structured logs. See Structured Logging to switch if needed.

Logs Explorer vs Log Analytics

These are two different tools in Cloud Logging and they serve different purposes. Beginners often try to use Logs Explorer for aggregation and hit a wall because LQL does not support GROUP BY, COUNT, or any SQL aggregation function. If you want that, use Log Analytics.

FeatureLogs ExplorerLog Analytics
Query languageLQL (filter syntax)SQL (BigQuery dialect)
Primary useIndividual log entry lookupAggregation, counting, trending
When to open itActive incident, reading specific entriesPost-incident analysis, capacity planning
OutputMatching log entriesTables, charts, aggregate results
Supports GROUP BY / COUNTNoYes

Use Logs Explorer when you need to read specific log entries during an incident. Use Log Analytics when you need to answer questions like “how many 500 errors did we have per service per hour last week?”

If you want to build ongoing monitoring from log data rather than one-off analysis, look at log-based metrics. They turn a recurring LQL filter into a Cloud Monitoring metric that feeds into alerts and dashboards.

Log buckets, retention, and sinks

Cloud Logging stores log entries in log buckets. Every project has two default buckets:

  • _Required receives Admin Activity audit logs, System Event audit logs, and Access Transparency logs. Retention is fixed at 400 days and cannot be changed or deleted.
  • _Default receives all other logs. Default retention is 30 days. You can increase this at extra cost, decrease it, or create custom buckets with different retention policies and regions.
Warning

Logs older than the retention window are permanently gone. There is no recovery option. If you need logs beyond 30 days for compliance, audits, or post-incident review, set up a log sink to BigQuery or Cloud Storage before an incident happens.

Exporting logs with sinks

A log sink routes matching log entries to a destination outside Cloud Logging in real time. You specify an LQL filter and a destination:

  • BigQuery for long-term storage and SQL analysis beyond the 30-day window
  • Cloud Storage for archival
  • Pub/Sub to stream logs to a SIEM or custom processor
  • Another Cloud Logging bucket to route logs to a different project or region

Sinks process logs as they arrive. There is no backfill. A sink only routes logs that arrive after it is created.

# Create a sink that exports error logs to BigQuery
gcloud logging sinks create error-logs-to-bq \
  bigquery.googleapis.com/projects/my-app-prod/datasets/logs \
  --log-filter='severity>=ERROR' \
  --project=my-app-prod

Why your query returns no results

If Logs Explorer returns nothing, work through these checks in order before assuming the logs do not exist.

Check this first

Verify the time range before anything else. Logs Explorer defaults to the last hour. This single setting causes more empty results than any filter mistake. An incident from two hours ago, yesterday, or last week falls outside the default window.

  1. Wrong project. Logs for a service in project A are not visible when you are viewing project B. Check the project selector in the top navigation bar.
  2. Wrong resource type. If you filter by resource.type=“cloud_run_revision” but the service is deployed as a Cloud Run job, you will get nothing. Remove the resource type filter temporarily and inspect what is actually there, then add the correct type.
  3. Querying jsonPayload when logs are textPayload. If your application writes plain text, jsonPayload.message:“error” returns nothing. Try textPayload:“error”, or remove the payload filter entirely and expand a raw entry to see how it is structured.
  4. Logs have aged out. The _Default bucket retains logs for 30 days. An incident from 45 days ago will return nothing unless you set up a sink to BigQuery or Cloud Storage before the window closed.
  5. IAM permissions. The Logs Viewer role (roles/logging.viewer) is required to view log entries. Without it, Logs Explorer appears to return no results even when logs exist. Confirm you have the right role on the correct project.

Common beginner mistakes

  1. Writing SQL syntax in the query bar. LQL has no SELECT, WHERE, or FROM. Write filter expressions directly: severity=“ERROR” resource.type=“cloud_run_revision”. If you want SQL-style aggregation, use Log Analytics instead.
  2. Forgetting to set the time range. The default is the last hour. Always verify the time window before concluding there are no matching logs.
  3. Filtering too narrowly too soon. Starting with ten conditions at once makes it hard to tell which one is wrong when results come back empty. Start broad with resource type and severity, then add conditions one at a time.
  4. Querying jsonPayload on textPayload logs. If your app emits plain text, structured field queries return nothing. Inspect a raw log entry first to confirm the payload type before adding field-level filters.
  5. Assuming logs are retained forever. The _Default bucket keeps logs for 30 days only. Set up log export sinks to BigQuery or Cloud Storage before you need them, not after an incident.

Frequently asked questions

What query language does Logs Explorer use?

Logs Explorer uses the Logging Query Language (LQL). It is not SQL. You filter fields with = (exact match), != (not equal), and : (substring contains). Combine conditions with AND, OR, and NOT. A bare string with no operator is a substring search across all fields.

Why is my Logs Explorer query returning no results?

The most common causes are: wrong time range (Logs Explorer defaults to the last hour), wrong project or resource scope, querying jsonPayload fields when the app emits textPayload, and logs aged out past the retention window. Check each of these before concluding there are no logs.

How long are logs retained by default?

The _Default log bucket retains logs for 30 days. The _Required bucket retains Admin Activity and System Event audit logs for 400 days and that retention cannot be changed.

How do I export logs to BigQuery, Cloud Storage, or Pub/Sub?

Create a log sink. A sink defines an LQL filter and a destination (BigQuery dataset, Cloud Storage bucket, or Pub/Sub topic). Logs matching the filter are routed to the destination in real time. Sinks do not backfill historical logs.

What is the difference between Logs Explorer and Log Analytics?

Logs Explorer is for troubleshooting: you search individual log entries with LQL to find what went wrong. Log Analytics is for aggregation: you run SQL queries to count, group, and trend log data across large time windows. Use Logs Explorer during incidents and Log Analytics for post-incident analysis or capacity planning.

Last verified: 25 March 2026 Cloud services change frequently. Verify details against official documentation before making infrastructure decisions.