Skip to content

Commit

Permalink
convert plugin config to scraper config
Browse files Browse the repository at this point in the history
  • Loading branch information
isacikgoz committed Nov 27, 2023
1 parent 47b5231 commit 114fd7d
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 0 deletions.
19 changes: 19 additions & 0 deletions server/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ type configuration struct {
HonorTimestamps *bool
// Option to enable the experimental in-memory metadata storage and append metadata to the WAL.
EnableMetadataStorage *bool
// Scrape interval is the time between polling the /metrics endpoint
ScrapeIntervalSeconds *int
// Screap timeout tells scraper to give up on the poll for a single scrape attempt
ScrapeTimeoutSeconds *int
}

func (c *configuration) SetDefaults() {
Expand Down Expand Up @@ -61,9 +65,24 @@ func (c *configuration) SetDefaults() {
if c.EnableMetadataStorage == nil {
c.EnableMetadataStorage = model.NewBool(true)
}
if c.ScrapeIntervalSeconds == nil {
c.ScrapeIntervalSeconds = model.NewInt(60)
}
if c.ScrapeTimeoutSeconds == nil {
c.ScrapeTimeoutSeconds = model.NewInt(10)
}
}

func (c *configuration) IsValid() error {
if *c.ScrapeIntervalSeconds < 1 {
return errors.New("scrape interval should be greater than zero")
}
if *c.ScrapeTimeoutSeconds < 1 {
return errors.New("scrape timeout should be greater than zero")
}
if *c.BodySizeLimitBytes < 100 {
return errors.New("openmetrics body size is not realistic, should be greater than 100 bytes")
}
return nil
}

Expand Down
9 changes: 9 additions & 0 deletions server/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package main

import (
"github.com/prometheus/prometheus/model/labels"
)

var (
sampleMutator func(labels.Labels) labels.Labels //nolint:unused
)
34 changes: 34 additions & 0 deletions server/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@ package main
import (
"fmt"
"net/http"
"net/url"
"sync"
"time"

"github.com/mattermost/mattermost/server/public/plugin"
"github.com/mattermost/mattermost/server/v8/platform/shared/filestore"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/config"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/relabel"
"github.com/prometheus/prometheus/scrape"
"github.com/prometheus/prometheus/tsdb"
)

Expand Down Expand Up @@ -54,6 +60,10 @@ func (p *Plugin) OnActivate() error {
p.configuration.SetDefaults()
}

if err = p.configuration.IsValid(); err != nil {
return fmt.Errorf("could not validate config: %w", err)
}

// check if cluster is enabled
if p.isHA() {
// TODO(isacikgoz): get cluster info
Expand All @@ -72,6 +82,30 @@ func (p *Plugin) OnActivate() error {
return fmt.Errorf("could not open target tsdb: %w", err)
}

scrapeInterval := *p.configuration.ScrapeIntervalSeconds

// TODO(isacikgoz): Use multiple targets for HA env
ls := labels.FromMap(map[string]string{
model.AddressLabel: "localhost:8067",
model.ScrapeIntervalLabel: fmt.Sprintf("%ds", scrapeInterval),
model.ScrapeTimeoutLabel: fmt.Sprintf("%ds", *p.configuration.ScrapeTimeoutSeconds),
})
lb := labels.NewBuilder(ls)

lset, origLabels, err := scrape.PopulateLabels(lb, &config.ScrapeConfig{
JobName: "prometheus",
}, true)
if err != nil {
return err
}

target := scrape.NewTarget(lset, origLabels, url.Values{})

// Mutator is being used to apply labels to the metric samples
sampleMutator = func(l labels.Labels) labels.Labels {
return mutateSampleLabels(l, target, *p.configuration.HonorTimestamps, []*relabel.Config{})
}

return nil
}

Expand Down
60 changes: 60 additions & 0 deletions server/sample.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package main

import (
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/relabel"
"github.com/prometheus/prometheus/scrape"
"golang.org/x/exp/slices"
)

func mutateSampleLabels(lset labels.Labels, target *scrape.Target, honor bool, rc []*relabel.Config) labels.Labels {
lb := labels.NewBuilder(lset)

if honor {
target.LabelsRange(func(l labels.Label) {
if !lset.Has(l.Name) {
lb.Set(l.Name, l.Value)
}
})
} else {
var conflictingExposedLabels []labels.Label
target.LabelsRange(func(l labels.Label) {
existingValue := lset.Get(l.Name)
if existingValue != "" {
conflictingExposedLabels = append(conflictingExposedLabels, labels.Label{Name: l.Name, Value: existingValue})
}
// It is now safe to set the target label.
lb.Set(l.Name, l.Value)
})

if len(conflictingExposedLabels) > 0 {
resolveConflictingExposedLabels(lb, conflictingExposedLabels)
}
}

res := lb.Labels()

if len(rc) > 0 {
res, _ = relabel.Process(res, rc...)
}

return res
}

func resolveConflictingExposedLabels(lb *labels.Builder, conflictingExposedLabels []labels.Label) {
slices.SortStableFunc(conflictingExposedLabels, func(a, b labels.Label) bool {
return len(a.Name) < len(b.Name)
})

for _, l := range conflictingExposedLabels {
newName := l.Name
for {
newName = model.ExportedLabelPrefix + newName
if lb.Get(newName) == "" {
lb.Set(newName, l.Value)
break
}
}
}
}

0 comments on commit 114fd7d

Please sign in to comment.