mirror of
https://github.com/imgproxy/imgproxy.git
synced 2025-01-23 11:14:48 +02:00
201 lines
6.2 KiB
Go
201 lines
6.2 KiB
Go
package internal
|
|
|
|
import (
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// Harvestable is something that can be merged into a Harvest.
|
|
type Harvestable interface {
|
|
MergeIntoHarvest(h *Harvest)
|
|
}
|
|
|
|
// Harvest contains collected data.
|
|
type Harvest struct {
|
|
Metrics *metricTable
|
|
CustomEvents *customEvents
|
|
TxnEvents *txnEvents
|
|
ErrorEvents *errorEvents
|
|
ErrorTraces harvestErrors
|
|
TxnTraces *harvestTraces
|
|
SlowSQLs *slowQueries
|
|
SpanEvents *spanEvents
|
|
}
|
|
|
|
const (
|
|
// txnEventPayloadlimit is the maximum number of events that should be
|
|
// sent up in one post.
|
|
txnEventPayloadlimit = 5000
|
|
)
|
|
|
|
// Payloads returns a map from expected collector method name to data type.
|
|
func (h *Harvest) Payloads(splitLargeTxnEvents bool) []PayloadCreator {
|
|
ps := []PayloadCreator{
|
|
h.Metrics,
|
|
h.CustomEvents,
|
|
h.ErrorEvents,
|
|
h.ErrorTraces,
|
|
h.TxnTraces,
|
|
h.SlowSQLs,
|
|
h.SpanEvents,
|
|
}
|
|
if splitLargeTxnEvents {
|
|
ps = append(ps, h.TxnEvents.payloads(txnEventPayloadlimit)...)
|
|
} else {
|
|
ps = append(ps, h.TxnEvents)
|
|
}
|
|
return ps
|
|
}
|
|
|
|
// NewHarvest returns a new Harvest.
|
|
func NewHarvest(now time.Time) *Harvest {
|
|
return &Harvest{
|
|
Metrics: newMetricTable(maxMetrics, now),
|
|
CustomEvents: newCustomEvents(maxCustomEvents),
|
|
TxnEvents: newTxnEvents(maxTxnEvents),
|
|
ErrorEvents: newErrorEvents(maxErrorEvents),
|
|
ErrorTraces: newHarvestErrors(maxHarvestErrors),
|
|
TxnTraces: newHarvestTraces(),
|
|
SlowSQLs: newSlowQueries(maxHarvestSlowSQLs),
|
|
SpanEvents: newSpanEvents(maxSpanEvents),
|
|
}
|
|
}
|
|
|
|
var (
|
|
trackMutex sync.Mutex
|
|
trackMetrics []string
|
|
)
|
|
|
|
// TrackUsage helps track which integration packages are used.
|
|
func TrackUsage(s ...string) {
|
|
trackMutex.Lock()
|
|
defer trackMutex.Unlock()
|
|
|
|
m := "Supportability/" + strings.Join(s, "/")
|
|
trackMetrics = append(trackMetrics, m)
|
|
}
|
|
|
|
func createTrackUsageMetrics(metrics *metricTable) {
|
|
trackMutex.Lock()
|
|
defer trackMutex.Unlock()
|
|
|
|
for _, m := range trackMetrics {
|
|
metrics.addSingleCount(m, forced)
|
|
}
|
|
}
|
|
|
|
// CreateFinalMetrics creates extra metrics at harvest time.
|
|
func (h *Harvest) CreateFinalMetrics() {
|
|
h.Metrics.addSingleCount(instanceReporting, forced)
|
|
|
|
h.Metrics.addCount(customEventsSeen, h.CustomEvents.numSeen(), forced)
|
|
h.Metrics.addCount(customEventsSent, h.CustomEvents.numSaved(), forced)
|
|
|
|
h.Metrics.addCount(txnEventsSeen, h.TxnEvents.numSeen(), forced)
|
|
h.Metrics.addCount(txnEventsSent, h.TxnEvents.numSaved(), forced)
|
|
|
|
h.Metrics.addCount(errorEventsSeen, h.ErrorEvents.numSeen(), forced)
|
|
h.Metrics.addCount(errorEventsSent, h.ErrorEvents.numSaved(), forced)
|
|
|
|
h.Metrics.addCount(spanEventsSeen, h.SpanEvents.numSeen(), forced)
|
|
h.Metrics.addCount(spanEventsSent, h.SpanEvents.numSaved(), forced)
|
|
|
|
if h.Metrics.numDropped > 0 {
|
|
h.Metrics.addCount(supportabilityDropped, float64(h.Metrics.numDropped), forced)
|
|
}
|
|
|
|
createTrackUsageMetrics(h.Metrics)
|
|
}
|
|
|
|
// PayloadCreator is a data type in the harvest.
|
|
type PayloadCreator interface {
|
|
// In the event of a rpm request failure (hopefully simply an
|
|
// intermittent collector issue) the payload may be merged into the next
|
|
// time period's harvest.
|
|
Harvestable
|
|
// Data prepares JSON in the format expected by the collector endpoint.
|
|
// This method should return (nil, nil) if the payload is empty and no
|
|
// rpm request is necessary.
|
|
Data(agentRunID string, harvestStart time.Time) ([]byte, error)
|
|
// EndpointMethod is used for the "method" query parameter when posting
|
|
// the data.
|
|
EndpointMethod() string
|
|
}
|
|
|
|
func supportMetric(metrics *metricTable, b bool, metricName string) {
|
|
if b {
|
|
metrics.addSingleCount(metricName, forced)
|
|
}
|
|
}
|
|
|
|
// CreateTxnMetrics creates metrics for a transaction.
|
|
func CreateTxnMetrics(args *TxnData, metrics *metricTable) {
|
|
// Duration Metrics
|
|
rollup := backgroundRollup
|
|
if args.IsWeb {
|
|
rollup = webRollup
|
|
metrics.addDuration(dispatcherMetric, "", args.Duration, 0, forced)
|
|
}
|
|
|
|
metrics.addDuration(args.FinalName, "", args.Duration, args.Exclusive, forced)
|
|
metrics.addDuration(rollup, "", args.Duration, args.Exclusive, forced)
|
|
|
|
// Better CAT Metrics
|
|
if cat := args.BetterCAT; cat.Enabled {
|
|
caller := callerUnknown
|
|
if nil != cat.Inbound {
|
|
caller = cat.Inbound.payloadCaller
|
|
}
|
|
m := durationByCallerMetric(caller)
|
|
metrics.addDuration(m.all, "", args.Duration, args.Duration, unforced)
|
|
metrics.addDuration(m.webOrOther(args.IsWeb), "", args.Duration, args.Duration, unforced)
|
|
|
|
// Transport Duration Metric
|
|
if nil != cat.Inbound {
|
|
d := cat.Inbound.TransportDuration
|
|
m = transportDurationMetric(caller)
|
|
metrics.addDuration(m.all, "", d, d, unforced)
|
|
metrics.addDuration(m.webOrOther(args.IsWeb), "", d, d, unforced)
|
|
}
|
|
|
|
// CAT Error Metrics
|
|
if args.HasErrors() {
|
|
m = errorsByCallerMetric(caller)
|
|
metrics.addSingleCount(m.all, unforced)
|
|
metrics.addSingleCount(m.webOrOther(args.IsWeb), unforced)
|
|
}
|
|
|
|
supportMetric(metrics, args.AcceptPayloadSuccess, supportTracingAcceptSuccess)
|
|
supportMetric(metrics, args.AcceptPayloadException, supportTracingAcceptException)
|
|
supportMetric(metrics, args.AcceptPayloadParseException, supportTracingAcceptParseException)
|
|
supportMetric(metrics, args.AcceptPayloadCreateBeforeAccept, supportTracingCreateBeforeAccept)
|
|
supportMetric(metrics, args.AcceptPayloadIgnoredMultiple, supportTracingIgnoredMultiple)
|
|
supportMetric(metrics, args.AcceptPayloadIgnoredVersion, supportTracingIgnoredVersion)
|
|
supportMetric(metrics, args.AcceptPayloadUntrustedAccount, supportTracingAcceptUntrustedAccount)
|
|
supportMetric(metrics, args.AcceptPayloadNullPayload, supportTracingAcceptNull)
|
|
supportMetric(metrics, args.CreatePayloadSuccess, supportTracingCreatePayloadSuccess)
|
|
supportMetric(metrics, args.CreatePayloadException, supportTracingCreatePayloadException)
|
|
}
|
|
|
|
// Apdex Metrics
|
|
if args.Zone != ApdexNone {
|
|
metrics.addApdex(apdexRollup, "", args.ApdexThreshold, args.Zone, forced)
|
|
|
|
mname := apdexPrefix + removeFirstSegment(args.FinalName)
|
|
metrics.addApdex(mname, "", args.ApdexThreshold, args.Zone, unforced)
|
|
}
|
|
|
|
// Error Metrics
|
|
if args.HasErrors() {
|
|
metrics.addSingleCount(errorsRollupMetric.all, forced)
|
|
metrics.addSingleCount(errorsRollupMetric.webOrOther(args.IsWeb), forced)
|
|
metrics.addSingleCount(errorsPrefix+args.FinalName, forced)
|
|
}
|
|
|
|
// Queueing Metrics
|
|
if args.Queuing > 0 {
|
|
metrics.addDuration(queueMetric, "", args.Queuing, args.Queuing, forced)
|
|
}
|
|
}
|