Searching the logs¶
Every host's container logs, journal, and Traefik access log end up in VictoriaLogs on ci01. This page shows where to search them and gives the queries that answer the usual questions, using the fields the fleet's agents set. Use it when a service misbehaves and you want its log without logging in to its host.
Nothing here changes anything. The queries are written in LogsQL. See LogsQL for the grammar, and Log collection and streams for how the lines get there.
Status: written, not yet run.
Prerequisites¶
- The fleet has left bootstrap mode, so the agents ship logs. See Leaving bootstrap mode.
- Your machine resolves ci01's service names, and you can sign in through Authentik.
Placeholders¶
| Placeholder | Value |
|---|---|
<host> |
A host's short name, such as id01 |
<container> |
A container's name as docker ps shows it, such as core-ntfy |
<unit> |
A systemd unit's full name, such as sshd.service |
1. Open a search page¶
Two pages search the same store. Use whichever you have open.
Open https://logs.ci01.home.myah-mitchell.com/select/vmui in a browser. Type a query in the box at the top and press Enter.
Open https://grafana.ci01.home.myah-mitchell.com, go to Explore, and choose the VictoriaLogs data source. Type a query in the query field and click Run query.
Both pages have a time range picker of their own. A _time filter in the query narrows the search inside that range, so set the picker at least as wide as the filter.
2. Find the stream¶
Start by finding out what the stream you want is called. This lists the 20 streams that logged the most in the last hour:
The name's form tells you the source.
stream_name |
Source | Example |
|---|---|---|
container-<container> |
A container's output | container-core-ntfy |
<unit> |
The journal, for that systemd unit | sshd.service |
host- and a file name |
A .log file under /var/log |
host-audit-audit.log |
syslog- and the sender |
A device sending syslog to port 5140 | syslog-172.16.7.1 |
A container's name starts with its stack's project, so the same service on two hosts has the same stream name. Step 4 tells them apart.
3. Read one source¶
For a container, give its stream in braces. This returns the last 15 minutes of ntfy's output:
For a service of the host itself, name its unit. This returns the last hour of the SSH daemon's journal:
The braces take the same matchers as a metrics query, so =~ matches a regular expression. This returns every container of the victoriametrics project:
4. Narrow to one host¶
Every line carries a host field. For a line from the journal it is the host's own name. For a container's line it is the name of the Vector container that read it, which has the host's name inside it. A word filter matches both:
5. Filter by level and text¶
Vector settles each line's severity into the field level, in capitals: ERROR, WARN, INFO, DEBUG, or UNKNOWN when it found none. This returns every error in the last hour, from anything:
A quoted phrase is looked for in the text of the line. Filters separated by spaces must all match:
To see which sources are producing the errors, count them by stream:
A line the parser could not read keeps the level UNKNOWN, whatever it says. When a search by level finds nothing, search for the text.
6. Search Traefik's access log¶
Traefik's access log has fields of its own and no stream_name. Its lines are the ones with a RouterName, and each is one request. A line is stored under the time its request started, so a _time filter selects by when the request was made.
| Field | Holds |
|---|---|
RouterName, ServiceName |
The route that matched and the service it sent the request to |
DownstreamStatus |
The status code returned to the client, as a number |
RequestMethod, RequestPath |
The request |
Duration |
The time taken, in nanoseconds |
level |
error for a status of 500 or more, warn for 400 or more, otherwise info. Lower case, unlike every other source |
This returns every request in the last hour that ended in a server error:
This counts the last hour's requests by route and status:
_time:1h RouterName:* | stats by (RouterName, DownstreamStatus) count() as requests | sort by (requests desc)
Cookies and the Authorization header are replaced with REDACTED before a line leaves its host.
When a search finds nothing¶
| Check | How |
|---|---|
| The time range | Widen the page's picker and the _time filter together |
| That anything arrives | Run _time:5m with no other filter. Lines from every host scroll past |
| The stream's name | Run the query from step 2 again and copy the name from its result |
| The host's agents | See When it goes wrong |
VictoriaLogs keeps a year of logs, or 5 GB, whichever is reached first. A busy fleet reaches the size limit long before the year.
What's next¶
A search you run often can become an alert. See Adding an alert rule.
For the rest of the language, see the LogsQL documentation.
Not yet confirmed¶
- The whole page. No log has been shipped by a running fleet, so no field name or value has been seen in VictoriaLogs. Every one is read from
containers/vector/config/vector-system.ymlin fleet-stacks. - The
hostfield. Its values are what Vector's sources document, and the filter in step 4 depends on the Vector container's name holding the host's name. - The example stream names for a file and for syslog, which are built from the config's rules and not observed.
- The labels in VictoriaLogs' page and in Grafana's Explore.
- How Traefik's access log is stored. Vector's sink names an index,
traefik-access, which the page assumes VictoriaLogs does not keep as a thing to filter on, so it finds the lines byRouterNameinstead. - The time a Traefik line is stored under. Vector's sink sets
_time_fieldtotimestamp, the field its transform fills from the request's start time, so_timeis expected to be the time of the request. No line has been stored to check.