Commit a782b882 authored by Mayra Cabrera's avatar Mayra Cabrera

Merge branch '218649-add-pod-health-dashboard' into 'master'

Make Pod health dashboard available to users

See merge request gitlab-org/gitlab!37482
parents ad4248a4 857c9f51
...@@ -4,10 +4,29 @@ module Metrics ...@@ -4,10 +4,29 @@ module Metrics
module Dashboard module Dashboard
class PodDashboardService < ::Metrics::Dashboard::PredefinedDashboardService class PodDashboardService < ::Metrics::Dashboard::PredefinedDashboardService
DASHBOARD_PATH = 'config/prometheus/pod_metrics.yml' DASHBOARD_PATH = 'config/prometheus/pod_metrics.yml'
DASHBOARD_NAME = 'Pod Health' DASHBOARD_NAME = N_('K8s pod health')
# SHA256 hash of dashboard content # SHA256 hash of dashboard content
DASHBOARD_VERSION = 'f12f641d2575d5dcb69e2c633ff5231dbd879ad35020567d8fc4e1090bfdb4b4' DASHBOARD_VERSION = '0515db7a99078a2423b037f99251ba16bd163603c0a30229ae8aa7386e96421c'
SEQUENCE = [
STAGES::MetricEndpointInserter,
STAGES::VariableEndpointInserter,
STAGES::PanelIdsInserter,
STAGES::Sorter
].freeze
class << self
def all_dashboard_paths(_project)
[{
path: DASHBOARD_PATH,
display_name: _(DASHBOARD_NAME),
default: false,
system_dashboard: false,
out_of_the_box_dashboard: out_of_the_box_dashboard?
}]
end
end
private private
......
---
title: Add a new K8s Pod health metrics dashboard
merge_request: 37482
author:
type: added
dashboard: 'Pod metrics' dashboard: 'K8s pod health'
priority: 10 priority: 2
templating:
variables:
pod:
label: 'Pod name'
type: metric_label_values
options:
series_selector: 'container_memory_working_set_bytes'
label: 'pod'
panel_groups: panel_groups:
- group: CPU metrics - group: CPU metrics
panels: panels:
...@@ -8,9 +18,9 @@ panel_groups: ...@@ -8,9 +18,9 @@ panel_groups:
y_label: "Cores per pod" y_label: "Cores per pod"
metrics: metrics:
- id: pod_cpu_usage_seconds_total - id: pod_cpu_usage_seconds_total
query_range: 'rate(container_cpu_usage_seconds_total{pod_name="{{pod_name}}",container_name="POD"}[5m])' query_range: 'rate(container_cpu_usage_seconds_total{pod="{{pod}}",container="POD"}[5m])'
unit: "cores" unit: "cores"
label: pod_name label: pod
- group: Memory metrics - group: Memory metrics
panels: panels:
- title: "Memory usage working set" - title: "Memory usage working set"
...@@ -18,9 +28,9 @@ panel_groups: ...@@ -18,9 +28,9 @@ panel_groups:
y_label: "Working set memory (MiB)" y_label: "Working set memory (MiB)"
metrics: metrics:
- id: pod_memory_working_set - id: pod_memory_working_set
query_range: 'container_memory_working_set_bytes{pod_name="{{pod_name}}",container_name="POD"}/1024/1024' query_range: 'container_memory_working_set_bytes{pod="{{pod}}",container="POD"}/1024/1024'
unit: "MiB" unit: "MiB"
label: pod_name label: pod
- group: Network metrics - group: Network metrics
panels: panels:
- title: "Network Receive (In)" - title: "Network Receive (In)"
...@@ -28,17 +38,17 @@ panel_groups: ...@@ -28,17 +38,17 @@ panel_groups:
y_label: "Received (KiB/sec)" y_label: "Received (KiB/sec)"
metrics: metrics:
- id: pod_network_receive - id: pod_network_receive
query_range: 'rate(container_network_receive_bytes_total{pod_name="{{pod_name}}",container_name="POD"}[5m])/1024' query_range: 'rate(container_network_receive_bytes_total{pod="{{pod}}",container="POD"}[5m])/1024'
unit: "KiB / sec" unit: "KiB / sec"
label: pod_name label: pod
- title: "Network Transmit (Out)" - title: "Network Transmit (Out)"
type: "line-chart" type: "line-chart"
y_label: "Transmitted (KiB/sec)" y_label: "Transmitted (KiB/sec)"
metrics: metrics:
- id: pod_network_transmit - id: pod_network_transmit
query_range: 'rate(container_network_transmit_bytes_total{pod_name="{{pod_name}}",container_name="POD"}[5m])/1024' query_range: 'rate(container_network_transmit_bytes_total{pod="{{pod}}",container="POD"}[5m])/1024'
unit: "KiB / sec" unit: "KiB / sec"
label: pod_name label: pod
- group: Disk metrics - group: Disk metrics
panels: panels:
- title: "Disk Reads" - title: "Disk Reads"
...@@ -46,14 +56,14 @@ panel_groups: ...@@ -46,14 +56,14 @@ panel_groups:
y_label: "Disk reads (KiB/sec)" y_label: "Disk reads (KiB/sec)"
metrics: metrics:
- id: pod_disk_reads - id: pod_disk_reads
query_range: 'rate(container_fs_reads_bytes_total{container_name="POD",pod_name="{{pod_name}}"}[5m])/1024' query_range: 'rate(container_fs_reads_bytes_total{container="POD",pod="{{pod}}"}[5m])/1024'
unit: "KiB / sec" unit: "KiB / sec"
label: pod_name label: pod
- title: "Disk Writes" - title: "Disk Writes"
type: "line-chart" type: "line-chart"
y_label: "Disk writes (KiB/sec)" y_label: "Disk writes (KiB/sec)"
metrics: metrics:
- id: pod_disk_writes - id: pod_disk_writes
query_range: 'rate(container_fs_writes_bytes_total{container_name="POD",pod_name="{{pod_name}}"}[5m])/1024' query_range: 'rate(container_fs_writes_bytes_total{container="POD",pod="{{pod}}"}[5m])/1024'
unit: "KiB / sec" unit: "KiB / sec"
label: pod_name label: pod
...@@ -14,10 +14,7 @@ module Gitlab ...@@ -14,10 +14,7 @@ module Gitlab
::Metrics::Dashboard::SelfMonitoringDashboardService, ::Metrics::Dashboard::SelfMonitoringDashboardService,
# This dashboard is displayed on the K8s cluster settings health page. # This dashboard is displayed on the K8s cluster settings health page.
::Metrics::Dashboard::ClusterDashboardService, ::Metrics::Dashboard::ClusterDashboardService
# This dashboard is not yet ready for the world.
::Metrics::Dashboard::PodDashboardService
].freeze ].freeze
class << self class << self
...@@ -72,9 +69,11 @@ module Gitlab ...@@ -72,9 +69,11 @@ module Gitlab
# display_name: String, # display_name: String,
# default: Boolean }] # default: Boolean }]
def find_all_paths(project) def find_all_paths(project)
user_facing_dashboard_services(project).flat_map do |service| dashboards = user_facing_dashboard_services(project).flat_map do |service|
service.all_dashboard_paths(project) service.all_dashboard_paths(project)
end end
Gitlab::Utils.stable_sort_by(dashboards) { |dashboard| dashboard[:display_name].downcase }
end end
private private
......
...@@ -13641,6 +13641,9 @@ msgstr "" ...@@ -13641,6 +13641,9 @@ msgstr ""
msgid "Just me" msgid "Just me"
msgstr "" msgstr ""
msgid "K8s pod health"
msgstr ""
msgid "Keep divergent refs" msgid "Keep divergent refs"
msgstr "" msgstr ""
......
...@@ -165,13 +165,14 @@ RSpec.describe MetricsDashboard do ...@@ -165,13 +165,14 @@ RSpec.describe MetricsDashboard do
it 'adds starred dashboard information and sorts the list' do it 'adds starred dashboard information and sorts the list' do
all_dashboards = json_response['all_dashboards'].map { |dashboard| dashboard.slice('display_name', 'starred', 'user_starred_path') } all_dashboards = json_response['all_dashboards'].map { |dashboard| dashboard.slice('display_name', 'starred', 'user_starred_path') }
expected_response = [ expected_response = [
{ "display_name" => "Overview", "starred" => false, 'user_starred_path' => api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: 'config/prometheus/common_metrics.yml' }) },
{ "display_name" => "anomaly.yml", "starred" => false, 'user_starred_path' => api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: '.gitlab/dashboards/anomaly.yml' }) }, { "display_name" => "anomaly.yml", "starred" => false, 'user_starred_path' => api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: '.gitlab/dashboards/anomaly.yml' }) },
{ "display_name" => "errors.yml", "starred" => true, 'user_starred_path' => api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: '.gitlab/dashboards/errors.yml' }) }, { "display_name" => "errors.yml", "starred" => true, 'user_starred_path' => api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: '.gitlab/dashboards/errors.yml' }) },
{ "display_name" => "K8s pod health", "starred" => false, 'user_starred_path' => api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: 'config/prometheus/pod_metrics.yml' }) },
{ "display_name" => "Overview", "starred" => false, 'user_starred_path' => api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: 'config/prometheus/common_metrics.yml' }) },
{ "display_name" => "test.yml", "starred" => true, 'user_starred_path' => api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: '.gitlab/dashboards/test.yml' }) } { "display_name" => "test.yml", "starred" => true, 'user_starred_path' => api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: '.gitlab/dashboards/test.yml' }) }
] ]
expect(all_dashboards).to eql expected_response expect(all_dashboards).to eq(expected_response)
end end
end end
end end
......
...@@ -8,7 +8,7 @@ RSpec.describe MetricsDashboard, '(JavaScript fixtures)', type: :controller do ...@@ -8,7 +8,7 @@ RSpec.describe MetricsDashboard, '(JavaScript fixtures)', type: :controller do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:namespace) { create(:namespace, name: 'monitoring' )} let_it_be(:namespace) { create(:namespace, name: 'monitoring' )}
let_it_be(:project) { project_with_dashboard_namespace('.gitlab/dashboards/test.yml', namespace: namespace) } let_it_be(:project) { project_with_dashboard_namespace('.gitlab/dashboards/test.yml', nil, namespace: namespace) }
let_it_be(:environment) { create(:environment, id: 1, project: project) } let_it_be(:environment) { create(:environment, id: 1, project: project) }
let_it_be(:params) { { environment: environment } } let_it_be(:params) { { environment: environment } }
......
...@@ -143,19 +143,41 @@ RSpec.describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store ...@@ -143,19 +143,41 @@ RSpec.describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store
describe '.find_all_paths' do describe '.find_all_paths' do
let(:all_dashboard_paths) { described_class.find_all_paths(project) } let(:all_dashboard_paths) { described_class.find_all_paths(project) }
let(:system_dashboard) { { path: system_dashboard_path, display_name: 'Overview', default: true, system_dashboard: true, out_of_the_box_dashboard: true } } let(:system_dashboard) { { path: system_dashboard_path, display_name: 'Overview', default: true, system_dashboard: true, out_of_the_box_dashboard: true } }
let(:k8s_pod_health_dashboard) { { path: pod_dashboard_path, display_name: 'K8s pod health', default: false, system_dashboard: false, out_of_the_box_dashboard: true } }
it 'includes only the system dashboard by default' do it 'includes OOTB dashboards by default' do
expect(all_dashboard_paths).to eq([system_dashboard]) expect(all_dashboard_paths).to eq([k8s_pod_health_dashboard, system_dashboard])
end end
context 'when the project contains dashboards' do context 'when the project contains dashboards' do
let(:dashboard_path) { '.gitlab/dashboards/test.yml' } let(:dashboard_content) { fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml') }
let(:project) { project_with_dashboard(dashboard_path) } let(:project) { project_with_dashboards(dashboards) }
let(:dashboards) do
{
'.gitlab/dashboards/metrics.yml' => dashboard_content,
'.gitlab/dashboards/better_metrics.yml' => dashboard_content
}
end
it 'includes system and project dashboards' do it 'includes OOTB and project dashboards' do
project_dashboard = { path: dashboard_path, display_name: 'test.yml', default: false, system_dashboard: false, out_of_the_box_dashboard: false } project_dashboard1 = {
path: '.gitlab/dashboards/metrics.yml',
display_name: 'metrics.yml',
default: false,
system_dashboard: false,
out_of_the_box_dashboard: false
}
project_dashboard2 = {
path: '.gitlab/dashboards/better_metrics.yml',
display_name: 'better_metrics.yml',
default: false,
system_dashboard: false,
out_of_the_box_dashboard: false
}
expect(all_dashboard_paths).to contain_exactly(system_dashboard, project_dashboard) expect(all_dashboard_paths).to eq([project_dashboard2, k8s_pod_health_dashboard, project_dashboard1, system_dashboard])
end end
end end
...@@ -185,7 +207,7 @@ RSpec.describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store ...@@ -185,7 +207,7 @@ RSpec.describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store
out_of_the_box_dashboard: false out_of_the_box_dashboard: false
} }
expect(all_dashboard_paths).to contain_exactly(self_monitoring_dashboard, project_dashboard) expect(all_dashboard_paths).to eq([self_monitoring_dashboard, project_dashboard])
end end
end end
end end
......
...@@ -54,4 +54,20 @@ RSpec.describe Metrics::Dashboard::PodDashboardService, :use_clean_rails_memory_ ...@@ -54,4 +54,20 @@ RSpec.describe Metrics::Dashboard::PodDashboardService, :use_clean_rails_memory_
let(:dashboard_version) { subject.send(:dashboard_version) } let(:dashboard_version) { subject.send(:dashboard_version) }
end end
end end
describe '.all_dashboard_paths' do
it 'returns the dashboard attributes' do
all_dashboards = described_class.all_dashboard_paths(project)
expect(all_dashboards).to eq(
[{
path: described_class::DASHBOARD_PATH,
display_name: described_class::DASHBOARD_NAME,
default: false,
system_dashboard: false,
out_of_the_box_dashboard: true
}]
)
end
end
end end
# frozen_string_literal: true # frozen_string_literal: true
module MetricsDashboardHelpers module MetricsDashboardHelpers
def project_with_dashboard(dashboard_path, dashboard_yml = nil) # @param dashboards [Hash<string, string>] - Should contain a hash where
dashboard_yml ||= fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml') # each key is the path to a dashboard in the repository and each value is
# the dashboard content.
create(:project, :custom_repo, files: { dashboard_path => dashboard_yml }) # Ex: { '.gitlab/dashboards/dashboard1.yml' => fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml') }
def project_with_dashboards(dashboards, project_params = {})
create(:project, :custom_repo, **project_params, files: dashboards)
end end
def project_with_dashboard_namespace(dashboard_path, dashboard_yml = nil) def project_with_dashboard(dashboard_path, dashboard_yml = nil, project_params = {})
dashboard_yml ||= fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml') dashboard_yml ||= fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml')
create(:project, :custom_repo, namespace: namespace, path: 'monitor-project', files: { dashboard_path => dashboard_yml }) project_with_dashboards({ dashboard_path => dashboard_yml }, project_params)
end
def project_with_dashboard_namespace(dashboard_path, dashboard_yml = nil, project_params = {})
project_with_dashboard(dashboard_path, dashboard_yml, project_params.reverse_merge(path: 'monitor-project'))
end end
def delete_project_dashboard(project, user, dashboard_path) def delete_project_dashboard(project, user, dashboard_path)
......
...@@ -62,7 +62,7 @@ end ...@@ -62,7 +62,7 @@ end
RSpec.shared_examples 'dashboard_version contains SHA256 hash of dashboard file content' do RSpec.shared_examples 'dashboard_version contains SHA256 hash of dashboard file content' do
specify do specify do
dashboard = File.read(Rails.root.join(dashboard_path)) dashboard = File.read(Rails.root.join(dashboard_path))
expect(Digest::SHA256.hexdigest(dashboard)).to eq(dashboard_version) expect(dashboard_version).to eq(Digest::SHA256.hexdigest(dashboard))
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment