bronto-log-search
Load this skill before writing or running a Bronto log search - counting, grouping, trending or fetching log events with the Bronto MCP tools. It explains which tool answers which question, how to wri
SKILL.mdskills/bronto-log-search/SKILL.md
GitHubRun a Bronto log search
Bronto stores logs in datasets, each identified by a log_id. Every search runs over a list of log_ids and a time window, with an optional search_filter. If you don't yet know which datasets hold the logs you need, use the bronto-dataset-discovery skill first.
1. Pick the tool
Work from summaries to raw events, and only fetch events once you know what to look for.
| Question | Tool |
|---|---|
| Where are the errors in this window? | get_error_summary - per-dataset error and warning totals; does not use search quota |
| How many, how often, which values, how slow? | timeseries - counts and aggregates, optionally grouped and bucketed over time |
| What do the events say? | search_logs - raw events, with a small limit and only the columns you need |
| Is there a saved search for this already? | get_saved_searches, then run_saved_search |
A saved search runs over the window it was saved with unless you override it. Pass the incident window to run_saved_search as from_ts and to_ts, or as time_range, and set limit.
search_logs returns events only. It rejects groups with aggregate select columns; use timeseries with group_by_keys for any grouped count or aggregate.
2. Set the time window
- During an investigation, pass the window as
timerange_startandtimerange_endin Unix epoch milliseconds, so every call covers exactly the same period. - For a quick look,
time_rangeaccepts relative windows such asLast 15 minutes,Last 1 hourorLast 24 hours. - Start narrow, around the incident, and widen only if the first results are empty or the cause began earlier.
3. Write the search_filter
search_filter is the WHERE clause of a query: a predicate only. Never put GROUP BY, ORDER BY, HAVING or aggregate functions in it.
Check field names first. Call get_keys for each dataset you search and copy key names exactly. Schemas differ between datasets, so a key that exists in one dataset silently matches nothing in another. Dataset names, collections and tags are not fields.
Quoting:
- String values take single quotes:
log_level = 'ERROR'. An unquoted word on either side of an operator is read as a field name, sostatus = errorcompares two fields. - Numbers and booleans are bare:
status >= 500,authenticated = false. Quoting a number makes it a string comparison. - Field names that contain any of
= ! ? . , < > - + * / % ^ & |take double quotes:"exception.type" IS NOT NULL,"request-time" = '500ms'. - Escape a quote by doubling it:
'O''Brien'.
Free text: a bare word or quoted string on its own, such as timeout or 'connection refused', matches anywhere in the raw event, ignoring case. It is shorthand for @raw ILIKE '%timeout%'. Use free text first for opaque identifiers such as request IDs and trace IDs. Free text does not search resource attributes whose names start with $, such as $service or $hostname; filter on those by name: "$service" = 'checkout-api'.
Common operators:
| Need | Example |
|---|---|
| Exact value | log_level = 'ERROR' |
| One of several values | status IN (500, 502, 503) |
| Exclude values | log_level NOT IN ('DEBUG', 'TRACE') |
| Field present or missing | "exception.type" IS NOT NULL |
| Substring, case-insensitive | message ILIKE '%timed out%' |
| Numeric range | duration_ms >= 1000 AND duration_ms < 5000 |
| Combine | log_level = 'ERROR' AND (timeout OR 'connection refused') |
AND binds before OR; use parentheses. For the full operator list, data type rules and regular expressions, see references/search-syntax.md.
4. Aggregate with timeseries
metric_functionsis required. UseCOUNT(*)for event counts, andSUM,AVG,MIN,MAX,P50,P75,P90,P95orP99on numeric fields only, for exampleP95(duration_ms).group_by_keysgroups the result, for example["path"]or["log_level"]. Setlimitto the number of groups you need; the response markstruncated: truewhen more groups exist.num_of_slicessets the number of time buckets. Use it to see when something started or stopped.- Leave
minimal_outputfalse when you need per-bucket values or any aggregate other than the count. The minimal response keeps only total counts. - In each group,
countis the number of matching events andvalueis the aggregate. Reportvaluefor sums, averages and percentiles.
To see which kinds of message dominate, group by $pattern_id. Bronto assigns a pattern ID to each event as it is ingested, based on the structure of the message, so this groups events like Connection to db-1 failed and Connection to db-2 failed together. An empty pattern ID means the event matched no pattern.
5. Fetch events with search_logs
- Set a small
limit, such as 10. The API returns 100 events by default, each with every field and@rawunless you setselect. - Set
most_recent_first: trueto see the latest events; without it, results come oldest first. To find the first occurrence, leave it false, or use a bucketedtimeseriesinstead. - Use
selectto return only the columns you need, such as["log_level", "message", "exception.type"]. Without it, each event comes back in full and a few dozen events can fill the context. order_bysorts, for exampleduration_ms DESCto find the slowest requests.group_by_patterns: truecollapses repeated events into pattern templates with counts, but events that match no pattern still come back in full. Combine it with a narrow filter and a smalllimit. To see the events behind one pattern, search again with"$pattern_id" = '<pattern_id>'.- To page through more results, pass the
pagination_tokenfrom the response'slinks. Stop paging once you have the events you need, and after three pages narrow the filter or usetimeseriesinstead.
6. Read the results carefully
- Zero matches is not proof of absence. Before you report that something didn't happen, check the field name with
get_keys, check the value's quoting and case, and check the time window andlog_ids. - Compare with a baseline. A count during the incident means little alone. Run the same
timeseriesfor an earlier period, or use more time buckets to see the change. - Each response includes a
webapp_url. Include it in your findings so a person can open the same search in Bronto. - Quote evidence exactly. When a log line supports a conclusion, quote it with its timestamp and dataset.
Limits
- Make at most 20 Bronto tool calls in this skill before reporting what you found.
- A query is at most 16,000 characters and 400 expressions.
- All steps are read-only. Do not create monitors or saved searches as part of this skill.