Transform Logs to Metrics#
Often there are numerical values in log lines that you'd like to extract and chart as a timeseries.
Simple Parsing#
Take this log line for example: A log line field=200
You'd like to extract 200
and use that value.
scenario11.yaml shows the base OpenTelemetry collector configuration we'll use during this exercise. Notice that beyond some host / operating system enrichment and batching, the telemetry is not altered in any way before it hits Dynatrace.
Stop Previous Collector#
If you haven't done so already, stop the previous collector process by pressing Ctrl + C
.
Start Collector#
Run the following command to start the collector:
/workspaces/$RepositoryName/dynatrace-otel-collector --config=/workspaces/$RepositoryName/scenario11.yaml
Generate Log Data#
Open file.log
file and add these log lines then save the file.
A first log line field=200
A second log line field=200
View Data in Dynatrace#
Tip
Right click and "open image in new tab" to see large image
Open a new notebook (or add a DQL section to an existing notebook).
fetch logs
| search("log line")
| fieldsKeep timestamp, content
| sort timestamp desc
Click the Run
button on the DQL tile. You should see the new data.
Extract the Metric#
Adjust your DQL to the following:
fetch logs
| search("log line")
| parse content, """DATA "field="INT:my_value"""
| fieldsKeep timestamp, content, my_value
| sort timestamp desc
Click the Run
button again on the DQL tile. You should see a new column called my_value
with the value of 200
extracted into its own field.
DQL Explained#
Let's take a minute to understand the above DQL:
First, all logs are fetched. Next, the content
field is parsed. The syntax says:
- Expect some data, any data
- Eventually you should find a literal string
field=
- Immediately after the
=
, expect an integer. Extract it as a standalone field and name the fieldmy_value
.
Then, of all the data you have, keep only the timestamp
, content
and my_value
fields.
Finally, sort the log lines in descending timestamp order (most recent at the top).
Charting Metrics as Timeseries#
To chart the above, click the DQL panel, go to Options
and change the visualization to Line
.
There's a problem though, by default Dynatrace splits the timeseries based on the log line.
Using Dynatrace Query Language, you can tell Dynatrace to treat all my_value
results as coming from a single source (ie. do not split by the textual value of the line) and thus you get one line on the chart.
To do so, use this DQL:
fetch logs
| search("log line")
| parse content, """DATA "field="INT:my_value"""
| fieldsKeep timestamp, content, my_value
| makeTimeseries avg(my_value)
As you have probably guessed, this time we're taking average myValue
and creating a timeseries entity from it. This time, there is a single timeseries (line) which is what you want.
Adding Thresholds#
Under the options for the Line
chart, find the Thresholds
submenu and open it.
Here you can set visual thresholds.
Set a warning threshold for any value above 170
and a failure threshold for anything over 190
.
Hover over the bars on the left axis to see the labels: warning
and failure
.
Multiple Series Log Parsing#
Now imagine a more complex log example:
A log line field=170 table=tableA
A log line field=20 table=tableB
A log line field=65 table=tableC
We still want to extract the field
value (170
, 20
and 65
) but this time, these values refer to different "things". Meaning the value of 170
applies to tableA
, the value of 20
applies to tableB
and the value of 65
applies to tableC
.
Obviously, if we somehow mixed this up and applied 170
to tableC
, our charting and alerts would be incorrect.
So, how can we use DQL to achieve this?
First, add these log lines to file.log
and save the file:
A log line field=170 table=tableA
A log line field=20 table=tableB
A log line field=65 table=tableC
Next update the DQL as follows:
fetch logs
| search("log line")
| parse content, """DATA "field="INT:my_value DATA "table="WORD:split_by"""
| fieldsKeep timestamp, content, my_value
| makeTimeseries avg(my_value), by: {split_by}
Dynatrace has extracted the values and grouped by the split_by
field. In other words, grouped by the table name.