> For the complete documentation index, see [llms.txt](https://docs.cybaops.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cybaops.com/modules/investigate.md).

# Investigate

At its core, Investigate is the query and analysis layer of CybaOps used during incident analysis.

It allows analysts to query logs and events across the environment, acting as the primary way to build context beyond the initial alert.

It is CybaOps’ built-in SIEM query layer that allows analysts to pivot from alerts into full log analysis, correlate activity across time, and build a complete, evidence-backed investigation directly within the case timeline.

### <mark style="color:$primary;">Contents</mark>

* [Terminology](#terminology)
* [Layout](#layout)
* [Query Input](#query-input)
  * [Query Syntax](#query-syntax)
    * Basic Operations
    * Wildcards
    * Piping
    * General Functions
    * Aggregation / Metric Functions
    * Visualisation Functions
* [Timeline](#timeline)
* [Event Log](#event-log)
* [Data Sources](#data-sources)
* [Full Flow Example](#full-flow-example)
  * [Drilling Down: From Overview to a Targeted Investigation](#drilling-down-from-overview-to-a-targeted-investigation)

### <mark style="color:$primary;">Terminology</mark>

* **Event:** A recorded occurrence. The contents of an event vary by data source. Events are structured as key/value pairs, for example:

```
{
    key: value
}
```

* **Investigation:** Through the CybaOps platform, you can launch standalone investigations: self-contained units that let you use Investigate without linking it to a Case.
* **Query:** A structured way to define filters for events.
* **Field:** Each entry within an event is a field, consisting of one key and one value. In the UI, numeric values appear green, text values appear reddish, and boolean (`true` / `false`) values appear blue. You do not need to manage field types manually when writing a query, as Investigate handles this automatically.
* **Operator:** A symbol used in a query to define the conditions you want to apply to fields. Operators are detailed later in this document.
* **Data Pool:** A source of data from which events are formed. The most common is the CybaOps MDR.

### <mark style="color:$primary;">Layout</mark>

<picture><source srcset="/files/D6Z2KZBZDIUaFgazY43v" media="(prefers-color-scheme: dark)"><img src="/files/kA8dexFhEFdgbusGzdoW" alt=""></picture>

This is the primary view for Investigate. It can be divided into three parts, each named after its most important component: the query input, the timeline, and the event log.

### <mark style="color:$primary;">Query Input</mark>

The query input section centres on the query input box, but a few secondary features also sit alongside it.

* **Query Input:** This is the main method you’ll use to gather and filter data. Every UI feature that manipulates the data (apart from the time ranges) makes a corresponding change to the query in the query input box, so you can easily modify and reproduce queries.
* **AI button:** This uses Sentry AI to generate queries automatically from your input. Note that the resulting query may not be fully accurate and may require manual adjustment.
* **Calendar:** This lets you specify a timespan more precisely, offering predefined intervals alongside a calendar for selecting specific ranges. This is the control that sets the query’s time range.
* **Data Source:** This lets you choose the data source for your events. This document demonstrates the CybaOps MDR source; data sources are covered in more detail later.

#### <mark style="color:$primary;">Query Syntax</mark>

**Basic Operations**

For basic data queries, use the following syntax:

```
PROPERTY = "value"
```

where `PROPERTY` is any property present in an event.

Investigate automatically flattens all sub-objects and lists/arrays within events. For example, an event containing a nested object and a list, such as the following, can be accessed using dot notation.

```
{
    name: "A"
    context: {
        context_name: "B"
        list: ["X", "Y", "Z"]
        subcontext: {
            subcontext_name: "C"
        }
    },
    
}
```

On the platform, this event is displayed and processed as:

```
{
    name: "A"
    context.context_name: "B"
    context.list[0]: "X"
    context.list[1]: "Y"
    context.list[2]: "Z"
    context.subcontext.subcontext_name: "C"
}
```

Note that lists are zero-indexed, so the first item is `[0]`, not `[1]`.

Logical operators and negation are supported in queries:

```
name = "device-01" OR name = "device-02"
agent_version = "1.2.5" AND type = "workstation"
type = "mobile" AND operating_system != "ios"
```

Other operators are also supported, including `<`, `>`, `>=`, and `<=` for numeric values.

On the platform, you can include or exclude specific event properties visually by opening an event’s details and pressing the +/- buttons. This adds the corresponding parameter to the query.

**Wildcards**

Wildcards can be used in the following format:

```
host = "pc-*"
```

where `*` matches any trailing data in the value. You can also check whether a field exists at all:

```
host = *
```

**Piping**

Searches support piping, which lets you chain queries and functions for visualisation, grouping, and other purposes.

For example, to pipe query results into a pie chart visualisation function:

```
host = "server-*" | piechart(agent_version)
```

Here, a pie chart is produced for all agent versions across host devices whose names begin with `server-`. The output of a visualisation function can also be piped into other functions, such as the field replacements described later.

A typical investigative pattern is to start with a broad filter and then narrow it with each pipe — for example, filtering events, grouping them, and visualising the result in a single chained query:

```
class_name = "DNS Actvity" | group(host)
```

<picture><source srcset="/files/zL9QJ3T88ANaAVGjkAw3" media="(prefers-color-scheme: dark)"><img src="/files/4LsLduT0pEBcnTCkRKgc" alt=""></picture>

**General Functions**

`group()` groups events by one or more fields. It also supports metric functions, allowing aggregated data per group to be included in the result. For example, to group by system type and display the average CPU time per group:

```
type = * | group(type,function=avg(cpu))
```

Grouping can also be done in the UI via the “Group by” button. In both cases, the metric appears alongside the total count metric as a field with a predefined name of the form `_[function name].[original field name]`, so `avg(max)` yields `_avg.max`.

`select()` lets you define which fields appear in the search result, without grouping. For example, to return only host, CPU, and memory usage across all hosts:

```
host = * | select(host,cpu,memory_usage)
```

Selecting fields can also be done in the UI via the “Select fields” button:

<picture><source srcset="/files/zr1ff3TlV2VS5UZdFikW" media="(prefers-color-scheme: dark)"><img src="/files/NTnjUkCdA9ccEagvj1E2" alt=""></picture>

**Aggregation / Metric Functions**

Investigate provides the following aggregation functions: `sum`, `avg`, `max`, `min`, `count`, and `uniquecount`. These are passed as the special `function` parameter, and are available in more than one place: both inside the `group()` function and inside the `timechart()` visualisation function. They can all be accessed within the UI:

<figure><picture><source srcset="/files/qFIGKbKCgWp0vqq6FmFS" media="(prefers-color-scheme: dark)"><img src="/files/Y8eUDfmOst6SgQDbPfT1" alt=""></picture><figcaption></figcaption></figure>

The same aggregation can therefore be expressed either as a grouped table or as a time series, depending on whether you want a snapshot or a trend. For example, to see the average CPU time per system type:

Group aggregation (snapshot per group):

```
type = * | group(type, function=avg(cpu))
```

Time chart aggregation (the same metric plotted over time):

```
type = * | timechart(type, function=avg(cpu))
```

The first returns one aggregated value per group; the second plots that aggregated value across the selected time range so you can see how it changes.

Note that multiple functions are supported too:

```
type = * | timechart(type, function=["avg(cpu)","max(cpu)"])
```

This would give both an average and a maximum field in the output.

**Visualisation Functions**

There are two primary visualisations: `timechart()` and `piechart()`. Data must be piped into either function, and the primary argument of both is the field to group over (grouping is performed automatically).

* **Time Chart:** Lets you view the occurrence of any number of groups over time. This is very useful for incident response, for example when mapping the deployment of a faulty update or a remediation. As noted above, it also accepts a `function` parameter, so you can plot an aggregated metric (such as an average or sum) over time rather than just event counts.

<figure><picture><source srcset="/files/gscM9yo7MpfRvvW3r5Vo" media="(prefers-color-scheme: dark)"><img src="/files/kbDOc6K1IWnLt5vBl9Ei" alt=""></picture><figcaption></figcaption></figure>

* **Pie Chart:** Provides an easily digestible overview of the proportion of events per group.&#x20;

<figure><picture><source srcset="/files/3z2OJJMk2pU2Qn1nRHZf" media="(prefers-color-scheme: dark)"><img src="/files/jSA1RICdOvhrWcsEmnnX" alt=""></picture><figcaption></figcaption></figure>

### <mark style="color:$primary;">Timeline</mark>

The second part of the UI is the Timeline. Besides the timeline itself, a few UI elements let you manipulate it:

* **The auto-refresh dropdown:** Sets how often the search automatically refreshes, so your results stay up to date at the chosen interval without re-running the query manually. (Note: the query’s *time range* is set with the Calendar, described above, not with this dropdown.)
* **Event List / Group By:** The two available textual views. Event List is the standard view and lets you inspect individual events; Group By is available only when the query contains grouping.
* **Time Chart / Pie Chart:** The two visualisations designed for use with grouped data. (The time chart can also be used without grouping, in which case it returns a result identical to the timeline, except in line form.) Both are detailed later in this document.

The timeline gives you a clear overview of the number of events matching your query, or of all events if no query is specified. You can use the mouse to select a range within it, which automatically sets the time interval to that period. This is invaluable when honing in on a specific incident or cause. In the clip below, selecting a range and switching to the **Group By** view shows how the matching events regroup in real time:&#x20;

<figure><picture><source srcset="/files/OmrLq3tSVrKQusrwcTSV" media="(prefers-color-scheme: dark)"><img src="/files/9dXAlRJoihhBNUq3Emqp" alt=""></picture><figcaption></figcaption></figure>

### <mark style="color:$primary;">Event Log</mark>

The final part is the event log. Alongside the log itself are two shortcut buttons to the powerful field manipulation functions. Using them automatically appends the appropriate clause to the query.

* **Group By:** Groups events by a chosen field, which is very useful for isolating affected machines, for example.
* **Select Fields:** Shows only particular fields per event, which is useful for including only relevant data.

The event log contains the raw event data for a given number of events (which you can specify in the bottom right of the screen; note that the more events you request, the slower the request will be).

When an event is expanded, you can hover over any field to reveal quick actions for that field. There are four symbols. Three modify the query itself, the other adds it to the timeline.

<picture><source srcset="/files/lPE4EzqeOuBf0gg12aJA" media="(prefers-color-scheme: dark)"><img src="/files/GnHBy1weuB1DadVxbPM9" alt=""></picture>

* **Plus:** Adds the given field:value as a condition to the query (only events with this value for this field are returned, in addition to any existing filters).
* **Minus:** The same as Plus, but adds the negation as a condition (only events that do *not* have this value for the field are returned, in addition to any existing filters).
* **Two overlapping squares:** A shortcut to the Group function. It groups all events under the existing query by the specified field.

The final (rightmost) action appears only when you’re working within an existing alert:

* **Timeline symbol:** Adds the given event to the incident timeline, marking it as an event involved in the investigation. This is how you promote a raw log line into evidence on the case timeline. At the moment, the Timeline integration isn’t fully completed.

### <mark style="color:$primary;">Data Sources</mark>

From a data perspective, provenance depends on the selected data pool. There is currently one source: MDR.

* **MDR:** Events from CybaOps’ MDR service. For context, MDR is the detection and response layer that collects, correlates, and manages security events and incidents, providing the underlying data that Investigate uses for deep analysis and querying.

### <mark style="color:$primary;">Full Flow Example</mark>

This example shows how to quickly answer a set of common questions in an open incident case: - What types of events are present? - How many events are there of each type? - When did these events occur, and at what frequency? - What is the proportion of each type relative to the others?

<picture><source srcset="/files/0Thy4mJ1u5gMLm0d8eGq" media="(prefers-color-scheme: dark)"><img src="/files/6bYsjLoc0sGgc8QkVMQm" alt=""></picture>

Here’s our data. First, to break the events down by type, we can group on the `class_name` field:

<picture><source srcset="/files/44KTxfrcpBKg5u3NvPfH" media="(prefers-color-scheme: dark)"><img src="/files/I4gpWtZCyoBygAYymG38" alt=""></picture>

This single step answers our first two questions: we can see the four types alongside the count for each one. To answer the third question, bring up a time chart:

<picture><source srcset="/files/hx7Yh88qTeKCoceIoU6L" media="(prefers-color-scheme: dark)"><img src="/files/OZ5x2ZCJyUmNJo5sQmB4" alt=""></picture>

This lets us easily see how each event type is distributed over time, as well as its frequency.

We’ve effectively answered the fourth question over time via the time chart, but for an overall proportion, switch to the pie chart:

<picture><source srcset="/files/do42mg3T2JhNjMLAU8c7" media="(prefers-color-scheme: dark)"><img src="/files/oOAE2tWsXJEu4wegCeYT" alt=""></picture>

This view is ideal for a high-level overview, particularly one intended for a less technical audience.

Overall, we’ve reached our answers very quickly — Investigate delivers rapid context for rapid responses.

#### <mark style="color:$primary;">Drilling Down: From Overview to a Targeted Investigation</mark>

The flow above gives us the lay of the land. The real value of Investigate, though, comes from moving from that overview into a focused investigation. Continuing from the grouped view above, suppose the `DNS Activity` class stands out and we want to understand it.

First, drill into just that event type. You can click the Add quick action on a `class_name = "DNS Activity"` field, or type it directly:

```
class_name = "DNS Activity"
```

<figure><picture><source srcset="/files/NGR9K22Ny4deenlMHmas" media="(prefers-color-scheme: dark)"><img src="/files/XCg2HosCaGIpfWTvHnOf" alt=""></picture><figcaption></figcaption></figure>

The timeline now reflects only DNS events. To find out which top 5 hosts are responsible, use the group shortcut on the `src_endpoint.ip` field and once queried, the group selection button at the bottom to select the top 5, or write:

```
class_name = "DNS Activity" | group("src_endpoint.ip", size=5)
```

<figure><picture><source srcset="/files/E4x1v7CO6S6I4GZQ2PnU" media="(prefers-color-scheme: dark)"><img src="/files/EehVAafz2Xo2KNYy6LZe" alt=""></picture><figcaption></figcaption></figure>

This filters out all of the less prominent hosts, leaving only the noisiest hosts at a glance.

Say one IP clearly dominates. Narrow to it by adding its value as a condition — again via the Add quick action, or directly:

```
class_name = "DNS Activity" AND src_endpoint.ip = "195.98.19.245"
```

<figure><picture><source srcset="/files/AOcJdHxwwUhlEh5zifhK" media="(prefers-color-scheme: dark)"><img src="/files/zSHUWcTvs8IIGplyr4hN" alt=""></picture><figcaption></figcaption></figure>

From here you can plot that single host’s DNS activity over time to spot bursts or beaconing-like regularity by either clicking on the timechart button after grouping by the IP, or adding in the query parameter yourself:

```
class_name = "DNS Activity" AND src_endpoint.ip = "195.98.19.245" | timechart("src_endpoint.ip")
```

<figure><picture><source srcset="/files/VeqcXqVSHzD6V3jDFFjB" media="(prefers-color-scheme: dark)"><img src="/files/Scw0pCKzYRqeZ7oTTC5U" alt=""></picture><figcaption></figcaption></figure>

In just a few steps we’ve gone from “what’s in this data?” to “what is this specific host doing, and when?” — overview to targeted investigation, all by extending one query. When working within an alert, the Timeline shortcut can then be used to add the key DNS events to the incident timeline as evidence.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.cybaops.com/modules/investigate.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
