chore(perf): Pre-allocate where possible (enable prealloc linter) (#88952)

* chore(perf): Pre-allocate where possible (enable prealloc linter)

Signed-off-by: Dave Henderson <dave.henderson@grafana.com>

* fix TestAlertManagers_buildRedactedAMs

Signed-off-by: Dave Henderson <dave.henderson@grafana.com>

* prealloc a slice that appeared after rebase

Signed-off-by: Dave Henderson <dave.henderson@grafana.com>

---------

Signed-off-by: Dave Henderson <dave.henderson@grafana.com>
This commit is contained in:
Dave Henderson
2024-06-14 14:16:36 -04:00
committed by GitHub
parent e53e6e7caa
commit 6262c56132
43 changed files with 211 additions and 140 deletions
@@ -326,7 +326,7 @@ func (e DatasourcePermissionsService) SetBuiltInRolePermission(ctx context.Conte
// if an OSS/unlicensed instance is upgraded to Enterprise/licensed.
// https://github.com/grafana/identity-access-team/issues/672
func (e DatasourcePermissionsService) SetPermissions(ctx context.Context, orgID int64, resourceID string, commands ...accesscontrol.SetResourcePermissionCommand) ([]accesscontrol.ResourcePermission, error) {
var dbCommands []resourcepermissions.SetResourcePermissionsCommand
dbCommands := make([]resourcepermissions.SetResourcePermissionsCommand, 0, len(commands))
for _, cmd := range commands {
// Only set query permissions for built-in roles; do not set permissions for data sources with * as UID, as this would grant wildcard permissions
if cmd.Permission != "Query" || cmd.BuiltinRole == "" || resourceID == "*" {
@@ -420,21 +420,12 @@ func (s *Service) RunMigration(ctx context.Context, uid string) (*cloudmigration
}
func (s *Service) getMigrationDataJSON(ctx context.Context) (*cloudmigration.MigrateDataRequest, error) {
var migrationDataSlice []cloudmigration.MigrateDataRequestItem
// Data sources
dataSources, err := s.getDataSources(ctx)
if err != nil {
s.log.Error("Failed to get datasources", "err", err)
return nil, err
}
for _, ds := range dataSources {
migrationDataSlice = append(migrationDataSlice, cloudmigration.MigrateDataRequestItem{
Type: cloudmigration.DatasourceDataType,
RefID: ds.UID,
Name: ds.Name,
Data: ds,
})
}
// Dashboards
dashboards, err := s.getDashboards(ctx)
@@ -443,6 +434,26 @@ func (s *Service) getMigrationDataJSON(ctx context.Context) (*cloudmigration.Mig
return nil, err
}
// Folders
folders, err := s.getFolders(ctx)
if err != nil {
s.log.Error("Failed to get folders", "err", err)
return nil, err
}
migrationDataSlice := make(
[]cloudmigration.MigrateDataRequestItem, 0,
len(dataSources)+len(dashboards)+len(folders),
)
for _, ds := range dataSources {
migrationDataSlice = append(migrationDataSlice, cloudmigration.MigrateDataRequestItem{
Type: cloudmigration.DatasourceDataType,
RefID: ds.UID,
Name: ds.Name,
Data: ds,
})
}
for _, dashboard := range dashboards {
dashboard.Data.Del("id")
migrationDataSlice = append(migrationDataSlice, cloudmigration.MigrateDataRequestItem{
@@ -453,13 +464,6 @@ func (s *Service) getMigrationDataJSON(ctx context.Context) (*cloudmigration.Mig
})
}
// Folders
folders, err := s.getFolders(ctx)
if err != nil {
s.log.Error("Failed to get folders", "err", err)
return nil, err
}
for _, f := range folders {
migrationDataSlice = append(migrationDataSlice, cloudmigration.MigrateDataRequestItem{
Type: cloudmigration.FolderDataType,
@@ -468,6 +472,7 @@ func (s *Service) getMigrationDataJSON(ctx context.Context) (*cloudmigration.Mig
Data: f,
})
}
migrationData := &cloudmigration.MigrateDataRequest{
Items: migrationDataSlice,
}
@@ -521,9 +526,9 @@ func (s *Service) getFolders(ctx context.Context) ([]folder.Folder, error) {
return nil, err
}
var result []folder.Folder
for _, folder := range folders {
result = append(result, *folder)
result := make([]folder.Folder, len(folders))
for i, folder := range folders {
result[i] = *folder
}
return result, nil
@@ -535,10 +540,11 @@ func (s *Service) getDashboards(ctx context.Context) ([]dashboards.Dashboard, er
return nil, err
}
var result []dashboards.Dashboard
for _, dashboard := range dashs {
result = append(result, *dashboard)
result := make([]dashboards.Dashboard, len(dashs))
for i, dashboard := range dashs {
result[i] = *dashboard
}
return result, nil
}
+6 -1
View File
@@ -332,12 +332,14 @@ func setupRedisLiveEngine(g *GrafanaLive, node *centrifuge.Node) error {
redisShardConfigs := []centrifuge.RedisShardConfig{
{Address: redisAddress, Password: redisPassword},
}
var redisShards []*centrifuge.RedisShard
redisShards := make([]*centrifuge.RedisShard, 0, len(redisShardConfigs))
for _, redisConf := range redisShardConfigs {
redisShard, err := centrifuge.NewRedisShard(node, redisConf)
if err != nil {
return fmt.Errorf("error connecting to Live Redis: %v", err)
}
redisShards = append(redisShards, redisShard)
}
@@ -348,6 +350,7 @@ func setupRedisLiveEngine(g *GrafanaLive, node *centrifuge.Node) error {
if err != nil {
return fmt.Errorf("error creating Live Redis broker: %v", err)
}
node.SetBroker(broker)
presenceManager, err := centrifuge.NewRedisPresenceManager(node, centrifuge.RedisPresenceManagerConfig{
@@ -357,7 +360,9 @@ func setupRedisLiveEngine(g *GrafanaLive, node *centrifuge.Node) error {
if err != nil {
return fmt.Errorf("error creating Live Redis presence manager: %v", err)
}
node.SetPresenceManager(presenceManager)
return nil
}
+6 -2
View File
@@ -116,17 +116,21 @@ func (s *Manager) handleDatasourceEvent(orgID int64, dsUID string, resubmit bool
s.mu.RUnlock()
return nil
}
var resubmitRequests []streamRequest
var waitChannels []chan struct{}
resubmitRequests := make([]streamRequest, 0, len(dsStreams))
waitChannels := make([]chan struct{}, 0, len(dsStreams))
for channel := range dsStreams {
streamCtx, ok := s.streams[channel]
if !ok {
continue
}
streamCtx.cancelFn()
waitChannels = append(waitChannels, streamCtx.CloseCh)
resubmitRequests = append(resubmitRequests, streamCtx.streamRequest)
}
s.mu.RUnlock()
// Wait for all streams to stop.
+1 -1
View File
@@ -563,8 +563,8 @@ func toRuleGroup(log log.Logger, manager state.AlertInstanceManager, groupKey ng
// Returns the whole JSON model as a string if it fails to extract a minimum of 1 query.
func ruleToQuery(logger log.Logger, rule *ngmodels.AlertRule) string {
var queryErr error
var queries []string
queries := make([]string, 0, len(rule.Data))
for _, q := range rule.Data {
q, err := q.GetQuery()
if err != nil {
@@ -46,156 +46,164 @@ func ContactPointToContactPointExport(cp definitions.ContactPoint) (notify.APIRe
// This is needed to keep the API models clean and convert from database model
j.RegisterExtension(&contactPointsExtension{})
var integration []*notify.GrafanaIntegrationConfig
contactPointsLength := len(cp.Alertmanager) + len(cp.Dingding) + len(cp.Discord) + len(cp.Email) +
len(cp.Googlechat) + len(cp.Kafka) + len(cp.Line) + len(cp.Opsgenie) +
len(cp.Pagerduty) + len(cp.OnCall) + len(cp.Pushover) + len(cp.Sensugo) +
len(cp.Sns) + len(cp.Slack) + len(cp.Teams) + len(cp.Telegram) +
len(cp.Threema) + len(cp.Victorops) + len(cp.Webhook) + len(cp.Wecom) +
len(cp.Webex)
integration := make([]*notify.GrafanaIntegrationConfig, 0, contactPointsLength)
var errs []error
for _, i := range cp.Alertmanager {
el, err := marshallIntegration(j, "prometheus-alertmanager", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Dingding {
el, err := marshallIntegration(j, "dingding", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Discord {
el, err := marshallIntegration(j, "discord", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Email {
el, err := marshallIntegration(j, "email", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Googlechat {
el, err := marshallIntegration(j, "googlechat", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Kafka {
el, err := marshallIntegration(j, "kafka", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Line {
el, err := marshallIntegration(j, "line", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Opsgenie {
el, err := marshallIntegration(j, "opsgenie", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Pagerduty {
el, err := marshallIntegration(j, "pagerduty", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.OnCall {
el, err := marshallIntegration(j, "oncall", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Pushover {
el, err := marshallIntegration(j, "pushover", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Sensugo {
el, err := marshallIntegration(j, "sensugo", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Sns {
el, err := marshallIntegration(j, "sns", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Slack {
el, err := marshallIntegration(j, "slack", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Teams {
el, err := marshallIntegration(j, "teams", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Telegram {
el, err := marshallIntegration(j, "telegram", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Threema {
el, err := marshallIntegration(j, "threema", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Victorops {
el, err := marshallIntegration(j, "victorops", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Webhook {
el, err := marshallIntegration(j, "webhook", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Wecom {
el, err := marshallIntegration(j, "wecom", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
for _, i := range cp.Webex {
el, err := marshallIntegration(j, "webex", i, i.DisableResolveMessage)
integration = append(integration, el)
if err != nil {
errs = append(errs, err)
}
integration = append(integration, el)
}
if len(errs) > 0 {
return notify.APIReceiver{}, errors.Join(errs...)
}
@@ -88,13 +88,14 @@ func (ecp *ContactPointService) GetContactPoints(ctx context.Context, q ContactP
}
}
var contactPoints []apimodels.EmbeddedContactPoint
for _, gr := range grafanaReceivers {
contactPoints := make([]apimodels.EmbeddedContactPoint, len(grafanaReceivers))
for i, gr := range grafanaReceivers {
contactPoint, err := GettableGrafanaReceiverToEmbeddedContactPoint(gr)
if err != nil {
return nil, err
}
contactPoints = append(contactPoints, contactPoint)
contactPoints[i] = contactPoint
}
sort.SliceStable(contactPoints, func(i, j int) bool {
@@ -31,17 +31,19 @@ func (t *TemplateService) GetTemplates(ctx context.Context, orgID int64) ([]defi
return nil, err
}
var templates []definitions.NotificationTemplate
templates := make([]definitions.NotificationTemplate, 0, len(revision.cfg.TemplateFiles))
for name, tmpl := range revision.cfg.TemplateFiles {
tmpl := definitions.NotificationTemplate{
Name: name,
Template: tmpl,
}
provenance, err := t.provenanceStore.GetProvenance(ctx, &tmpl, orgID)
if err != nil {
return nil, err
}
tmpl.Provenance = definitions.Provenance(provenance)
templates = append(templates, tmpl)
}
+5 -4
View File
@@ -492,13 +492,14 @@ func (am *Alertmanager) GetReceivers(ctx context.Context) ([]apimodels.Receiver,
return []apimodels.Receiver{}, err
}
var rcvs []apimodels.Receiver
for _, rcv := range res.Payload {
rcvs = append(rcvs, apimodels.Receiver{
rcvs := make([]apimodels.Receiver, len(res.Payload))
for i, rcv := range res.Payload {
rcvs[i] = apimodels.Receiver{
Name: *rcv.Name,
Integrations: []apimodels.Integration{},
})
}
}
return rcvs, nil
}
+8 -4
View File
@@ -205,15 +205,17 @@ func (d *AlertsRouter) SyncAndApplyConfigFromDatabase(ctx context.Context) error
}
func buildRedactedAMs(l log.Logger, alertmanagers []ExternalAMcfg, ordId int64) []string {
var redactedAMs []string
redactedAMs := make([]string, 0, len(alertmanagers))
for _, am := range alertmanagers {
parsedAM, err := url.Parse(am.URL)
if err != nil {
l.Error("Failed to parse alertmanager string", "org", ordId, "error", err)
continue
}
redactedAMs = append(redactedAMs, parsedAM.Redacted())
}
return redactedAMs
}
@@ -225,9 +227,6 @@ func asSHA256(strings []string) string {
}
func (d *AlertsRouter) alertmanagersFromDatasources(orgID int64) ([]ExternalAMcfg, error) {
var (
alertmanagers []ExternalAMcfg
)
// We might have alertmanager datasources that are acting as external
// alertmanager, let's fetch them.
query := &datasources.GetDataSourcesByTypeQuery{
@@ -240,6 +239,9 @@ func (d *AlertsRouter) alertmanagersFromDatasources(orgID int64) ([]ExternalAMcf
if err != nil {
return nil, fmt.Errorf("failed to fetch datasources for org: %w", err)
}
alertmanagers := make([]ExternalAMcfg, 0, len(dataSources))
for _, ds := range dataSources {
if !ds.JsonData.Get(definitions.HandleGrafanaManagedAlerts).MustBool(false) {
continue
@@ -262,11 +264,13 @@ func (d *AlertsRouter) alertmanagersFromDatasources(orgID int64) ([]ExternalAMcf
"error", err)
continue
}
alertmanagers = append(alertmanagers, ExternalAMcfg{
URL: amURL,
Headers: headers,
})
}
return alertmanagers, nil
}
+2 -1
View File
@@ -712,7 +712,7 @@ func TestAlertManagers_buildRedactedAMs(t *testing.T) {
amUrls: []string{"1234://user:password@localhost:9094"},
errCalls: 1,
errLog: "Failed to parse alertmanager string",
expected: nil,
expected: []string{},
},
}
@@ -724,6 +724,7 @@ func TestAlertManagers_buildRedactedAMs(t *testing.T) {
URL: url,
})
}
require.Equal(t, tt.expected, buildRedactedAMs(&fakeLogger, cfgs, tt.orgId))
require.Equal(t, tt.errCalls, fakeLogger.ErrorLogs.Calls)
require.Equal(t, tt.errLog, fakeLogger.ErrorLogs.Message)
+1 -1
View File
@@ -141,9 +141,9 @@ func errorAlert(labels, annotations data.Labels, alertState *State, urlStr strin
func FromStateTransitionToPostableAlerts(firingStates []StateTransition, stateManager *Manager, appURL *url.URL) apimodels.PostableAlerts {
alerts := apimodels.PostableAlerts{PostableAlerts: make([]models.PostableAlert, 0, len(firingStates))}
var sentAlerts []*State
ts := time.Now()
sentAlerts := make([]*State, 0, len(firingStates))
for _, alertState := range firingStates {
if !alertState.NeedsSending(stateManager.ResendDelay) {
continue
+3 -1
View File
@@ -787,7 +787,8 @@ func (st DBstore) RenameReceiverInNotificationSettings(ctx context.Context, orgI
if len(rules) == 0 {
return 0, nil
}
var updates []ngmodels.UpdateRule
updates := make([]ngmodels.UpdateRule, 0, len(rules))
for _, rule := range rules {
r := ngmodels.CopyRule(rule)
for idx := range r.NotificationSettings {
@@ -795,6 +796,7 @@ func (st DBstore) RenameReceiverInNotificationSettings(ctx context.Context, orgI
r.NotificationSettings[idx].Receiver = newReceiver
}
}
updates = append(updates, ngmodels.UpdateRule{
Existing: rule,
New: *r,
@@ -401,15 +401,15 @@ type pluginsSettingsServiceMock struct {
func (s *pluginsSettingsServiceMock) GetPluginSettings(_ context.Context, args *pluginsettings.GetArgs) ([]*pluginsettings.InfoDTO, error) {
s.getPluginSettingsArgs = append(s.getPluginSettingsArgs, args.OrgID)
var res []*pluginsettings.InfoDTO
for _, ps := range s.storedPluginSettings {
res = append(res, &pluginsettings.InfoDTO{
res := make([]*pluginsettings.InfoDTO, len(s.storedPluginSettings))
for i, ps := range s.storedPluginSettings {
res[i] = &pluginsettings.InfoDTO{
PluginID: ps.PluginID,
OrgID: ps.OrgID,
Enabled: ps.Enabled,
Pinned: ps.Pinned,
PluginVersion: ps.PluginVersion,
})
}
}
return res, s.err
@@ -163,17 +163,23 @@ func (p *EnvVarsProvider) tracingEnvVars(plugin *plugins.Plugin) []string {
func (p *EnvVarsProvider) pluginSettingsEnvVars(pluginID string) []string {
const customConfigPrefix = "GF_PLUGIN"
var env []string
for k, v := range p.cfg.PluginSettings[pluginID] {
pluginSettings := p.cfg.PluginSettings[pluginID]
env := make([]string, 0, len(pluginSettings))
for k, v := range pluginSettings {
if k == "path" || strings.ToLower(k) == "id" {
continue
}
key := fmt.Sprintf("%s_%s", customConfigPrefix, strings.ToUpper(k))
if value := os.Getenv(key); value != "" {
v = value
}
env = append(env, fmt.Sprintf("%s=%s", key, v))
}
return env
}
+4 -2
View File
@@ -191,7 +191,9 @@ func getNonFolderDashboardDoc(dash dashboard, location string) *bluge.Document {
func getDashboardPanelDocs(dash dashboard, location string) []*bluge.Document {
dashURL := fmt.Sprintf("/d/%s/%s", dash.uid, slugify.Slugify(dash.summary.Name))
var docs []*bluge.Document
// pre-allocating a little bit more than necessary, possibly
docs := make([]*bluge.Document, 0, len(dash.summary.Nested))
for _, panel := range dash.summary.Nested {
if panel.Fields["type"] == "row" {
continue // skip rows
@@ -239,7 +241,7 @@ func getDashboardPanelDocs(dash dashboard, location string) []*bluge.Document {
}
// Names need to be indexed a few ways to support key features
func newSearchDocument(uid string, name string, descr string, url string) *bluge.Document {
func newSearchDocument(uid, name, descr, url string) *bluge.Document {
doc := bluge.NewDocument(uid)
if name != "" {
+3 -1
View File
@@ -51,9 +51,11 @@ func Test_punctuationCharFilter_Filter(t1 *testing.T) {
func TestNgramIndexAnalyzer(t *testing.T) {
stream := ngramIndexAnalyzer.Analyze([]byte("x-rays.and.xRays, and НемногоКириллицы"))
expectedTerms := []string{"x", "r", "ra", "ray", "rays", "a", "an", "and", "x", "r", "ra", "ray", "rays", "a", "an", "and", "н", "не", "нем", "немн", "немно", "немног", "немного", "к", "ки", "кир", "кири", "кирил", "кирилл", "кирилли"}
var actualTerms []string
actualTerms := make([]string, 0, len(stream))
for _, t := range stream {
actualTerms = append(actualTerms, string(t.Term))
}
require.Equal(t, expectedTerms, actualTerms)
}
@@ -97,9 +97,8 @@ func (e externalAlertmanagerToDatasources) Exec(sess *xorm.Session, mg *migrator
}
func removeDuplicates(strs []string) []string {
var res []string
found := map[string]bool{}
found := make(map[string]bool, len(strs))
res := make([]string, 0, len(strs))
for _, str := range strs {
if found[str] {
continue
@@ -435,8 +435,10 @@ func (f *accessControlDashboardPermissionFilter) nestedFoldersSelectors(permSele
}
func getAllowedUIDs(action string, user identity.Requester, scopePrefix string) []any {
var args []any
for _, uidScope := range user.GetPermissions()[action] {
uidScopes := user.GetPermissions()[action]
args := make([]any, 0, len(uidScopes))
for _, uidScope := range uidScopes {
if !strings.HasPrefix(uidScope, scopePrefix) {
continue
}
+1 -1
View File
@@ -101,7 +101,7 @@ func (api *Api) getAuthorizedList(ctx context.Context, identity identity.Request
return nil, err
}
var authorizedProviders []*models.SSOSettings
authorizedProviders := make([]*models.SSOSettings, 0, len(allProviders))
for _, provider := range allProviders {
ev := ac.EvalPermission(ac.ActionSettingsRead, ac.Scope("settings", "auth."+provider.Provider, "*"))
hasAccess, err := api.AccessControl.Evaluate(ctx, identity, ev)