2019-05-22 21:16:55 +00:00
|
|
|
package common
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2019-08-23 06:46:45 +00:00
|
|
|
"net/http"
|
2019-05-22 21:16:55 +00:00
|
|
|
|
2020-07-02 16:42:12 +00:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/app/vminsert/relabel"
|
2019-05-22 21:16:55 +00:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmstorage"
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
|
2019-08-23 06:46:45 +00:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
|
2024-11-26 11:45:17 +00:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
|
2024-05-12 09:24:48 +00:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/slicesutil"
|
2019-05-22 21:16:55 +00:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/storage"
|
|
|
|
)
|
|
|
|
|
|
|
|
// InsertCtx contains common bits for data points insertion.
|
|
|
|
type InsertCtx struct {
|
2021-03-31 20:12:56 +00:00
|
|
|
Labels sortedLabels
|
2019-05-22 21:16:55 +00:00
|
|
|
|
|
|
|
mrs []storage.MetricRow
|
|
|
|
metricNamesBuf []byte
|
2020-07-02 16:42:12 +00:00
|
|
|
|
2023-01-04 06:19:18 +00:00
|
|
|
relabelCtx relabel.Ctx
|
|
|
|
streamAggrCtx streamAggrCtx
|
|
|
|
|
|
|
|
skipStreamAggr bool
|
2019-05-22 21:16:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Reset resets ctx for future fill with rowsLen rows.
|
|
|
|
func (ctx *InsertCtx) Reset(rowsLen int) {
|
2024-01-14 20:33:19 +00:00
|
|
|
labels := ctx.Labels
|
|
|
|
for i := range labels {
|
2024-11-26 11:45:17 +00:00
|
|
|
labels[i] = prompbmarshal.Label{}
|
2019-05-22 21:16:55 +00:00
|
|
|
}
|
2024-01-14 20:33:19 +00:00
|
|
|
ctx.Labels = labels[:0]
|
2019-05-22 21:16:55 +00:00
|
|
|
|
2023-07-24 23:44:09 +00:00
|
|
|
mrs := ctx.mrs
|
|
|
|
for i := range mrs {
|
|
|
|
cleanMetricRow(&mrs[i])
|
2019-05-22 21:16:55 +00:00
|
|
|
}
|
2024-05-12 09:24:48 +00:00
|
|
|
mrs = slicesutil.SetLength(mrs, rowsLen)
|
2023-07-24 23:44:09 +00:00
|
|
|
ctx.mrs = mrs[:0]
|
|
|
|
|
2019-05-22 21:16:55 +00:00
|
|
|
ctx.metricNamesBuf = ctx.metricNamesBuf[:0]
|
2020-07-02 16:42:12 +00:00
|
|
|
ctx.relabelCtx.Reset()
|
2023-01-04 06:19:18 +00:00
|
|
|
ctx.streamAggrCtx.Reset()
|
|
|
|
ctx.skipStreamAggr = false
|
2019-05-22 21:16:55 +00:00
|
|
|
}
|
|
|
|
|
2023-07-24 23:44:09 +00:00
|
|
|
func cleanMetricRow(mr *storage.MetricRow) {
|
|
|
|
mr.MetricNameRaw = nil
|
|
|
|
}
|
|
|
|
|
2024-11-26 11:45:17 +00:00
|
|
|
func (ctx *InsertCtx) marshalMetricNameRaw(prefix []byte, labels []prompbmarshal.Label) []byte {
|
2019-05-22 21:16:55 +00:00
|
|
|
start := len(ctx.metricNamesBuf)
|
|
|
|
ctx.metricNamesBuf = append(ctx.metricNamesBuf, prefix...)
|
|
|
|
ctx.metricNamesBuf = storage.MarshalMetricNameRaw(ctx.metricNamesBuf, labels)
|
|
|
|
metricNameRaw := ctx.metricNamesBuf[start:]
|
|
|
|
return metricNameRaw[:len(metricNameRaw):len(metricNameRaw)]
|
|
|
|
}
|
|
|
|
|
2019-12-09 18:58:19 +00:00
|
|
|
// WriteDataPoint writes (timestamp, value) with the given prefix and labels into ctx buffer.
|
2024-11-26 11:45:17 +00:00
|
|
|
func (ctx *InsertCtx) WriteDataPoint(prefix []byte, labels []prompbmarshal.Label, timestamp int64, value float64) error {
|
2019-05-22 21:16:55 +00:00
|
|
|
metricNameRaw := ctx.marshalMetricNameRaw(prefix, labels)
|
2020-07-24 20:19:49 +00:00
|
|
|
return ctx.addRow(metricNameRaw, timestamp, value)
|
2019-05-22 21:16:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// WriteDataPointExt writes (timestamp, value) with the given metricNameRaw and labels into ctx buffer.
|
|
|
|
//
|
|
|
|
// It returns metricNameRaw for the given labels if len(metricNameRaw) == 0.
|
2024-11-26 11:45:17 +00:00
|
|
|
func (ctx *InsertCtx) WriteDataPointExt(metricNameRaw []byte, labels []prompbmarshal.Label, timestamp int64, value float64) ([]byte, error) {
|
2019-05-22 21:16:55 +00:00
|
|
|
if len(metricNameRaw) == 0 {
|
|
|
|
metricNameRaw = ctx.marshalMetricNameRaw(nil, labels)
|
|
|
|
}
|
2020-07-24 20:19:49 +00:00
|
|
|
err := ctx.addRow(metricNameRaw, timestamp, value)
|
|
|
|
return metricNameRaw, err
|
2019-05-22 21:16:55 +00:00
|
|
|
}
|
|
|
|
|
2020-07-24 20:19:49 +00:00
|
|
|
func (ctx *InsertCtx) addRow(metricNameRaw []byte, timestamp int64, value float64) error {
|
2019-05-22 21:16:55 +00:00
|
|
|
mrs := ctx.mrs
|
|
|
|
if cap(mrs) > len(mrs) {
|
|
|
|
mrs = mrs[:len(mrs)+1]
|
|
|
|
} else {
|
|
|
|
mrs = append(mrs, storage.MetricRow{})
|
|
|
|
}
|
|
|
|
mr := &mrs[len(mrs)-1]
|
|
|
|
ctx.mrs = mrs
|
|
|
|
mr.MetricNameRaw = metricNameRaw
|
|
|
|
mr.Timestamp = timestamp
|
|
|
|
mr.Value = value
|
2020-07-26 09:09:01 +00:00
|
|
|
if len(ctx.metricNamesBuf) > 16*1024*1024 {
|
|
|
|
if err := ctx.FlushBufs(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2020-07-24 20:19:49 +00:00
|
|
|
return nil
|
2019-05-22 21:16:55 +00:00
|
|
|
}
|
|
|
|
|
2019-12-09 18:58:19 +00:00
|
|
|
// AddLabelBytes adds (name, value) label to ctx.Labels.
|
|
|
|
//
|
|
|
|
// name and value must exist until ctx.Labels is used.
|
|
|
|
func (ctx *InsertCtx) AddLabelBytes(name, value []byte) {
|
2020-07-23 09:50:41 +00:00
|
|
|
if len(value) == 0 {
|
|
|
|
// Skip labels without values, since they have no sense.
|
|
|
|
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/600
|
|
|
|
// Do not skip labels with empty name, since they are equal to __name__.
|
|
|
|
return
|
2019-12-09 18:58:19 +00:00
|
|
|
}
|
2024-11-26 11:45:17 +00:00
|
|
|
ctx.Labels = append(ctx.Labels, prompbmarshal.Label{
|
2020-07-23 09:50:41 +00:00
|
|
|
// Do not copy name and value contents for performance reasons.
|
|
|
|
// This reduces GC overhead on the number of objects and allocations.
|
2024-01-14 20:33:19 +00:00
|
|
|
Name: bytesutil.ToUnsafeString(name),
|
|
|
|
Value: bytesutil.ToUnsafeString(value),
|
2020-07-23 09:50:41 +00:00
|
|
|
})
|
2019-12-09 18:58:19 +00:00
|
|
|
}
|
|
|
|
|
2019-05-22 21:16:55 +00:00
|
|
|
// AddLabel adds (name, value) label to ctx.Labels.
|
|
|
|
//
|
|
|
|
// name and value must exist until ctx.Labels is used.
|
|
|
|
func (ctx *InsertCtx) AddLabel(name, value string) {
|
2020-07-23 09:50:41 +00:00
|
|
|
if len(value) == 0 {
|
|
|
|
// Skip labels without values, since they have no sense.
|
|
|
|
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/600
|
|
|
|
// Do not skip labels with empty name, since they are equal to __name__.
|
|
|
|
return
|
2019-05-22 21:16:55 +00:00
|
|
|
}
|
2024-11-26 11:45:17 +00:00
|
|
|
ctx.Labels = append(ctx.Labels, prompbmarshal.Label{
|
2020-07-23 09:50:41 +00:00
|
|
|
// Do not copy name and value contents for performance reasons.
|
|
|
|
// This reduces GC overhead on the number of objects and allocations.
|
2024-01-14 20:33:19 +00:00
|
|
|
Name: name,
|
|
|
|
Value: value,
|
2020-07-23 09:50:41 +00:00
|
|
|
})
|
2019-05-22 21:16:55 +00:00
|
|
|
}
|
|
|
|
|
2020-07-02 16:42:12 +00:00
|
|
|
// ApplyRelabeling applies relabeling to ic.Labels.
|
|
|
|
func (ctx *InsertCtx) ApplyRelabeling() {
|
|
|
|
ctx.Labels = ctx.relabelCtx.ApplyRelabeling(ctx.Labels)
|
|
|
|
}
|
|
|
|
|
2019-05-22 21:16:55 +00:00
|
|
|
// FlushBufs flushes buffered rows to the underlying storage.
|
|
|
|
func (ctx *InsertCtx) FlushBufs() error {
|
2023-04-01 04:27:45 +00:00
|
|
|
sas := sasGlobal.Load()
|
2024-05-20 12:03:28 +00:00
|
|
|
if (sas.IsEnabled() || deduplicator != nil) && !ctx.skipStreamAggr {
|
2023-07-24 23:44:09 +00:00
|
|
|
matchIdxs := matchIdxsPool.Get()
|
|
|
|
matchIdxs.B = ctx.streamAggrCtx.push(ctx.mrs, matchIdxs.B)
|
2023-01-04 06:19:18 +00:00
|
|
|
if !*streamAggrKeepInput {
|
2023-07-24 23:44:09 +00:00
|
|
|
// Remove aggregated rows from ctx.mrs
|
|
|
|
ctx.dropAggregatedRows(matchIdxs.B)
|
2023-01-04 06:19:18 +00:00
|
|
|
}
|
2023-07-24 23:44:09 +00:00
|
|
|
matchIdxsPool.Put(matchIdxs)
|
2023-01-04 06:19:18 +00:00
|
|
|
}
|
2023-01-07 06:40:07 +00:00
|
|
|
// There is no need in limiting the number of concurrent calls to vmstorage.AddRows() here,
|
|
|
|
// since the number of concurrent FlushBufs() calls should be already limited via writeconcurrencylimiter
|
2023-02-13 18:51:55 +00:00
|
|
|
// used at every stream.Parse() call under lib/protoparser/*
|
2020-07-24 20:19:49 +00:00
|
|
|
err := vmstorage.AddRows(ctx.mrs)
|
|
|
|
ctx.Reset(0)
|
|
|
|
if err == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return &httpserver.ErrorWithStatusCode{
|
|
|
|
Err: fmt.Errorf("cannot store metrics: %w", err),
|
|
|
|
StatusCode: http.StatusServiceUnavailable,
|
2019-05-22 21:16:55 +00:00
|
|
|
}
|
|
|
|
}
|
2023-07-24 23:44:09 +00:00
|
|
|
|
|
|
|
func (ctx *InsertCtx) dropAggregatedRows(matchIdxs []byte) {
|
|
|
|
dst := ctx.mrs[:0]
|
|
|
|
src := ctx.mrs
|
|
|
|
if !*streamAggrDropInput {
|
|
|
|
for idx, match := range matchIdxs {
|
2023-08-10 12:27:21 +00:00
|
|
|
if match == 1 {
|
2023-07-24 23:44:09 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
dst = append(dst, src[idx])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tail := src[len(dst):]
|
|
|
|
for i := range tail {
|
|
|
|
cleanMetricRow(&tail[i])
|
|
|
|
}
|
|
|
|
ctx.mrs = dst
|
|
|
|
}
|
|
|
|
|
|
|
|
var matchIdxsPool bytesutil.ByteBufferPool
|