# Advanced Log Queries

This document provides advanced examples of querying logs using the groundcover API with complex filtering conditions.

### Overview

The `group` parameter supports various filter operations and combinations. This page demonstrates advanced patterns including:

* OR conditions within a single field
* NOT conditions (excluding values)
* Wildcard matching
* Free text search

### OR Conditions on a Single Field

To match multiple values for the same field (OR condition), include multiple filters in the same condition:

**Example: Match logs where `env` is either "prod" OR "dev" AND `level` is "error"**

```bash
curl 'https://app.groundcover.com/api/logs/v2/query' \
  -H 'accept: application/json' \
  -H 'authorization: Bearer <YOUR_API_KEY>' \
  -H 'Content-Type: application/json' \
  --data-raw '{
    "start": "2025-12-24T13:36:49.143Z",
    "end": "2025-12-24T19:36:49.143Z",
    "group": {
      "operator": "and",
      "conditions": [
        {
          "filters": [{"op": "match", "value": "error"}],
          "key": "level",
          "origin": "root",
          "type": "string"
        },
        {
          "filters": [
            {"op": "match", "value": "prod"},
            {"op": "match", "value": "dev"}
          ],
          "key": "env",
          "origin": "root",
          "type": "string"
        }
      ]
    },
    "limit": 200,
    "skip": 0,
    "sortBy": "timestamp",
    "sortOrder": "desc",
    "selectors": [],
    "optimizeSearch": true
  }'
```

**Structure:**

* Multiple `filters` in the same `conditions` entry create an OR relationship
* In this example, the `env` field matches if it equals "prod" **OR** "dev"
* The overall `operator: "and"` means both conditions must be satisfied (level=error AND (env=prod OR env=dev))

### NOT Conditions (Excluding Values)

To exclude specific values, use the `"op": "not_match"` operation:

**Example: Match logs where `level` is NOT "error" AND `env` is "prod"**

```bash
curl 'https://app.groundcover.com/api/logs/v2/query' \
  -H 'accept: application/json' \
  -H 'authorization: Bearer <YOUR_API_KEY>' \
  -H 'Content-Type: application/json' \
  --data-raw '{
    "start": "2025-12-24T13:39:48.388Z",
    "end": "2025-12-24T19:39:48.388Z",
    "group": {
      "operator": "and",
      "conditions": [
        {
          "filters": [{"op": "not_match", "value": "error"}],
          "key": "level",
          "origin": "root",
          "type": "string"
        },
        {
          "filters": [{"op": "match", "value": "prod"}],
          "key": "env",
          "origin": "root",
          "type": "string"
        }
      ]
    },
    "limit": 200,
    "skip": 0,
    "sortBy": "timestamp",
    "sortOrder": "desc",
    "selectors": [],
    "optimizeSearch": true
  }'
```

**Structure:**

* Use `"op": "not_match"` to exclude values
* This example returns logs where level is anything except "error" AND env is "prod"

### Wildcard Matching

To match values that start with, end with, or contain a pattern, use wildcard characters:

**Example: Match logs where `workload` starts with "groundcover" AND `level` is NOT "error"**

```bash
curl 'https://app.groundcover.com/api/logs/v2/query' \
  -H 'accept: application/json' \
  -H 'authorization: Bearer <YOUR_API_KEY>' \
  -H 'Content-Type: application/json' \
  --data-raw '{
    "start": "2025-12-24T13:41:07.744Z",
    "end": "2025-12-24T19:41:07.744Z",
    "group": {
      "operator": "and",
      "conditions": [
        {
          "filters": [{"op": "not_match", "value": "error"}],
          "key": "level",
          "origin": "root",
          "type": "string"
        },
        {
          "filters": [{"op": "match", "value": "groundcover*"}],
          "key": "workload",
          "origin": "root",
          "type": "string"
        }
      ]
    },
    "limit": 200,
    "skip": 0,
    "sortBy": "timestamp",
    "sortOrder": "desc",
    "selectors": [],
    "optimizeSearch": true
  }'
```

**Structure:**

* Use `*` as a wildcard character
* `"groundcover*"` matches any value starting with "groundcover" (e.g., "groundcover-backend", "groundcover-frontend")
* Wildcards can be used with both `match` and `not_match` operations

### Free Text Search

To search for specific text or phrases within log content (not limited to specific fields), use free text search with `phrase_search`:

**Example: Search for logs containing the phrase "POST /ingest" with additional fields**

```bash
curl 'https://app.groundcover.com/api/logs/v2/query' \
  -H 'accept: application/json' \
  -H 'authorization: Bearer <YOUR_API_KEY>' \
  -H 'Content-Type: application/json' \
  --data-raw '{
    "start": "2025-12-24T14:10:06.183Z",
    "end": "2025-12-24T20:10:06.183Z",
    "group": {
      "conditions": [{
        "filters": [{"op": "phrase_search", "value": "POST /ingest"}],
        "origin": "root",
        "type": "freetext"
      }],
      "operator": "and"
    },
    "limit": 200,
    "skip": 0,
    "sortBy": "timestamp",
    "sortOrder": "desc",
    "selectors": [{"key": "request.method"}, {"key": "cluster"}, {"key": "host.id"}],
    "optimizeSearch": true
  }'
```

**Structure:**

* Use `"op": "phrase_search"` for free text search
* Set `"type": "freetext"` (instead of `"type": "string"`)
* Do not include a `"key"` field - free text search searches across all log content
* The `value` can be a single word or a phrase (e.g., `"POST /ingest"`)
* Free text search searches within the log line content, not specific fields
* Use `selectors` to request additional fields. Format: `[{"key": "request.method"}, {"key": "cluster"}, {"key": "host.id"}]`

### Filter Operations

The following filter operations are supported:

| Operation       | Description                                      | Example                                            |
| --------------- | ------------------------------------------------ | -------------------------------------------------- |
| `match`         | Matches the exact value or pattern               | `{"op": "match", "value": "error"}`                |
| `not_match`     | Excludes the exact value or pattern              | `{"op": "not_match", "value": "error"}`            |
| `phrase_search` | Searches for a phrase in log content (free text) | `{"op": "phrase_search", "value": "POST /ingest"}` |

### Combining Conditions

#### AND Operator

When using `"operator": "and"`, all conditions must be satisfied:

```json
{
  "operator": "and",
  "conditions": [
    {"filters": [...], "key": "level", ...},
    {"filters": [...], "key": "env", ...}
  ]
}
```

This means: `level` condition **AND** `env` condition must both be true.

#### OR Within a Field

Multiple filters in the same condition create an OR relationship:

```json
{
  "filters": [
    {"op": "match", "value": "prod"},
    {"op": "match", "value": "dev"}
  ],
  "key": "env",
  ...
}
```

This means: `env` equals "prod" **OR** `env` equals "dev".

#### Complex Combinations

You can combine AND and OR operations:

```json
{
  "operator": "and",
  "conditions": [
    {
      "filters": [{"op": "match", "value": "error"}],
      "key": "level",
      "origin": "root",
      "type": "string"
    },
    {
      "filters": [
        {"op": "match", "value": "prod"},
        {"op": "match", "value": "dev"}
      ],
      "key": "env",
      "origin": "root",
      "type": "string"
    }
  ]
}
```

This means: `level` equals "error" **AND** (`env` equals "prod" **OR** `env` equals "dev").

### Best Practices

1. **Wildcard Performance**: Use wildcards judiciously as they can impact query performance on large datasets.
2. **NOT Operations**: `not_match` operations can be slower than `match` operations. Consider if you can achieve the same result with positive matches.
3. **Multiple Filters**: When using multiple filters in a single condition (OR), ensure they all apply to the same field.
4. **Consistent Structure**: Always include `origin: "root"` and the appropriate `type` for each condition.
5. **Testing**: Test complex queries with small time ranges first to verify the results before querying large datasets.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.groundcover.com/use-groundcover/remote-access-and-apis/api-examples/query-logs/advanced-log-queries.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
