Feat: Add cloud plugin cost management to admin section (#76547)
* feat: add cost management to admin and put adaptive metrics and log volume under it * test: fix applinks test * chore: fix lint error * remove "new" from feature toggle description --------- Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com>
This commit is contained in:
co-authored by
Ashley Harrison
parent
0f7233bdf6
commit
de1ed216f4
@@ -152,6 +152,7 @@ Experimental features might be changed or removed without prior notice.
|
||||
| `awsDatasourcesNewFormStyling` | Applies new form styling for configuration and query editors in AWS plugins |
|
||||
| `cachingOptimizeSerializationMemoryUsage` | If enabled, the caching backend gradually serializes query responses for the cache, comparing against the configured `[caching]max_value_mb` value as it goes. This can can help prevent Grafana from running out of memory while attempting to cache very large query responses. |
|
||||
| `pluginsInstrumentationStatusSource` | Include a status source label for plugin request metrics and logs |
|
||||
| `costManagementUi` | Toggles the display of the cost management ui plugin |
|
||||
|
||||
## Development feature toggles
|
||||
|
||||
|
||||
@@ -146,4 +146,5 @@ export interface FeatureToggles {
|
||||
cachingOptimizeSerializationMemoryUsage?: boolean;
|
||||
panelTitleSearchInV1?: boolean;
|
||||
pluginsInstrumentationStatusSource?: boolean;
|
||||
costManagementUi?: boolean;
|
||||
}
|
||||
|
||||
@@ -26,4 +26,5 @@ const (
|
||||
grafanaOperatorExperienceSquad codeowner = "@grafana/grafana-operator-experience-squad"
|
||||
enterpriseDatasourcesSquad codeowner = "@grafana/enterprise-datasources"
|
||||
grafanaSharingSquad codeowner = "@grafana/sharing-squad"
|
||||
grafanaDatabasesFrontend codeowner = "@grafana/databases-frontend"
|
||||
)
|
||||
|
||||
@@ -897,5 +897,12 @@ var (
|
||||
Stage: FeatureStageExperimental,
|
||||
Owner: grafanaPluginsPlatformSquad,
|
||||
},
|
||||
{
|
||||
Name: "costManagementUi",
|
||||
Description: "Toggles the display of the cost management ui plugin",
|
||||
Stage: FeatureStageExperimental,
|
||||
FrontendOnly: false,
|
||||
Owner: grafanaDatabasesFrontend,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -127,3 +127,4 @@ awsDatasourcesNewFormStyling,experimental,@grafana/aws-datasources,false,false,f
|
||||
cachingOptimizeSerializationMemoryUsage,experimental,@grafana/grafana-operator-experience-squad,false,false,false,false
|
||||
panelTitleSearchInV1,experimental,@grafana/backend-platform,true,false,false,false
|
||||
pluginsInstrumentationStatusSource,experimental,@grafana/plugins-platform-backend,false,false,false,false
|
||||
costManagementUi,experimental,@grafana/databases-frontend,false,false,false,false
|
||||
|
||||
|
@@ -518,4 +518,8 @@ const (
|
||||
// FlagPluginsInstrumentationStatusSource
|
||||
// Include a status source label for plugin request metrics and logs
|
||||
FlagPluginsInstrumentationStatusSource = "pluginsInstrumentationStatusSource"
|
||||
|
||||
// FlagCostManagementUi
|
||||
// Toggles the display of the cost management ui plugin
|
||||
FlagCostManagementUi = "costManagementUi"
|
||||
)
|
||||
|
||||
@@ -90,7 +90,9 @@ func (root *NavTreeRoot) RemoveSection(node *NavLink) {
|
||||
func (root *NavTreeRoot) FindById(id string) *NavLink {
|
||||
return FindById(root.Children, id)
|
||||
}
|
||||
|
||||
func (root *NavTreeRoot) FindByURL(url string) *NavLink {
|
||||
return FindByURL(root.Children, url)
|
||||
}
|
||||
func (root *NavTreeRoot) Sort() {
|
||||
Sort(root.Children)
|
||||
}
|
||||
@@ -192,6 +194,26 @@ func (root *NavTreeRoot) ApplyAdminIA(navAdminSubsectionsEnabled bool) {
|
||||
authenticationNode.IsSection = true
|
||||
adminNodeLinks = append(adminNodeLinks, authenticationNode)
|
||||
}
|
||||
|
||||
costManagementNode := root.FindById("plugin-page-grafana-costmanagementui-app")
|
||||
|
||||
if costManagementNode != nil {
|
||||
adminNodeLinks = append(adminNodeLinks, costManagementNode)
|
||||
}
|
||||
|
||||
costManagementMetricsNode := root.FindByURL("/a/grafana-costmanagementui-app/metrics")
|
||||
adaptiveMetricsNode := root.FindById("plugin-page-grafana-adaptive-metrics-app")
|
||||
|
||||
if costManagementMetricsNode != nil && adaptiveMetricsNode != nil {
|
||||
costManagementMetricsNode.Children = append(costManagementMetricsNode.Children, adaptiveMetricsNode)
|
||||
}
|
||||
|
||||
costManagementLogsNode := root.FindByURL("/a/grafana-costmanagementui-app/logs")
|
||||
logVolumeExplorerNode := root.FindById("plugin-page-grafana-logvolumeexplorer-app")
|
||||
|
||||
if costManagementLogsNode != nil && logVolumeExplorerNode != nil {
|
||||
costManagementLogsNode.Children = append(costManagementLogsNode.Children, logVolumeExplorerNode)
|
||||
}
|
||||
} else {
|
||||
adminNodeLinks = AppendIfNotNil(adminNodeLinks, root.FindById("datasources"))
|
||||
adminNodeLinks = AppendIfNotNil(adminNodeLinks, root.FindById("plugins"))
|
||||
@@ -245,3 +267,17 @@ func FindById(nodes []*NavLink, id string) *NavLink {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindByURL(nodes []*NavLink, url string) *NavLink {
|
||||
for _, child := range nodes {
|
||||
if child.Url == url {
|
||||
return child
|
||||
} else if len(child.Children) > 0 {
|
||||
if found := FindByURL(child.Children, url); found != nil {
|
||||
return found
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -33,4 +33,15 @@ func TestNavTreeRoot(t *testing.T) {
|
||||
require.Equal(t, "1", treeRoot.Children[0].Id)
|
||||
require.Equal(t, "4", treeRoot.Children[1].Id)
|
||||
})
|
||||
t.Run("FindByURL is able to find a navItem by url", func(t *testing.T) {
|
||||
treeRoot := NavTreeRoot{
|
||||
Children: []*NavLink{
|
||||
{Id: "1", Url: "/"},
|
||||
{Id: "2", Url: "/org"},
|
||||
{Id: "3", Url: "/org/users"},
|
||||
},
|
||||
}
|
||||
require.Equal(t, "2", treeRoot.FindByURL("/org").Id)
|
||||
require.Equal(t, "3", treeRoot.FindByURL("/org/users").Id)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -262,10 +262,18 @@ func (s *ServiceImpl) readNavigationSettings() {
|
||||
"grafana-incident-app": {SectionID: navtree.NavIDAlertsAndIncidents, SortWeight: 2, Text: "Incidents"},
|
||||
"grafana-ml-app": {SectionID: navtree.NavIDAlertsAndIncidents, SortWeight: 3, Text: "Machine Learning"},
|
||||
"grafana-cloud-link-app": {SectionID: navtree.NavIDCfg},
|
||||
"grafana-costmanagementui-app": {SectionID: navtree.NavIDCfg, Text: "Cost management"},
|
||||
"grafana-easystart-app": {SectionID: navtree.NavIDRoot, SortWeight: navtree.WeightApps + 1, Text: "Connections", Icon: "adjust-circle"},
|
||||
"k6-app": {SectionID: navtree.NavIDRoot, SortWeight: navtree.WeightAlertsAndIncidents + 1, Text: "Performance testing", Icon: "k6"},
|
||||
}
|
||||
|
||||
if s.features.IsEnabled(featuremgmt.FlagNavAdminSubsections) && s.features.IsEnabled(featuremgmt.FlagCostManagementUi) {
|
||||
// if cost management is enabled we want to nest adaptive metrics and log volume explorer under that plugin
|
||||
// in the admin section
|
||||
s.navigationAppConfig["grafana-adaptive-metrics-app"] = NavigationAppConfig{SectionID: navtree.NavIDCfg}
|
||||
s.navigationAppConfig["grafana-logvolumeexplorer-app"] = NavigationAppConfig{SectionID: navtree.NavIDCfg}
|
||||
}
|
||||
|
||||
s.navigationAppPathConfig = map[string]NavigationAppConfig{
|
||||
"/a/grafana-auth-app": {SectionID: navtree.NavIDCfg, SortWeight: 7},
|
||||
}
|
||||
|
||||
@@ -360,7 +360,8 @@ func TestAddAppLinks(t *testing.T) {
|
||||
func TestReadingNavigationSettings(t *testing.T) {
|
||||
t.Run("Should include defaults", func(t *testing.T) {
|
||||
service := ServiceImpl{
|
||||
cfg: setting.NewCfg(),
|
||||
cfg: setting.NewCfg(),
|
||||
features: featuremgmt.WithFeatures(),
|
||||
}
|
||||
|
||||
_, _ = service.cfg.Raw.NewSection("navigation.app_sections")
|
||||
@@ -371,7 +372,8 @@ func TestReadingNavigationSettings(t *testing.T) {
|
||||
|
||||
t.Run("Can add additional overrides via ini system", func(t *testing.T) {
|
||||
service := ServiceImpl{
|
||||
cfg: setting.NewCfg(),
|
||||
cfg: setting.NewCfg(),
|
||||
features: featuremgmt.WithFeatures(),
|
||||
}
|
||||
|
||||
appSections, _ := service.cfg.Raw.NewSection("navigation.app_sections")
|
||||
|
||||
Reference in New Issue
Block a user