-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* wip metrics * configurable interval * log.trace -> debug * explicit message for 404 * update metrics model * don't crash if LAPI is down * update crowdsec dep * update crowdsec dep * use version.DetectOS() from go-cs-lib * update crowdsec * do not allow to configure metrics interval * update crowdsec dep * remove interval parameter * update crowdsec dep * update go version + golangci-lint * lint * lint * update golangci action, remove toolchain directive from go.mod --------- Co-authored-by: Sebastien Blot <sebastien@crowdsec.net>
- Loading branch information
Showing
8 changed files
with
199 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
package csbouncer | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"net/http" | ||
"time" | ||
|
||
"github.com/sirupsen/logrus" | ||
|
||
"github.com/crowdsecurity/go-cs-lib/version" | ||
|
||
"github.com/crowdsecurity/crowdsec/pkg/apiclient" | ||
"github.com/crowdsecurity/crowdsec/pkg/models" | ||
) | ||
|
||
type MetricsUpdater func(*models.RemediationComponentsMetrics, time.Duration) | ||
|
||
const ( | ||
defaultMetricsInterval = 15 * time.Minute | ||
) | ||
|
||
type MetricsProvider struct { | ||
APIClient *apiclient.ApiClient | ||
Interval time.Duration | ||
static staticMetrics | ||
updater MetricsUpdater | ||
logger logrus.FieldLogger | ||
} | ||
|
||
type staticMetrics struct { | ||
osName string | ||
osVersion string | ||
startupTS int64 | ||
featureFlags []string | ||
bouncerType string | ||
} | ||
|
||
// newStaticMetrics should be called once over the lifetime of the program (more if we support hot-reload) | ||
func newStaticMetrics(bouncerType string) staticMetrics { | ||
osName, osVersion := version.DetectOS() | ||
|
||
return staticMetrics{ | ||
osName: osName, | ||
osVersion: osVersion, | ||
startupTS: time.Now().Unix(), | ||
featureFlags: []string{}, | ||
bouncerType: bouncerType, | ||
} | ||
} | ||
|
||
func NewMetricsProvider(client *apiclient.ApiClient, bouncerType string, updater MetricsUpdater, logger logrus.FieldLogger) (*MetricsProvider, error) { | ||
return &MetricsProvider{ | ||
APIClient: client, | ||
Interval: defaultMetricsInterval, | ||
updater: updater, | ||
static: newStaticMetrics(bouncerType), | ||
logger: logger, | ||
}, nil | ||
} | ||
|
||
func (m *MetricsProvider) metricsPayload() *models.AllMetrics { | ||
os := &models.OSversion{ | ||
Name: &m.static.osName, | ||
Version: &m.static.osVersion, | ||
} | ||
|
||
bouncerVersion := version.String() | ||
|
||
base := &models.BaseMetrics{ | ||
Os: os, | ||
Version: &bouncerVersion, | ||
FeatureFlags: m.static.featureFlags, | ||
Metrics: make([]*models.DetailedMetrics, 0), | ||
UtcStartupTimestamp: &m.static.startupTS, | ||
} | ||
|
||
item0 := &models.RemediationComponentsMetrics{ | ||
BaseMetrics: *base, | ||
Type: m.static.bouncerType, | ||
} | ||
|
||
if m.updater != nil { | ||
m.updater(item0, m.Interval) | ||
} | ||
|
||
return &models.AllMetrics{ | ||
RemediationComponents: []*models.RemediationComponentsMetrics{item0}, | ||
} | ||
} | ||
|
||
func (m *MetricsProvider) Run(ctx context.Context) error { | ||
if m.Interval == 0 { | ||
m.logger.Infof("usage metrics disabled") | ||
return nil | ||
} | ||
|
||
if m.updater == nil { | ||
m.logger.Warningf("no updater provided, metrics will be static") | ||
} | ||
|
||
ticker := time.NewTicker(m.Interval) | ||
|
||
for { | ||
select { | ||
case <-ctx.Done(): | ||
return errors.New("metric provider halted") | ||
case <-ticker.C: | ||
met := m.metricsPayload() | ||
|
||
ctxTime, cancel := context.WithTimeout(ctx, 10*time.Second) | ||
defer cancel() | ||
|
||
_, resp, err := m.APIClient.UsageMetrics.Add(ctxTime, met) | ||
switch { | ||
case errors.Is(err, context.DeadlineExceeded): | ||
m.logger.Warnf("timeout sending metrics") | ||
continue | ||
case resp != nil && resp.Response != nil && resp.Response.StatusCode == http.StatusNotFound: | ||
m.logger.Warnf("metrics endpoint not found, older LAPI?") | ||
continue | ||
case err != nil: | ||
m.logger.Warnf("failed to send metrics: %s", err) | ||
continue | ||
} | ||
|
||
if resp.Response.StatusCode != http.StatusCreated { | ||
m.logger.Warnf("failed to send metrics: %s", resp.Response.Status) | ||
continue | ||
} | ||
|
||
m.logger.Debugf("usage metrics sent") | ||
} | ||
} | ||
} |
Oops, something went wrong.