-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- [x] Create the `Stats` structs to output structured metrics convertible into key-values ready for the backend - [x] Store truncations in the code because there will be output merged between runs --------- Signed-off-by: Eliott Bouhana <[email protected]>
- Loading branch information
1 parent
02b711a
commit 405eb7a
Showing
5 changed files
with
163 additions
and
80 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
// Unless explicitly stated otherwise all files in this repository are licensed | ||
// under the Apache License Version 2.0. | ||
// This product includes software developed at Datadog (https://www.datadoghq.com/). | ||
// Copyright 2016-present Datadog, Inc. | ||
|
||
package waf | ||
|
||
import ( | ||
"fmt" | ||
"sync" | ||
"time" | ||
) | ||
|
||
// Stats stores the metrics collected by the WAF. | ||
type Stats struct { | ||
// Timers returns a map of metrics and their durations. | ||
Timers map[string]time.Duration | ||
|
||
// Timeout | ||
TimeoutCount uint64 | ||
|
||
// Truncations provides details about truncations that occurred while | ||
// encoding address data for WAF execution. | ||
Truncations map[TruncationReason][]int | ||
} | ||
|
||
const ( | ||
wafPersistentEncoderTag = "_dd.appsec.waf.encode.persistent" | ||
wafEphemeralEncoderTag = "_dd.appsec.waf.encode.ephemeral" | ||
wafRunTag = "_dd.appsec.waf.run" | ||
wafDurationTag = "_dd.appsec.waf.duration" | ||
wafDurationExtTag = "_dd.appsec.waf.duration_ext" | ||
wafTimeoutTag = "_dd.appsec.waf.timeouts" | ||
wafTruncationTag = "_dd.appsec.waf.truncations" | ||
) | ||
|
||
// Metrics transform the stats returned by the WAF into a map of key value metrics for datadog backend | ||
func (stats *Stats) Metrics() map[string]any { | ||
tags := make(map[string]any, len(stats.Timers)+len(stats.Truncations)+1) | ||
for k, v := range stats.Timers { | ||
tags[k] = uint64(v.Microseconds()) | ||
} | ||
|
||
tags[wafTimeoutTag] = stats.TimeoutCount | ||
for reason, list := range stats.Truncations { | ||
tags[fmt.Sprintf("%s.%s", wafTruncationTag, reason.String())] = list | ||
} | ||
|
||
return tags | ||
} | ||
|
||
type metricsStore struct { | ||
data map[string]time.Duration | ||
mutex sync.RWMutex | ||
} | ||
|
||
func (metrics *metricsStore) add(key string, duration time.Duration) { | ||
metrics.mutex.Lock() | ||
defer metrics.mutex.Unlock() | ||
if metrics.data == nil { | ||
metrics.data = make(map[string]time.Duration, 5) | ||
} | ||
|
||
metrics.data[key] += duration | ||
} | ||
|
||
func (metrics *metricsStore) get(key string) time.Duration { | ||
metrics.mutex.RLock() | ||
defer metrics.mutex.RUnlock() | ||
return metrics.data[key] | ||
} | ||
|
||
func (metrics *metricsStore) copy() map[string]time.Duration { | ||
metrics.mutex.Lock() | ||
defer metrics.mutex.Unlock() | ||
if metrics.data == nil { | ||
return nil | ||
} | ||
|
||
copy := make(map[string]time.Duration, len(metrics.data)) | ||
for k, v := range metrics.data { | ||
copy[k] = v | ||
} | ||
return copy | ||
} | ||
|
||
// merge merges the current metrics with new ones | ||
func (metrics *metricsStore) merge(other map[string]time.Duration) { | ||
metrics.mutex.Lock() | ||
defer metrics.mutex.Unlock() | ||
if metrics.data == nil { | ||
metrics.data = make(map[string]time.Duration, 5) | ||
} | ||
|
||
for key, val := range other { | ||
prev, ok := metrics.data[key] | ||
if !ok { | ||
prev = 0 | ||
} | ||
metrics.data[key] = prev + val | ||
} | ||
} |
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