influxdb-rails
influxdb-rails copied to clipboard
Group metrics per request (breakdown table)
The request id is a unique UUID and therefore we store it in a field. Unfortunately fields can not be grouped in InfluxDB. For ActiveRecord SQL, the data schema looks for instance like this
requed_id | name | location | value |
---|---|---|---|
123-456 | Post Load | PostController#index | 100 |
123-456 | Post Load | PostController#index | 80 |
123-456 | User Load | PostController#index | 100 |
With this data schema we can only calculate the total count of all requests, total averages etc.
However, I would like to count on a per request basis, something like this:
requed_id | name | location | count | avg_value |
---|---|---|---|---|
123-456 | Post Load | PostController#index | 2 | 90 |
123-456 | User Load | PostController#index | 1 | 100 |
This has several advantages
- Better performance because we have precalculated values
- We can spot issues like n+1 queries or missing memoization
I thought about several options
-
Continuous queries We use a continuous query to downsample our metrics every X seconds. I haven't looked into it in detail but I assume we will run into the same limitation that we can not group by a field in InfluxDB.
-
Group in gem We would need to do the grouping as pre processing and then write another metric to InfluxDB. We already have
Current
so we could just store everything in a hash there and then write it together withprocess_action.action_controller
. So for ActiveRecord SQL we could just do something like
# Store all SQL queries in Current attributes
Current.summary = { }
Current.summary["User Load"] ||= []
Current.summary["User Load"] << 100
Current.summary
# => { "User Load" => [100], "Post Load" => [100, 80] }
# Store the metrics with process_action.action_controller
Current.summary.each do |key, value|
count = value.length
avg_value = value / count
Metric.new(
hook_name: "summary",
values: { count: count, avg_value: avg_value }
).write
end