Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
build
dist
.vscode
.vscode
dashboards/openstack-libvirt-dashboard/vendor
dashboards/openstack-libvirt-dashboard/jsonnetfile.lock.json
15 changes: 15 additions & 0 deletions dashboards/openstack-libvirt-dashboard/jsonnetfile.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"version": 1,
"dependencies": [
{
"source": {
"git": {
"remote": "https://github.com/grafana/grafonnet.git",
"subdir": "gen/grafonnet-v11.4.0"
}
},
"version": "main"
}
],
"legacyImports": true
}
124 changes: 124 additions & 0 deletions dashboards/openstack-libvirt-dashboard/lib/query.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
local g = import 'github.com/grafana/grafonnet/gen/grafonnet-v11.4.0/main.libsonnet';

{
power_state: g.query.prometheus.new('${datasource}', 'libvirt_domain_info_state{domain="$vm_id"}'),
cpu_allocated: g.query.prometheus.new('${datasource}', 'libvirt_domain_vcpu_current{domain="$vm_id"}'),
memory_allocated: g.query.prometheus.new('${datasource}', 'libvirt_domain_memory_stats_maximum_bytes{domain="$vm_id"}'),
disk_count: g.query.prometheus.new('${datasource}', 'count(libvirt_domain_block_stats_info{domain="$vm_id"})'),
network_port_count: g.query.prometheus.new('${datasource}', 'count(libvirt_domain_interface_stats_info{domain="$vm_id"})'),

cpu_usage_percentage: g.query.prometheus.new(
'${datasource}',
'(rate(libvirt_domain_info_cpu_time_seconds_total{domain="$vm_id"}[5m])/libvirt_domain_vcpu_current{domain="$vm_id"}) * 100'
) + g.query.prometheus.withLegendFormat('{{domain}}'),
cpu_steal_pecentage: g.query.prometheus.new(
'${datasource}',
'(sum by (domain) (rate(libvirt_domain_vcpu_delay_seconds_total{domain="$vm_id"}[5m]))/sum by (domain) (rate(libvirt_domain_vcpu_time_seconds_total{domain="$vm_id"}[5m]))) * 100'
) + g.query.prometheus.withLegendFormat('{{domain}}'),

memory_usage_percentage: g.query.prometheus.new(
'${datasource}',
'libvirt_domain_memory_stats_used_percent{domain="$vm_id"}'
) + g.query.prometheus.withLegendFormat('{{domain}}'),

memory_swap_bytes: g.query.prometheus.new(
'${datasource}',
'sum by (domain)(\n rate(libvirt_domain_memory_stats_swap_in_bytes{domain="$vm_id"}[2m])\n+\n rate(libvirt_domain_memory_stats_swap_out_bytes{domain="$vm_id"}[2m])\n)\n'
) + g.query.prometheus.withLegendFormat('{{domain}}'),

storage_iops_total: g.query.prometheus.new(
'${datasource}',
'rate(\n sum by (domain, target_device) (\n {__name__=~"libvirt_domain_block_stats_(read|write)_requests_total", domain="$vm_id"} > 0\n )[2m:30s]\n)'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

storage_iops_read: g.query.prometheus.new(
'${datasource}',
'rate(\n sum by (domain, target_device) (\n {__name__=~"libvirt_domain_block_stats_read_requests_total", domain="$vm_id"} > 0\n )[2m:30s]\n)'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

storage_iops_write: g.query.prometheus.new(
'${datasource}',
'rate(\n sum by (domain, target_device) (\n {__name__=~"libvirt_domain_block_stats_write_requests_total", domain="$vm_id"} > 0\n )[2m:30s]\n)'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

storage_throughput_total: g.query.prometheus.new(
'${datasource}',
'rate(\n sum by (domain, target_device) (\n {__name__=~"libvirt_domain_block_stats_(read|write)_bytes_total", domain="$vm_id"} > 0\n )[2m:30s]\n)'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

storage_throughput_read: g.query.prometheus.new(
'${datasource}',
'rate(\n sum by (domain, target_device) (\n {__name__=~"libvirt_domain_block_stats_read_bytes_total", domain="$vm_id"} > 0\n )[2m:30s]\n)'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

storage_throughput_write: g.query.prometheus.new(
'${datasource}',
'rate(\n sum by (domain, target_device) (\n {__name__=~"libvirt_domain_block_stats_write_bytes_total", domain="$vm_id"} > 0\n )[2m:30s]\n)'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

storage_latency_read: g.query.prometheus.new(
'${datasource}',
'rate(\n sum by (domain, target_device) (\n {__name__=~"libvirt_domain_block_stats_read_time_seconds_total", domain="$vm_id"} > 0\n )[2m:30s]\n)\n/\nrate(\n sum by (domain, target_device) (\n {__name__=~"libvirt_domain_block_stats_read_requests_total", domain="$vm_id"} > 0\n )[2m:30s]\n) * 1000'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

storage_latency_write: g.query.prometheus.new(
'${datasource}',
'rate(\n sum by (domain, target_device) (\n {__name__=~"libvirt_domain_block_stats_write_time_seconds_total", domain="$vm_id"} > 0\n )[2m:30s]\n)\n/\nrate(\n sum by (domain, target_device) (\n {__name__=~"libvirt_domain_block_stats_write_requests_total", domain="$vm_id"} > 0\n )[2m:30s]\n) * 1000'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

storage_average_block_size: g.query.prometheus.new(
'${datasource}',
'rate(\n sum by (domain, target_device) (\n {__name__=~"libvirt_domain_block_stats_(read|write)_bytes_total", domain="$vm_id"} > 0\n )[2m:30s]\n)\n/\nrate(\n sum by (domain, target_device) (\n {__name__=~"libvirt_domain_block_stats_(read|write)_requests_total", domain="$vm_id"} > 0\n )[2m:30s]\n)'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

newtork_throughput_total: g.query.prometheus.new(
'${datasource}',
'sum by (domain, target_device)(\n rate(libvirt_domain_interface_stats_receive_bytes_total{domain="$vm_id"}[2m])\n+\n rate(libvirt_domain_interface_stats_transmit_bytes_total{domain="$vm_id"}[2m])\n)\n'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

newtork_throughput_receive: g.query.prometheus.new(
'${datasource}',
'sum by (domain, target_device)(\n rate(libvirt_domain_interface_stats_receive_bytes_total{domain="$vm_id"}[2m])\n)\n'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

newtork_throughput_transmit: g.query.prometheus.new(
'${datasource}',
'sum by (domain, target_device)(\n rate(libvirt_domain_interface_stats_transmit_bytes_total{domain="$vm_id"}[2m])\n)\n'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

network_packet_total: g.query.prometheus.new(
'${datasource}',
'sum by (domain, target_device)(\n rate(libvirt_domain_interface_stats_transmit_packets_total{domain="$vm_id"}[2m])\n+\n rate(libvirt_domain_interface_stats_receive_packets_total{domain="$vm_id"}[2m])\n)\n'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

network_packet_receive: g.query.prometheus.new(
'${datasource}',
'sum by (domain, target_device)(\n rate(libvirt_domain_interface_stats_receive_packets_total{domain="$vm_id"}[2m])\n)\n'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

network_packet_transmit: g.query.prometheus.new(
'${datasource}',
'sum by (domain, target_device)(\n rate(libvirt_domain_interface_stats_transmit_packets_total{domain="$vm_id"}[2m])\n)\n'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

network_errors_receive: g.query.prometheus.new(
'${datasource}',
'sum by (domain, target_device)(\n rate(libvirt_domain_interface_stats_receive_errors_total{domain="$vm_id"}[2m])\n)\n'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

network_errors_transmit: g.query.prometheus.new(
'${datasource}',
'sum by (domain, target_device)(\n rate(libvirt_domain_interface_stats_transmit_errors_total{domain="$vm_id"}[2m])\n)\n'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

network_drops_receive: g.query.prometheus.new(
'${datasource}',
'sum by (domain, target_device)(\n rate(libvirt_domain_interface_stats_receive_drops_total{domain="$vm_id"}[2m])\n)'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

network_drops_transmit: g.query.prometheus.new(
'${datasource}',
'sum by (domain, target_device)(\n rate(libvirt_domain_interface_stats_receive_drops_total{domain="$vm_id"}[2m])\n)'
) + g.query.prometheus.withLegendFormat('{{target_device}}'),

}
47 changes: 47 additions & 0 deletions dashboards/openstack-libvirt-dashboard/lib/templates.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
local g = import 'github.com/grafana/grafonnet/gen/grafonnet-v11.4.0/main.libsonnet';

{
// A specialized Stat panel for this specific dashboard context
vmStatPanel(title, targets, description='', unit=null, colorMode='value', mappings=[], noThresholds=false)::
local base = g.panel.stat.new(title)
+ g.panel.stat.queryOptions.withDatasource('prometheus', '${datasource}')
+ g.panel.stat.queryOptions.withTargets(targets)
+ g.panel.stat.options.withGraphMode('area')
+ g.panel.stat.options.reduceOptions.withCalcs(['lastNotNull'])
+ g.panel.stat.standardOptions.withNoValue('Requires VM to be powered-on');

// Manual Field Config for Thresholds
local thresholdConfig = if noThresholds then
{
fieldConfig: {
defaults: {
thresholds: {
mode: 'absolute',
// A single step with null value = solid color everywhere
steps: [{ color: 'green', value: 0 }],
},
},
},
}
else
{};

base
+ g.panel.stat.options.withColorMode(colorMode)
+ thresholdConfig // Apply the manual config here
+ (if description != '' then g.panel.stat.panelOptions.withDescription(description) else {})
+ (if unit != null then g.panel.stat.standardOptions.withUnit(unit) else {})
+ (if std.length(mappings) > 0 then g.panel.stat.standardOptions.withMappings(mappings) else {}),


timeSeriesPanel(title, targets, unit=null, description='', noThresholds=false)::
g.panel.timeSeries.new(title)
+ g.panel.timeSeries.queryOptions.withDatasource('prometheus', '${datasource}')
+ g.panel.timeSeries.queryOptions.withTargets(targets)
+ g.panel.timeSeries.options.legend.withDisplayMode('list')
+ g.panel.timeSeries.options.legend.withPlacement('bottom')
+ g.panel.timeSeries.options.tooltip.withMode('multi')
+ g.panel.timeSeries.standardOptions.withNoValue('No Data')
+ (if unit != null then g.panel.timeSeries.standardOptions.withUnit(unit) else {})
+ (if description != '' then g.panel.timeSeries.panelOptions.withDescription(description) else {}),
}
25 changes: 25 additions & 0 deletions dashboards/openstack-libvirt-dashboard/lib/variables.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
local g = import 'github.com/grafana/grafonnet/gen/grafonnet-v11.4.0/main.libsonnet';

{
// datasource:
// g.dashboard.variable.datasource.new('datasource', 'prometheus')
// + g.dashboard.variable.datasource.generalOptions.withLabel('DataSource'),

project:
g.dashboard.variable.query.new('project_name', 'label_values(libvirt_domain_openstack_info, project_name)')
+ g.dashboard.variable.query.withDatasource('prometheus', '${datasource}')
+ g.dashboard.variable.query.refresh.onLoad()
+ g.dashboard.variable.query.generalOptions.withLabel('Project Name'),

vmName:
g.dashboard.variable.query.new('vm_name', 'label_values(libvirt_domain_openstack_info{project_name="$project_name"}, instance_name)')
+ g.dashboard.variable.query.withDatasource('prometheus', '${datasource}')
+ g.dashboard.variable.query.refresh.onLoad()
+ g.dashboard.variable.query.generalOptions.withLabel('VM Name'),

vmId:
g.dashboard.variable.query.new('vm_id', 'label_values(libvirt_domain_openstack_info{instance_name="$vm_name", project_name="$project_name"}, instance_id)')
+ g.dashboard.variable.query.withDatasource('prometheus', '${datasource}')
+ g.dashboard.variable.query.refresh.onLoad()
+ g.dashboard.variable.query.generalOptions.withLabel('VM ID'),
}
Loading