Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lapi detailed metrics #2858

Merged
merged 145 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from 127 commits
Commits
Show all changes
145 commits
Select commit Hold shift + click to select a range
d1f6226
add /usage-metrics endpoint definition
blotus Feb 2, 2024
76c04fd
regenerate pkg/models
mmetc Feb 8, 2024
c325c27
(wip) lp metrics
mmetc Mar 12, 2024
d9a3819
ignore duplicate data points
mmetc Mar 8, 2024
876c339
lint
mmetc Mar 8, 2024
b00e553
interval messages
mmetc Mar 11, 2024
95f38d9
explicit message for 404
mmetc Mar 11, 2024
11499c8
display more LP information in cscli
blotus Mar 21, 2024
dbdf3ad
wip
blotus Mar 21, 2024
33778ca
wip
blotus Mar 22, 2024
0be7cc3
store more payload
blotus Apr 19, 2024
be64f61
set pushed_at after sending metrics
blotus Apr 19, 2024
2b940a4
up
blotus Apr 22, 2024
c6ebd7a
handle 422 error from CAPI
blotus Apr 22, 2024
f085318
update swagger and models
blotus Apr 22, 2024
7b093b9
add lapi metrics in swagger and models
blotus Apr 22, 2024
18b8ddb
add missing file
blotus Apr 22, 2024
538ab0b
up
blotus Apr 22, 2024
3169343
Merge branch 'master' into lapi-detailed-metrics
blotus Apr 22, 2024
e36d2cb
up
blotus Apr 22, 2024
12ce5e3
add more required fields in models
blotus Apr 23, 2024
675a7ee
merge master
blotus May 2, 2024
31e68cf
merge master
blotus May 2, 2024
8d62aef
fix test
blotus May 2, 2024
de26714
add cscli machines inspect
blotus May 2, 2024
f6b8b01
lint
blotus May 3, 2024
9d6b6cd
fix bats test for usage-metrics
blotus May 3, 2024
088dd1a
lint
blotus May 3, 2024
0a247c1
merge master branch
blotus Jun 6, 2024
f08a6bc
remove console_options for LPs
blotus Jun 6, 2024
0cd822a
wip
blotus Jun 11, 2024
5c8cfad
wip
blotus Jun 18, 2024
61d2dba
wip
blotus Jun 18, 2024
2fd72e7
up
blotus Jun 19, 2024
16c7d59
up
blotus Jun 20, 2024
0bfbd3e
up
blotus Jun 25, 2024
df43eaf
up
blotus Jun 25, 2024
727b2e3
remove feature flag
blotus Jun 25, 2024
1cb5675
mark metrics as sent on 422
blotus Jun 26, 2024
95b1082
always send datasources
blotus Jun 26, 2024
e5d1485
Merge branch 'master' into lapi-detailed-metrics
mmetc Jun 28, 2024
4ab5a53
update functional test; workaround for openapi verbose error
mmetc Jun 28, 2024
ea70f25
redundant import alias
mmetc Jun 28, 2024
518cd86
split metrics func tests to own file
mmetc Jun 28, 2024
2cb7bbb
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 1, 2024
be4dc1d
wip machines and hub state
mmetc Jul 1, 2024
f7978c7
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 1, 2024
141ae11
wip
mmetc Jul 2, 2024
dae1cc6
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 2, 2024
76ed1e5
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 2, 2024
e18791a
update for hub state change
mmetc Jul 2, 2024
b1dd9fd
inspect -o json
mmetc Jul 3, 2024
a470989
validate metrics body based on auth type
blotus Jul 3, 2024
4e2a3f5
machines list -o raw: show timestamp instead of delta for last_heartbeat
mmetc Jul 3, 2024
18cc51d
merge back bouncers_table.go to list command
mmetc Jul 3, 2024
0f1e38a
func test empty payload
mmetc Jul 3, 2024
5298236
cscli bouncers inspect
mmetc Jul 3, 2024
06ff891
bouncer feature flags; handle lastpull == nil
mmetc Jul 3, 2024
450387e
feature flags
mmetc Jul 3, 2024
3ba3236
disable redundant-import-alias linter
mmetc Jul 3, 2024
421ceb2
order items by name before sending metrics
mmetc Jul 3, 2024
d447943
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 3, 2024
af0ef90
basic tests
blotus Jul 3, 2024
8e4ad91
up
blotus Jul 3, 2024
af278ce
up
blotus Jul 4, 2024
9fb1d40
up
blotus Jul 4, 2024
7431b52
up
blotus Jul 4, 2024
636ce5c
dry
mmetc Jul 4, 2024
a887d40
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 4, 2024
198fc6c
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 4, 2024
d3e6560
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 4, 2024
b577647
send metrics every 30 minutes to CAPI
blotus Jul 5, 2024
66ad913
sort type names
mmetc Jul 4, 2024
90e60ec
explicit soft wrap
mmetc Jul 5, 2024
7f923b0
extract method processMetrics()
mmetc Jul 5, 2024
e55f3a8
statbouncer.go
mmetc Jul 5, 2024
8759e4f
reduce verbositiy, format byte totals, warn only once per each error
mmetc Jul 9, 2024
36e34a4
todo
mmetc Jul 9, 2024
8657560
cscli metrics: drop support for '-o raw' (just use json)
mmetc Jul 9, 2024
42c1439
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 9, 2024
df5ba9f
wip bytes/packets
mmetc Jul 9, 2024
7665c7a
update func tests
mmetc Jul 10, 2024
6670b08
fup
mmetc Jul 10, 2024
3b08f82
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 10, 2024
1cac76a
more readable tests
mmetc Jul 10, 2024
6df2462
more bouncer tests
mmetc Jul 10, 2024
4577568
test data
mmetc Jul 10, 2024
70f9c65
stable row order
mmetc Jul 10, 2024
f525003
rename package to avoid shadowing
mmetc Jul 11, 2024
2236994
remove metric payload size limit
mmetc Jul 11, 2024
3519bf4
update log/error messages; lint
mmetc Jul 11, 2024
0467486
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 11, 2024
0a74de5
footer with totals by origin; fix display of 0 values
mmetc Jul 11, 2024
50c772a
add maxLength for some elements
blotus Jul 11, 2024
69f7a4e
revert "db: round created, updated... timestamps to 1 second" to fix …
mmetc Jul 11, 2024
8c73c1a
table formatting
mmetc Jul 11, 2024
daf7a13
bouncer stats: dynamic columns
mmetc Jul 12, 2024
9af0055
removed temporary hack
mmetc Jul 12, 2024
987f155
fix multiple bouncer tables
mmetc Jul 12, 2024
2f97c3b
extract method bouncerTable(), separate tables with newline
mmetc Jul 12, 2024
adc86c2
continue loop if metric row can't be parsed
mmetc Jul 12, 2024
2d7b8e7
show earliest collection date for each bouncer
mmetc Jul 12, 2024
11bba5e
func tests: add back sleep for mysql
mmetc Jul 12, 2024
e4cbed1
detect os when in docker, report ex. osname = "Debian (docker)"
mmetc Jul 12, 2024
3365371
describe CAPI as CAPI (community blocklist) in table output only (not…
mmetc Jul 12, 2024
5e07560
display metrics without origin only in the total line
mmetc Jul 12, 2024
8e4622f
display "-" for missing data (like per-origin processed bytes/packets)
mmetc Jul 12, 2024
e8dd87a
pluralize known unit names
mmetc Jul 12, 2024
d671a67
enable 08_* func tests
mmetc Jul 15, 2024
facc26d
comments
mmetc Jul 15, 2024
0381678
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 15, 2024
308b29b
use version.DetectOS() from go-cs-lib
mmetc Jul 15, 2024
3bbed0d
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 15, 2024
1f8e1da
move metrics tomb to global for now
blotus Jul 15, 2024
b865eec
remove configuration option for metrics interval
blotus Jul 15, 2024
8990cd8
fix usage_metrics endpoint to work with cert auth, add some tests
mmetc Jul 15, 2024
259d202
comments, lint
mmetc Jul 15, 2024
df4cd7e
set pushed metrics timestamp in utc; lint
mmetc Jul 15, 2024
9fe3b5f
remove test bouncer after use
mmetc Jul 15, 2024
b6c748e
Merge branch 'master' into lapi-detailed-metrics
buixor Jul 16, 2024
09f41cd
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 17, 2024
c9d307e
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 17, 2024
557096b
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 17, 2024
9609edb
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 18, 2024
4dc45ee
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 18, 2024
d1ffcac
properly init/reinit lpmetrics tomb
blotus Jul 18, 2024
3fe047f
Merge branch 'master' into lapi-detailed-metrics
blotus Jul 22, 2024
e6bf753
CI: update test dependencies (#3146)
mmetc Jul 22, 2024
51d6f84
long label for origin "cscli", "crowdsec"
mmetc Jul 22, 2024
2290ad2
Merge branch 'master' into lapi-detailed-metrics
mmetc Jul 22, 2024
a585ba0
dont' sum active_decisions
mmetc Jul 22, 2024
3af62dc
handle _gauge suffix on metrics names
mmetc Jul 23, 2024
bb8171a
explicitly de-duplicate raw metrics
mmetc Jul 23, 2024
7d790fe
collection timestamp can't be nil so warn
mmetc Jul 23, 2024
5517acf
always aggregate over ipv4+ipv6 (even in json output)
mmetc Jul 23, 2024
c68646b
extract method extractRawMetrics()
mmetc Jul 23, 2024
5b47ad3
extract aggegation methods
mmetc Jul 23, 2024
1187184
types for aggregated data
mmetc Jul 23, 2024
6448777
unroll map creation, extract more methods
mmetc Jul 23, 2024
9ad7a73
do not try to get console options for LP
blotus Jul 23, 2024
d7185a9
commends and dry
mmetc Jul 23, 2024
d5444b0
default value for received_at
blotus Jul 23, 2024
aeb3f08
lin/style
mmetc Jul 23, 2024
e55747a
mod tidy
mmetc Jul 23, 2024
01479b8
Revert "default value for received_at"
mmetc Jul 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions cmd/crowdsec/crowdsec.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,19 @@
})
outputWg.Wait()

mp := NewMetricsProvider(
apiClient,
lpMetricsDefaultInterval,
log.WithField("service", "lpmetrics"),
cConfig.API.Server.ConsoleConfig.EnabledOptions(),
datasources,
hub,
)

Check warning on line 151 in cmd/crowdsec/crowdsec.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/crowdsec.go#L151

Added line #L151 was not covered by tests
lpMetricsTomb.Go(func() error {
return mp.Run(context.Background(), &lpMetricsTomb)
})

if cConfig.Prometheus != nil && cConfig.Prometheus.Enabled {
aggregated := false
if cConfig.Prometheus.Level == configuration.CFG_METRICS_AGGREGATE {
Expand Down
182 changes: 182 additions & 0 deletions cmd/crowdsec/lpmetrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
package main

import (
"context"
"errors"
"net/http"
"time"

"github.com/sirupsen/logrus"

"gopkg.in/tomb.v2"

"github.com/crowdsecurity/go-cs-lib/ptr"
"github.com/crowdsecurity/go-cs-lib/trace"
"github.com/crowdsecurity/go-cs-lib/version"

"github.com/crowdsecurity/crowdsec/pkg/acquisition"
"github.com/crowdsecurity/crowdsec/pkg/apiclient"
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
"github.com/crowdsecurity/crowdsec/pkg/fflag"
"github.com/crowdsecurity/crowdsec/pkg/models"
)

const lpMetricsDefaultInterval = 30 * time.Minute

// MetricsProvider collects metrics from the LP and sends them to the LAPI
type MetricsProvider struct {
apic *apiclient.ApiClient
interval time.Duration
static staticMetrics
logger *logrus.Entry
}

type staticMetrics struct {
osName string
osVersion string
startupTS int64
featureFlags []string
consoleOptions []string
datasourceMap map[string]int64
hubState models.HubItems
}

func getHubState(hub *cwhub.Hub) models.HubItems {
ret := models.HubItems{}

Check warning on line 46 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L46

Added line #L46 was not covered by tests
for _, itemType := range cwhub.ItemTypes {
ret[itemType] = []models.HubItem{}
items, _ := hub.GetInstalledItemsByType(itemType)
cwhub.SortItemSlice(items)

Check warning on line 51 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L51

Added line #L51 was not covered by tests
for _, item := range items {
status := "official"
if item.State.IsLocal() {
status = "custom"
}

Check warning on line 56 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L56

Added line #L56 was not covered by tests
if item.State.Tainted {
status = "tainted"
}

Check warning on line 59 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L59

Added line #L59 was not covered by tests
ret[itemType] = append(ret[itemType], models.HubItem{
Name: item.Name,
Status: status,
Version: item.Version,
})
}
}

return ret
}

// newStaticMetrics is called when the process starts, or reloads the configuration
func newStaticMetrics(consoleOptions []string, datasources []acquisition.DataSource, hub *cwhub.Hub) staticMetrics {
datasourceMap := map[string]int64{}

Check warning on line 74 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L74

Added line #L74 was not covered by tests
for _, ds := range datasources {
datasourceMap[ds.GetName()] += 1
}

Check warning on line 77 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L77

Added line #L77 was not covered by tests

osName, osVersion := version.DetectOS()

Check warning on line 80 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L80

Added line #L80 was not covered by tests
return staticMetrics{
osName: osName,
osVersion: osVersion,
startupTS: time.Now().UTC().Unix(),
featureFlags: fflag.Crowdsec.GetEnabledFeatures(),
consoleOptions: consoleOptions,
datasourceMap: datasourceMap,
hubState: getHubState(hub),
}

Check warning on line 89 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L89

Added line #L89 was not covered by tests
}

func NewMetricsProvider(apic *apiclient.ApiClient, interval time.Duration, logger *logrus.Entry,
consoleOptions []string, datasources []acquisition.DataSource, hub *cwhub.Hub) *MetricsProvider {
return &MetricsProvider{
apic: apic,
interval: interval,
logger: logger,
static: newStaticMetrics(consoleOptions, datasources, hub),
}

Check warning on line 99 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L99

Added line #L99 was not covered by tests
}

func (m *MetricsProvider) metricsPayload() *models.AllMetrics {
os := &models.OSversion{
Name: ptr.Of(m.static.osName),
Version: ptr.Of(m.static.osVersion),
}

Check warning on line 107 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L106-L107

Added lines #L106 - L107 were not covered by tests
base := models.BaseMetrics{
UtcStartupTimestamp: ptr.Of(m.static.startupTS),
Os: os,
Version: ptr.Of(version.String()),
FeatureFlags: m.static.featureFlags,
Metrics: make([]*models.DetailedMetrics, 0),
}

Check warning on line 115 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L114-L115

Added lines #L114 - L115 were not covered by tests
met := &models.LogProcessorsMetrics{
BaseMetrics: base,
Datasources: m.static.datasourceMap,
HubItems: m.static.hubState,
}

Check warning on line 121 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L120-L121

Added lines #L120 - L121 were not covered by tests
met.Metrics = append(met.Metrics, &models.DetailedMetrics{
Meta: &models.MetricsMeta{
UtcNowTimestamp: ptr.Of(time.Now().Unix()),
WindowSizeSeconds: ptr.Of(int64(m.interval.Seconds())),
},
Items: make([]*models.MetricsDetailItem, 0),
})

Check warning on line 129 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L129

Added line #L129 was not covered by tests
return &models.AllMetrics{
LogProcessors: []*models.LogProcessorsMetrics{met},
}

Check warning on line 132 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L132

Added line #L132 was not covered by tests
}

func (m *MetricsProvider) Run(ctx context.Context, myTomb *tomb.Tomb) error {
defer trace.CatchPanic("crowdsec/MetricsProvider.Run")

Check warning on line 137 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L137

Added line #L137 was not covered by tests
if m.interval == time.Duration(0) {
return nil
}

Check warning on line 140 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L139-L140

Added lines #L139 - L140 were not covered by tests

met := m.metricsPayload()

Check warning on line 143 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L143

Added line #L143 was not covered by tests
ticker := time.NewTicker(1) // Send on start

Check warning on line 145 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L145

Added line #L145 was not covered by tests
for {
select {
case <-ticker.C:
ctxTime, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()

Check warning on line 151 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L151

Added line #L151 was not covered by tests
_, resp, err := m.apic.UsageMetrics.Add(ctxTime, met)
switch {
case errors.Is(err, context.DeadlineExceeded):
m.logger.Warnf("timeout sending lp metrics")
ticker.Reset(m.interval)
continue
case err != nil && resp != nil && resp.Response.StatusCode == http.StatusNotFound:
m.logger.Warnf("metrics endpoint not found, older LAPI?")
ticker.Reset(m.interval)
continue
case err != nil:
m.logger.Warnf("failed to send lp metrics: %s", err)
ticker.Reset(m.interval)
continue

Check warning on line 165 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L154-L165

Added lines #L154 - L165 were not covered by tests
}

if resp.Response.StatusCode != http.StatusCreated {
m.logger.Warnf("failed to send lp metrics: %s", resp.Response.Status)
ticker.Reset(m.interval)
continue

Check warning on line 171 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L169-L171

Added lines #L169 - L171 were not covered by tests
}

ticker.Reset(m.interval)

Check warning on line 175 in cmd/crowdsec/lpmetrics.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/lpmetrics.go#L175

Added line #L175 was not covered by tests
m.logger.Tracef("lp usage metrics sent")
case <-myTomb.Dying():
ticker.Stop()
return nil
}
}
}
27 changes: 14 additions & 13 deletions cmd/crowdsec/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,29 @@ import (
)

var (
/*tombs for the parser, buckets and outputs.*/
acquisTomb tomb.Tomb
parsersTomb tomb.Tomb
bucketsTomb tomb.Tomb
outputsTomb tomb.Tomb
apiTomb tomb.Tomb
crowdsecTomb tomb.Tomb
pluginTomb tomb.Tomb
// tombs for the parser, buckets and outputs.
acquisTomb tomb.Tomb
parsersTomb tomb.Tomb
bucketsTomb tomb.Tomb
outputsTomb tomb.Tomb
apiTomb tomb.Tomb
crowdsecTomb tomb.Tomb
pluginTomb tomb.Tomb
lpMetricsTomb tomb.Tomb

flags *Flags

/*the state of acquisition*/
// the state of acquisition
dataSources []acquisition.DataSource
/*the state of the buckets*/
// the state of the buckets
holders []leakybucket.BucketFactory
buckets *leakybucket.Buckets

inputLineChan chan types.Event
inputEventChan chan types.Event
outputEventChan chan types.Event // the buckets init returns its own chan that is used for multiplexing
/*settings*/
lastProcessedItem time.Time /*keep track of last item timestamp in time-machine. it is used to GC buckets when we dump them.*/
// settings
lastProcessedItem time.Time // keep track of last item timestamp in time-machine. it is used to GC buckets when we dump them.
pluginBroker csplugin.PluginBroker
)

Expand Down Expand Up @@ -307,7 +308,7 @@ func LoadConfig(configFile string, disableAgent bool, disableAPI bool, quiet boo
if cConfig.API != nil && cConfig.API.Server != nil {
cConfig.API.Server.OnlineClient = nil
}
/*if the api is disabled as well, just read file and exit, don't daemonize*/
// if the api is disabled as well, just read file and exit, don't daemonize
if cConfig.DisableAPI {
cConfig.Common.Daemonize = false
}
Expand Down
11 changes: 11 additions & 0 deletions cmd/crowdsec/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
apiTomb = tomb.Tomb{}
crowdsecTomb = tomb.Tomb{}
pluginTomb = tomb.Tomb{}
lpMetricsTomb = tomb.Tomb{}

cConfig, err := LoadConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI, false)
if err != nil {
Expand Down Expand Up @@ -179,6 +180,15 @@
log.Warningf("Outputs didn't finish in time, some events may have not been flushed")
}

lpMetricsTomb.Kill(nil)

Check warning on line 184 in cmd/crowdsec/serve.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/serve.go#L184

Added line #L184 was not covered by tests
if err := lpMetricsTomb.Wait(); err != nil {
log.Warningf("Metrics returned error : %s", err)
reterr = err
}

Check warning on line 188 in cmd/crowdsec/serve.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/serve.go#L186-L188

Added lines #L186 - L188 were not covered by tests

log.Debugf("metrics are done")

Check warning on line 191 in cmd/crowdsec/serve.go

View check run for this annotation

Codecov / codecov/patch

cmd/crowdsec/serve.go#L191

Added line #L191 was not covered by tests
// He's dead, Jim.
crowdsecTomb.Kill(nil)

Expand Down Expand Up @@ -322,6 +332,7 @@
apiTomb = tomb.Tomb{}
crowdsecTomb = tomb.Tomb{}
pluginTomb = tomb.Tomb{}
lpMetricsTomb = tomb.Tomb{}

ctx := context.TODO()

Expand Down
3 changes: 3 additions & 0 deletions pkg/apiclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type ApiClient struct {
Metrics *MetricsService
Signal *SignalService
HeartBeat *HeartBeatService
UsageMetrics *UsageMetricsService
}

func (a *ApiClient) GetClient() *http.Client {
Expand Down Expand Up @@ -108,6 +109,7 @@ func NewClient(config *Config) (*ApiClient, error) {
c.Signal = (*SignalService)(&c.common)
c.DecisionDelete = (*DecisionDeleteService)(&c.common)
c.HeartBeat = (*HeartBeatService)(&c.common)
c.UsageMetrics = (*UsageMetricsService)(&c.common)

return c, nil
}
Expand Down Expand Up @@ -144,6 +146,7 @@ func NewDefaultClient(URL *url.URL, prefix string, userAgent string, client *htt
c.Signal = (*SignalService)(&c.common)
c.DecisionDelete = (*DecisionDeleteService)(&c.common)
c.HeartBeat = (*HeartBeatService)(&c.common)
c.UsageMetrics = (*UsageMetricsService)(&c.common)

return c, nil
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/apiclient/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,5 +348,5 @@ func TestNewClientBadAnswer(t *testing.T) {
URL: apiURL,
VersionPrefix: "v1",
}, &http.Client{})
cstest.RequireErrorContains(t, err, "invalid body: invalid character 'b' looking for beginning of value")
cstest.RequireErrorContains(t, err, "invalid body: bad")
}
12 changes: 9 additions & 3 deletions pkg/apiclient/resperr.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,18 @@

data, err := io.ReadAll(r.Body)
if err != nil || len(data) == 0 {
ret.Message = ptr.Of(fmt.Sprintf("http code %d, no error message", r.StatusCode))
ret.Message = ptr.Of(fmt.Sprintf("http code %d, no response body", r.StatusCode))

Check warning on line 37 in pkg/apiclient/resperr.go

View check run for this annotation

Codecov / codecov/patch

pkg/apiclient/resperr.go#L37

Added line #L37 was not covered by tests
return ret
}

if err := json.Unmarshal(data, ret); err != nil {
return fmt.Errorf("http code %d, invalid body: %w", r.StatusCode, err)
switch r.StatusCode {
case http.StatusUnprocessableEntity:
ret.Message = ptr.Of(fmt.Sprintf("http code %d, invalid request: %s", r.StatusCode, string(data)))

Check warning on line 43 in pkg/apiclient/resperr.go

View check run for this annotation

Codecov / codecov/patch

pkg/apiclient/resperr.go#L42-L43

Added lines #L42 - L43 were not covered by tests
default:
if err := json.Unmarshal(data, ret); err != nil {
ret.Message = ptr.Of(fmt.Sprintf("http code %d, invalid body: %s", r.StatusCode, string(data)))
return ret
}
}

return ret
Expand Down
29 changes: 29 additions & 0 deletions pkg/apiclient/usagemetrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package apiclient

import (
"context"
"fmt"
"net/http"

"github.com/crowdsecurity/crowdsec/pkg/models"
)

type UsageMetricsService service

func (s *UsageMetricsService) Add(ctx context.Context, metrics *models.AllMetrics) (interface{}, *Response, error) {
u := fmt.Sprintf("%s/usage-metrics", s.client.URLPrefix)

Check warning on line 15 in pkg/apiclient/usagemetrics.go

View check run for this annotation

Codecov / codecov/patch

pkg/apiclient/usagemetrics.go#L15

Added line #L15 was not covered by tests
req, err := s.client.NewRequest(http.MethodPost, u, &metrics)
if err != nil {
return nil, nil, err
}

Check warning on line 19 in pkg/apiclient/usagemetrics.go

View check run for this annotation

Codecov / codecov/patch

pkg/apiclient/usagemetrics.go#L18-L19

Added lines #L18 - L19 were not covered by tests

var response interface{}

Check warning on line 22 in pkg/apiclient/usagemetrics.go

View check run for this annotation

Codecov / codecov/patch

pkg/apiclient/usagemetrics.go#L22

Added line #L22 was not covered by tests
resp, err := s.client.Do(ctx, req, &response)
if err != nil {
return nil, resp, err
}

Check warning on line 26 in pkg/apiclient/usagemetrics.go

View check run for this annotation

Codecov / codecov/patch

pkg/apiclient/usagemetrics.go#L25-L26

Added lines #L25 - L26 were not covered by tests

return &response, resp, nil
}
Loading
Loading