wip
This commit is contained in:
parent
11499c8d9e
commit
dbdf3ad1bb
|
@ -4,39 +4,40 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/blackfireio/osinfo"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/blackfireio/osinfo"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"gopkg.in/tomb.v2"
|
"gopkg.in/tomb.v2"
|
||||||
|
|
||||||
"github.com/crowdsecurity/go-cs-lib/ptr"
|
"github.com/crowdsecurity/go-cs-lib/ptr"
|
||||||
"github.com/crowdsecurity/go-cs-lib/trace"
|
"github.com/crowdsecurity/go-cs-lib/trace"
|
||||||
|
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/acquisition"
|
"github.com/crowdsecurity/crowdsec/pkg/acquisition"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/apiclient"
|
"github.com/crowdsecurity/crowdsec/pkg/apiclient"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
|
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/cwversion"
|
"github.com/crowdsecurity/crowdsec/pkg/cwversion"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/fflag"
|
"github.com/crowdsecurity/crowdsec/pkg/fflag"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/models"
|
"github.com/crowdsecurity/crowdsec/pkg/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MetricsProvider collects metrics from the LP and sends them to the LAPI
|
// MetricsProvider collects metrics from the LP and sends them to the LAPI
|
||||||
type MetricsProvider struct {
|
type MetricsProvider struct {
|
||||||
apic *apiclient.ApiClient
|
apic *apiclient.ApiClient
|
||||||
interval time.Duration
|
interval time.Duration
|
||||||
static staticMetrics
|
static staticMetrics
|
||||||
logger *logrus.Entry
|
logger *logrus.Entry
|
||||||
}
|
}
|
||||||
|
|
||||||
type staticMetrics struct {
|
type staticMetrics struct {
|
||||||
osName string
|
osName string
|
||||||
osVersion string
|
osVersion string
|
||||||
startupTS int64
|
startupTS int64
|
||||||
featureFlags []string
|
featureFlags []string
|
||||||
consoleOptions []string
|
consoleOptions []string
|
||||||
datasourceMap map[string]int64
|
datasourceMap map[string]int64
|
||||||
hubState models.HubItems
|
hubState models.HubItems
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHubState(hub *cwhub.Hub) models.HubItems {
|
func getHubState(hub *cwhub.Hub) models.HubItems {
|
||||||
|
@ -96,50 +97,48 @@ func detectOS() (string, string) {
|
||||||
return osInfo.Name, osInfo.Version
|
return osInfo.Name, osInfo.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func NewMetricsProvider(apic *apiclient.ApiClient, interval time.Duration, logger *logrus.Entry,
|
func NewMetricsProvider(apic *apiclient.ApiClient, interval time.Duration, logger *logrus.Entry,
|
||||||
consoleOptions []string, datasources []acquisition.DataSource, hub *cwhub.Hub) *MetricsProvider {
|
consoleOptions []string, datasources []acquisition.DataSource, hub *cwhub.Hub) *MetricsProvider {
|
||||||
return &MetricsProvider{
|
return &MetricsProvider{
|
||||||
apic: apic,
|
apic: apic,
|
||||||
interval: interval,
|
interval: interval,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
static: newStaticMetrics(consoleOptions, datasources, hub),
|
static: newStaticMetrics(consoleOptions, datasources, hub),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MetricsProvider) metricsPayload() *models.AllMetrics {
|
func (m *MetricsProvider) metricsPayload() *models.AllMetrics {
|
||||||
meta := &models.MetricsMeta{
|
meta := &models.MetricsMeta{
|
||||||
UtcStartupTimestamp: m.static.startupTS,
|
UtcStartupTimestamp: m.static.startupTS,
|
||||||
WindowSizeSeconds: int64(m.interval.Seconds()),
|
WindowSizeSeconds: int64(m.interval.Seconds()),
|
||||||
}
|
}
|
||||||
|
|
||||||
os := &models.OSversion{
|
os := &models.OSversion{
|
||||||
Name: m.static.osName,
|
Name: m.static.osName,
|
||||||
Version: m.static.osVersion,
|
Version: m.static.osVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
base := models.BaseMetrics{
|
base := models.BaseMetrics{
|
||||||
Meta: meta,
|
Meta: meta,
|
||||||
Os: os,
|
Os: os,
|
||||||
Version: ptr.Of(cwversion.VersionStr()),
|
Version: ptr.Of(cwversion.VersionStr()),
|
||||||
FeatureFlags: m.static.featureFlags,
|
FeatureFlags: m.static.featureFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
item0 := &models.LogProcessorsMetricsItems0{
|
item0 := &models.LogProcessorsMetricsItems0{
|
||||||
BaseMetrics: base,
|
BaseMetrics: base,
|
||||||
ConsoleOptions: m.static.consoleOptions,
|
ConsoleOptions: m.static.consoleOptions,
|
||||||
Datasources: m.static.datasourceMap,
|
Datasources: m.static.datasourceMap,
|
||||||
HubItems: m.static.hubState,
|
HubItems: m.static.hubState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: more metric details... ?
|
// TODO: more metric details... ?
|
||||||
|
|
||||||
return &models.AllMetrics{
|
return &models.AllMetrics{
|
||||||
LogProcessors: []models.LogProcessorsMetrics{{item0}},
|
LogProcessors: []models.LogProcessorsMetrics{{item0}},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (m *MetricsProvider) Run(ctx context.Context, myTomb *tomb.Tomb) error {
|
func (m *MetricsProvider) Run(ctx context.Context, myTomb *tomb.Tomb) error {
|
||||||
defer trace.CatchPanic("crowdsec/MetricsProvider.Run")
|
defer trace.CatchPanic("crowdsec/MetricsProvider.Run")
|
||||||
|
|
||||||
|
@ -149,7 +148,7 @@ func (m *MetricsProvider) Run(ctx context.Context, myTomb *tomb.Tomb) error {
|
||||||
|
|
||||||
met := m.metricsPayload()
|
met := m.metricsPayload()
|
||||||
|
|
||||||
ticker := time.NewTicker(m.interval)
|
ticker := time.NewTicker(1) //Send on start
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
@ -177,6 +176,8 @@ func (m *MetricsProvider) Run(ctx context.Context, myTomb *tomb.Tomb) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ticker.Reset(m.interval)
|
||||||
|
|
||||||
m.logger.Tracef("lp usage metrics sent")
|
m.logger.Tracef("lp usage metrics sent")
|
||||||
case <-myTomb.Dying():
|
case <-myTomb.Dying():
|
||||||
ticker.Stop()
|
ticker.Stop()
|
||||||
|
|
|
@ -2,11 +2,15 @@ package apiserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/crowdsecurity/go-cs-lib/ptr"
|
"github.com/crowdsecurity/go-cs-lib/ptr"
|
||||||
"github.com/crowdsecurity/go-cs-lib/trace"
|
"github.com/crowdsecurity/go-cs-lib/trace"
|
||||||
"github.com/crowdsecurity/go-cs-lib/version"
|
"github.com/crowdsecurity/go-cs-lib/version"
|
||||||
|
@ -14,6 +18,67 @@ import (
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/models"
|
"github.com/crowdsecurity/crowdsec/pkg/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (a *apic) GetUsageMetrics() (*models.AllMetrics, error) {
|
||||||
|
lpsMetrics, err := a.dbClient.GetLPsUsageMetrics()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
spew.Dump(lpsMetrics)
|
||||||
|
|
||||||
|
bouncersMetrics, err := a.dbClient.GetBouncersUsageMetrics()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
spew.Dump(bouncersMetrics)
|
||||||
|
|
||||||
|
allMetrics := &models.AllMetrics{}
|
||||||
|
|
||||||
|
allLps := a.dbClient.ListMachines()
|
||||||
|
allBouncers := a.dbClient.ListBouncers()
|
||||||
|
|
||||||
|
for _, lpsMetric := range lpsMetrics {
|
||||||
|
lpName := lpsMetric.GeneratedBy
|
||||||
|
metrics := models.LogProcessorsMetricsItems0{}
|
||||||
|
|
||||||
|
err := json.Unmarshal([]byte(lpsMetric.Payload), &metrics)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("unable to unmarshal LPs metrics (%s)", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
lp, err := a.dbClient.QueryMachineByID(lpName)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("unable to get LP information for %s: %s", lpName, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if lp.Hubstate != nil {
|
||||||
|
metrics.HubItems = *lp.Hubstate
|
||||||
|
}
|
||||||
|
|
||||||
|
metrics.Os = &models.OSversion{
|
||||||
|
Name: lp.Osname,
|
||||||
|
Version: lp.Osversion,
|
||||||
|
}
|
||||||
|
|
||||||
|
metrics.FeatureFlags = strings.Split(lp.Featureflags, ",")
|
||||||
|
metrics.Version = &lp.Version
|
||||||
|
//TODO: meta
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//bouncerInfos := make(map[string]string)
|
||||||
|
|
||||||
|
//TODO: add LAPI metrics
|
||||||
|
|
||||||
|
return allMetrics, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *apic) GetMetrics() (*models.Metrics, error) {
|
func (a *apic) GetMetrics() (*models.Metrics, error) {
|
||||||
machines, err := a.dbClient.ListMachines()
|
machines, err := a.dbClient.ListMachines()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -160,3 +225,24 @@ func (a *apic) SendMetrics(stop chan (bool)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *apic) SendUsageMetrics() {
|
||||||
|
defer trace.CatchPanic("lapi/usageMetricsToAPIC")
|
||||||
|
|
||||||
|
ticker := time.NewTicker(5 * time.Second)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-a.metricsTomb.Dying():
|
||||||
|
//The normal metrics routine also kills push/pull tombs, does that make sense ?
|
||||||
|
ticker.Stop()
|
||||||
|
return
|
||||||
|
case <-ticker.C:
|
||||||
|
_, err := a.GetUsageMetrics()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("unable to get usage metrics (%s)", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/csplugin"
|
"github.com/crowdsecurity/crowdsec/pkg/csplugin"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/database"
|
"github.com/crowdsecurity/crowdsec/pkg/database"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/fflag"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -360,6 +361,15 @@ func (s *APIServer) Run(apiReady chan bool) error {
|
||||||
s.apic.SendMetrics(make(chan bool))
|
s.apic.SendMetrics(make(chan bool))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if fflag.CAPIUsageMetrics.IsEnabled() {
|
||||||
|
log.Infof("CAPI_USAGE_METRICS flag is enabled, starting usage metrics routine")
|
||||||
|
s.apic.metricsTomb.Go(func() error {
|
||||||
|
s.apic.SendUsageMetrics()
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s.httpServerTomb.Go(func() error {
|
s.httpServerTomb.Go(func() error {
|
||||||
|
@ -368,7 +378,7 @@ func (s *APIServer) Run(apiReady chan bool) error {
|
||||||
|
|
||||||
if err := s.httpServerTomb.Wait(); err != nil {
|
if err := s.httpServerTomb.Wait(); err != nil {
|
||||||
return fmt.Errorf("local API server stopped with error: %w", err)
|
return fmt.Errorf("local API server stopped with error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ import (
|
||||||
// RemoveOldMetrics
|
// RemoveOldMetrics
|
||||||
// avoid errors.Wrapf
|
// avoid errors.Wrapf
|
||||||
|
|
||||||
|
|
||||||
func (c *Client) CreateMetric(generatedType metric.GeneratedType, generatedBy string, collectedAt time.Time, payload string) (*ent.Metric, error) {
|
func (c *Client) CreateMetric(generatedType metric.GeneratedType, generatedBy string, collectedAt time.Time, payload string) (*ent.Metric, error) {
|
||||||
metric, err := c.Ent.Metric.
|
metric, err := c.Ent.Metric.
|
||||||
Create().
|
Create().
|
||||||
|
@ -38,3 +37,35 @@ func (c *Client) CreateMetric(generatedType metric.GeneratedType, generatedBy st
|
||||||
|
|
||||||
return metric, nil
|
return metric, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) GetLPsUsageMetrics() ([]*ent.Metric, error) {
|
||||||
|
metrics, err := c.Ent.Metric.Query().
|
||||||
|
Where(
|
||||||
|
metric.GeneratedTypeEQ(metric.GeneratedTypeLP),
|
||||||
|
metric.PushedAtIsNil(),
|
||||||
|
).
|
||||||
|
Order(ent.Desc(metric.FieldCollectedAt)).
|
||||||
|
All(c.CTX)
|
||||||
|
if err != nil {
|
||||||
|
c.Log.Warningf("GetLPsUsageMetrics: %s", err)
|
||||||
|
return nil, fmt.Errorf("getting LPs usage metrics: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return metrics, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) GetBouncersUsageMetrics() ([]*ent.Metric, error) {
|
||||||
|
metrics, err := c.Ent.Metric.Query().
|
||||||
|
Where(
|
||||||
|
metric.GeneratedTypeEQ(metric.GeneratedTypeRC),
|
||||||
|
metric.PushedAtIsNil(),
|
||||||
|
).
|
||||||
|
Order(ent.Desc(metric.FieldCollectedAt)).
|
||||||
|
All(c.CTX)
|
||||||
|
if err != nil {
|
||||||
|
c.Log.Warningf("GetBouncersUsageMetrics: %s", err)
|
||||||
|
return nil, fmt.Errorf("getting bouncers usage metrics: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return metrics, nil
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ var ChunkedDecisionsStream = &Feature{Name: "chunked_decisions_stream", Descript
|
||||||
var PapiClient = &Feature{Name: "papi_client", Description: "Enable Polling API client", State: DeprecatedState}
|
var PapiClient = &Feature{Name: "papi_client", Description: "Enable Polling API client", State: DeprecatedState}
|
||||||
var Re2GrokSupport = &Feature{Name: "re2_grok_support", Description: "Enable RE2 support for GROK patterns"}
|
var Re2GrokSupport = &Feature{Name: "re2_grok_support", Description: "Enable RE2 support for GROK patterns"}
|
||||||
var Re2RegexpInfileSupport = &Feature{Name: "re2_regexp_in_file_support", Description: "Enable RE2 support for RegexpInFile expr helper"}
|
var Re2RegexpInfileSupport = &Feature{Name: "re2_regexp_in_file_support", Description: "Enable RE2 support for RegexpInFile expr helper"}
|
||||||
|
var CAPIUsageMetrics = &Feature{Name: "capi_usage_metrics", Description: "Enable usage metrics push to CAPI"}
|
||||||
|
|
||||||
func RegisterAllFeatures() error {
|
func RegisterAllFeatures() error {
|
||||||
err := Crowdsec.RegisterFeature(CscliSetup)
|
err := Crowdsec.RegisterFeature(CscliSetup)
|
||||||
|
@ -40,5 +41,10 @@ func RegisterAllFeatures() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = Crowdsec.RegisterFeature(CAPIUsageMetrics)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue