influxdb/services/opentsdb/service.go

495 lines
13 KiB
Go
Raw Normal View History

// Package opentsdb provides a service for InfluxDB to ingest data via the opentsdb protocol.
2016-02-10 18:30:52 +00:00
package opentsdb // import "github.com/influxdata/influxdb/services/opentsdb"
import (
"bufio"
"bytes"
2015-07-31 18:00:22 +00:00
"crypto/tls"
"io"
"net"
"net/http"
"net/textproto"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
"github.com/influxdata/influxdb/logger"
"github.com/influxdata/influxdb/models"
"github.com/influxdata/influxdb/services/meta"
"github.com/influxdata/influxdb/tsdb"
"go.uber.org/zap"
)
// statistics gathered by the openTSDB package.
const (
statHTTPConnectionsHandled = "httpConnsHandled"
statTelnetConnectionsActive = "tlConnsActive"
statTelnetConnectionsHandled = "tlConnsHandled"
statTelnetPointsReceived = "tlPointsRx"
statTelnetBytesReceived = "tlBytesRx"
statTelnetReadError = "tlReadErr"
statTelnetBadLine = "tlBadLine"
statTelnetBadTime = "tlBadTime"
statTelnetBadTag = "tlBadTag"
statTelnetBadFloat = "tlBadFloat"
statBatchesTransmitted = "batchesTx"
statPointsTransmitted = "pointsTx"
statBatchesTransmitFail = "batchesTxFail"
statConnectionsActive = "connsActive"
statConnectionsHandled = "connsHandled"
statDroppedPointsInvalid = "droppedPointsInvalid"
)
// Service manages the listener and handler for an HTTP endpoint.
type Service struct {
ln net.Listener // main listener
httpln *chanListener // http channel-based listener
2018-08-02 19:42:48 +00:00
wg sync.WaitGroup
tls bool
tlsConfig *tls.Config
cert string
mu sync.RWMutex
ready bool // Has the required database been created?
done chan struct{} // Is the service closing or closed?
BindAddress string
Database string
RetentionPolicy string
PointsWriter interface {
feat: measurement metrics by login (#20687) After turning on authentication and both forms of ingress metrics: "ingress": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"cq","rp":"monitor"},"values":{"pointsWritten":38,"valuesWritten":76}}, "ingress:1": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"database","rp":"monitor"},"values":{"pointsWritten":76,"valuesWritten":152}}, "ingress:2": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"httpd","rp":"monitor"},"values":{"pointsWritten":38,"valuesWritten":874}}, "ingress:3": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"ingress","rp":"monitor"},"values":{"pointsWritten":534,"valuesWritten":1068}}, "ingress:4": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"localStore","rp":"monitor"},"values":{"pointsWritten":38,"valuesWritten":76}}, "ingress:5": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"queryExecutor","rp":"monitor"},"values":{"pointsWritten":38,"valuesWritten":190}}, "ingress:6": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"runtime","rp":"monitor"},"values":{"pointsWritten":38,"valuesWritten":570}}, "ingress:7": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"shard","rp":"monitor"},"values":{"pointsWritten":76,"valuesWritten":836}}, "ingress:8": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"subscriber","rp":"monitor"},"values":{"pointsWritten":38,"valuesWritten":114}}, "ingress:9": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"tsm1_cache","rp":"monitor"},"values":{"pointsWritten":76,"valuesWritten":684}}, "ingress:10": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"tsm1_engine","rp":"monitor"},"values":{"pointsWritten":76,"valuesWritten":2204}}, "ingress:11": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"tsm1_filestore","rp":"monitor"},"values":{"pointsWritten":76,"valuesWritten":152}}, "ingress:12": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"tsm1_wal","rp":"monitor"},"values":{"pointsWritten":76,"valuesWritten":304}}, "ingress:13": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"write","rp":"monitor"},"values":{"pointsWritten":38,"valuesWritten":342}}, "ingress:14": {"name":"ingress","tags":{"db":"telegraf","login":"admin","measurement":"cpu","rp":"autogen"},"values":{"pointsWritten":1,"valuesWritten":1}}, "ingress:15": {"name":"ingress","tags":{"db":"telegraf","login":"telegraf","measurement":"cpu","rp":"autogen"},"values":{"pointsWritten":1316,"valuesWritten":13160}}, "ingress:16": {"name":"ingress","tags":{"db":"telegraf","login":"telegraf","measurement":"disk","rp":"autogen"},"values":{"pointsWritten":642,"valuesWritten":4494}}, "ingress:17": {"name":"ingress","tags":{"db":"telegraf","login":"telegraf","measurement":"diskio","rp":"autogen"},"values":{"pointsWritten":214,"valuesWritten":2354}}, "ingress:18": {"name":"ingress","tags":{"db":"telegraf","login":"telegraf","measurement":"mem","rp":"autogen"},"values":{"pointsWritten":107,"valuesWritten":963}}, "ingress:19": {"name":"ingress","tags":{"db":"telegraf","login":"telegraf","measurement":"processes","rp":"autogen"},"values":{"pointsWritten":107,"valuesWritten":856}}, "ingress:20": {"name":"ingress","tags":{"db":"telegraf","login":"telegraf","measurement":"swap","rp":"autogen"},"values":{"pointsWritten":214,"valuesWritten":642}}, "ingress:21": {"name":"ingress","tags":{"db":"telegraf","login":"telegraf","measurement":"system","rp":"autogen"},"values":{"pointsWritten":321,"valuesWritten":749}}, Only by login: "ingress": {"name":"ingress","tags":{"login":"_systemuser_monitor"},"values":{"pointsWritten":42,"valuesWritten":354}}, "ingress:1": {"name":"ingress","tags":{"login":"admin"},"values":{"pointsWritten":1,"valuesWritten":1}}, "ingress:2": {"name":"ingress","tags":{"login":"telegraf"},"values":{"pointsWritten":3547,"valuesWritten":28246}}, Notice writes by users 'telegraf', '_systemuser_monitor', and 'admin'.
2021-02-04 16:52:53 +00:00
WritePointsPrivileged(ctx tsdb.WriteContext, database, retentionPolicy string, consistencyLevel models.ConsistencyLevel, points []models.Point) error
}
2015-12-23 15:48:25 +00:00
MetaClient interface {
CreateDatabase(name string) (*meta.DatabaseInfo, error)
2015-06-11 01:29:13 +00:00
}
// Points received over the telnet protocol are batched.
batchSize int
batchPending int
batchTimeout time.Duration
batcher *tsdb.PointBatcher
LogPointErrors bool
Logger *zap.Logger
stats *Statistics
defaultTags models.StatisticTags
}
// NewService returns a new instance of Service.
func NewService(c Config) (*Service, error) {
2016-04-05 21:36:07 +00:00
// Use defaults where necessary.
d := c.WithDefaults()
s := &Service{
2016-04-05 21:36:07 +00:00
tls: d.TLSEnabled,
2018-08-02 19:42:48 +00:00
tlsConfig: d.TLS,
2016-04-05 21:36:07 +00:00
cert: d.Certificate,
BindAddress: d.BindAddress,
Database: d.Database,
RetentionPolicy: d.RetentionPolicy,
batchSize: d.BatchSize,
batchPending: d.BatchPending,
batchTimeout: time.Duration(d.BatchTimeout),
Logger: zap.NewNop(),
2016-04-05 21:36:07 +00:00
LogPointErrors: d.LogPointErrors,
stats: &Statistics{},
defaultTags: models.StatisticTags{"bind": d.BindAddress},
}
2018-08-02 19:42:48 +00:00
if s.tlsConfig == nil {
s.tlsConfig = new(tls.Config)
}
return s, nil
}
// Open starts the service.
func (s *Service) Open() error {
s.mu.Lock()
defer s.mu.Unlock()
if s.done != nil {
return nil // Already open.
}
s.done = make(chan struct{})
s.Logger.Info("Starting OpenTSDB service")
s.batcher = tsdb.NewPointBatcher(s.batchSize, s.batchPending, s.batchTimeout)
s.batcher.Start()
// Start processing batches.
s.wg.Add(1)
go func() { defer s.wg.Done(); s.processBatches(s.batcher) }()
// Open listener.
2015-07-31 18:00:22 +00:00
if s.tls {
cert, err := tls.LoadX509KeyPair(s.cert, s.cert)
if err != nil {
return err
}
2018-08-02 19:42:48 +00:00
tlsConfig := s.tlsConfig.Clone()
tlsConfig.Certificates = []tls.Certificate{cert}
listener, err := tls.Listen("tcp", s.BindAddress, tlsConfig)
2015-07-31 18:00:22 +00:00
if err != nil {
return err
}
s.ln = listener
} else {
listener, err := net.Listen("tcp", s.BindAddress)
if err != nil {
return err
}
s.ln = listener
}
s.Logger.Info("Listening on TCP",
zap.Stringer("addr", s.ln.Addr()),
zap.Bool("tls", s.tls))
2015-07-31 18:00:22 +00:00
s.httpln = newChanListener(s.ln.Addr())
// Begin listening for connections.
s.wg.Add(2)
go func() { defer s.wg.Done(); s.serve() }()
go func() { defer s.wg.Done(); s.serveHTTP() }()
return nil
}
// Close closes the openTSDB service.
func (s *Service) Close() error {
if wait, err := func() (bool, error) {
s.mu.Lock()
defer s.mu.Unlock()
if s.closed() {
return false, nil // Already closed.
}
close(s.done)
// Close the listeners.
if err := s.ln.Close(); err != nil {
return false, err
}
if err := s.httpln.Close(); err != nil {
return false, err
}
if s.batcher != nil {
s.batcher.Stop()
}
return true, nil
}(); err != nil {
return err
} else if !wait {
return nil
}
s.wg.Wait()
s.mu.Lock()
s.done = nil
s.mu.Unlock()
return nil
}
// Closed returns true if the service is currently closed.
func (s *Service) Closed() bool {
s.mu.Lock()
defer s.mu.Unlock()
return s.closed()
}
func (s *Service) closed() bool {
select {
case <-s.done:
// Service is closing.
return true
default:
return s.done == nil
}
}
// createInternalStorage ensures that the required database has been created.
func (s *Service) createInternalStorage() error {
s.mu.RLock()
ready := s.ready
s.mu.RUnlock()
if ready {
return nil
}
if _, err := s.MetaClient.CreateDatabase(s.Database); err != nil {
return err
}
// The service is now ready.
s.mu.Lock()
s.ready = true
s.mu.Unlock()
return nil
}
// WithLogger sets the logger for the service.
func (s *Service) WithLogger(log *zap.Logger) {
s.Logger = log.With(zap.String("service", "opentsdb"))
}
// Statistics maintains statistics for the subscriber service.
type Statistics struct {
HTTPConnectionsHandled int64
ActiveTelnetConnections int64
HandledTelnetConnections int64
TelnetPointsReceived int64
TelnetBytesReceived int64
TelnetReadError int64
TelnetBadLine int64
TelnetBadTime int64
TelnetBadTag int64
TelnetBadFloat int64
BatchesTransmitted int64
PointsTransmitted int64
BatchesTransmitFail int64
ActiveConnections int64
HandledConnections int64
InvalidDroppedPoints int64
}
// Statistics returns statistics for periodic monitoring.
func (s *Service) Statistics(tags map[string]string) []models.Statistic {
return []models.Statistic{{
Name: "opentsdb",
Tags: s.defaultTags.Merge(tags),
Values: map[string]interface{}{
statHTTPConnectionsHandled: atomic.LoadInt64(&s.stats.HTTPConnectionsHandled),
statTelnetConnectionsActive: atomic.LoadInt64(&s.stats.ActiveTelnetConnections),
statTelnetConnectionsHandled: atomic.LoadInt64(&s.stats.HandledTelnetConnections),
statTelnetPointsReceived: atomic.LoadInt64(&s.stats.TelnetPointsReceived),
statTelnetBytesReceived: atomic.LoadInt64(&s.stats.TelnetBytesReceived),
statTelnetReadError: atomic.LoadInt64(&s.stats.TelnetReadError),
statTelnetBadLine: atomic.LoadInt64(&s.stats.TelnetBadLine),
statTelnetBadTime: atomic.LoadInt64(&s.stats.TelnetBadTime),
statTelnetBadTag: atomic.LoadInt64(&s.stats.TelnetBadTag),
statTelnetBadFloat: atomic.LoadInt64(&s.stats.TelnetBadFloat),
statBatchesTransmitted: atomic.LoadInt64(&s.stats.BatchesTransmitted),
statPointsTransmitted: atomic.LoadInt64(&s.stats.PointsTransmitted),
statBatchesTransmitFail: atomic.LoadInt64(&s.stats.BatchesTransmitFail),
statConnectionsActive: atomic.LoadInt64(&s.stats.ActiveConnections),
statConnectionsHandled: atomic.LoadInt64(&s.stats.HandledConnections),
statDroppedPointsInvalid: atomic.LoadInt64(&s.stats.InvalidDroppedPoints),
},
}}
}
// Addr returns the listener's address. Returns nil if listener is closed.
func (s *Service) Addr() net.Addr {
if s.ln == nil {
return nil
}
return s.ln.Addr()
}
// serve serves the handler from the listener.
func (s *Service) serve() {
for {
// Wait for next connection.
conn, err := s.ln.Accept()
if opErr, ok := err.(*net.OpError); ok && !opErr.Temporary() {
s.Logger.Info("OpenTSDB TCP listener closed")
return
} else if err != nil {
s.Logger.Info("Error accepting OpenTSDB", zap.Error(err))
continue
}
// Handle connection in separate goroutine.
go s.handleConn(conn)
}
}
// handleConn processes conn. This is run in a separate goroutine.
func (s *Service) handleConn(conn net.Conn) {
defer atomic.AddInt64(&s.stats.ActiveConnections, -1)
atomic.AddInt64(&s.stats.ActiveConnections, 1)
atomic.AddInt64(&s.stats.HandledConnections, 1)
2015-09-09 20:16:52 +00:00
// Read header into buffer to check if it's HTTP.
var buf bytes.Buffer
r := bufio.NewReader(io.TeeReader(conn, &buf))
// Attempt to parse connection as HTTP.
_, err := http.ReadRequest(r)
// Rebuild connection from buffer and remaining connection data.
bufr := bufio.NewReader(io.MultiReader(&buf, conn))
conn = &readerConn{Conn: conn, r: bufr}
// If no HTTP parsing error occurred then process as HTTP.
if err == nil {
atomic.AddInt64(&s.stats.HTTPConnectionsHandled, 1)
s.httpln.ch <- conn
return
}
// Otherwise handle in telnet format.
s.wg.Add(1)
s.handleTelnetConn(conn)
s.wg.Done()
}
// handleTelnetConn accepts OpenTSDB's telnet protocol.
// Each telnet command consists of a line of the form:
chore: update to go 1.19 (#24119) * chore: update to go 1.19.6 * chore: gofmt * test: fix tests for sort order change * chore: generate pb * feat: upgrade flux to v0.188.0 (#23911) * feat: upgrade flux to 0.171.0 Tests failing, safety commit First step in https://github.com/influxdata/influxdb/issues/23815 * fix: remove "org" parameter" from writeOptSource I attempted to implement the "orgOpt" argument in a similar fashion to f6669f7512. However, it looks like Flux doesn't accept "org" as a parameter to "load". It responds with: Error calling function \"load\" @113:16-113:30: error calling function \"to\" @6:19-6:47: unused arguments [org] This brings us from 194 passing to 570 passing. * fix: temporarily disable broken flux tests These tests expect rows to be stored in a certain order. However, nothing is specifying the sort order. This has been fixed in a later update to flux: (see 3d6f47ded). Temporarily disable these tests until we include a fixed version of the flux tests. * chore: add tests from a492993012 This fixes "test-flux.sh" so it runs tests within the "flux/" directory. This uncovered some other issues with the tests located within "flux/". These also needed to be updated to match the newer flux API. * feat: upgrade flux to 0.172.0 This includes changes made in "cbbf4b27da". Since "test.go" in 2.x diverged from 1.x, some modifications were required to make this compatible. * feat: upgrade flux to 0.173.0 * feat: upgrade flux to v0.174.0 * fix: Update the condition when reseting cursor (#23522) Filters that contain `or` may change between cursor resets so we must remember to update the condition in the read cursor. ```flux |> filter(fn: (r) => ((r["_field"] == "field1" and r["_value"]==true) or (r["_field"] == "field2" and r["_value"] == false))) ``` Closes https://github.com/influxdata/flux/issues/4804 * feat: upgrade flux to 0.174.1 * feat: upgrade flux to 0.175.0 * chore: remove end-to-end tests These were removed in a492993 for 2.x. These tests prevent "go test ./..." from completing. As stated in the original commit, these tests should now be handled by the "fluxtest" harness. * feat: upgrade flux to 0.176.0 Some tests needed to be disabled within the flux harness. This is a result of enabling "Optimize Aggregate Window" in flux@05a1065f. These tests are not present in 2.x. Therefore, I am unsure if the breakage is resolved in a later commit. * feat: upgrade flux to 0.177.0 * feat: upgrade flux to 0.178.0 * feat: upgrade flux to v0.179.0 This removes all invocations of "flux.RegisterOpSpec". According to flux@e39096d5, "flux.RegisterOpSpec" does nothing in the current version of flux and was removed. * chore: update fluxtest skip list (#23633) * chore: manually backport 785a465e9a This removes the reference to "flux.Spec". * build(flux): update flux to v0.181.0 (#23682) * build(flux): update flux to v0.184.2 * chore: skip more Flux acceptance tests There are issues for each skip detailed in test-flux.sh. * feat: upgrade flux to v0.185.0 This adds "FluxTesting" to the "HTTPD" configuration. This option is hidden and disabled by default. When "FluxTesting" is set, it enables the default testing flags for "Flux". These flags allow the "vectorized float tests" and tests requiring the "removeRedundantSortNodes" and "labelPolymorphism" flag enabled to work. These changes are based off of d8553c002e. flux@3d6f47ded is included within this version of Flux. Therefore we can now include the "group_*" tests. * feat: upgrade flux to 0.186.0 * feat: upgrade flux to 0.187.0 * feat: upgrade flux to 0.188.0 * fix: re-run ./generate.sh with updated protoc * fix: restrict cores to match CircleCI documentation Co-authored-by: davidby-influx <dbyrne@influxdata.com> Co-authored-by: Markus Westerlind <marwes91@gmail.com> Co-authored-by: Sean Brickley <sean@wabr.io> Co-authored-by: Jonathan A. Sternberg <jonathan@influxdata.com> Co-authored-by: Christopher M. Wolff <chris.wolff@influxdata.com> --------- Co-authored-by: Brandon Pfeifer <bpfeifer@influxdata.com> Co-authored-by: davidby-influx <dbyrne@influxdata.com> Co-authored-by: Markus Westerlind <marwes91@gmail.com> Co-authored-by: Sean Brickley <sean@wabr.io> Co-authored-by: Jonathan A. Sternberg <jonathan@influxdata.com> Co-authored-by: Christopher M. Wolff <chris.wolff@influxdata.com>
2023-03-03 15:05:05 +00:00
//
// put sys.cpu.user 1356998400 42.5 host=webserver01 cpu=0
func (s *Service) handleTelnetConn(conn net.Conn) {
defer conn.Close()
defer atomic.AddInt64(&s.stats.ActiveTelnetConnections, -1)
atomic.AddInt64(&s.stats.ActiveTelnetConnections, 1)
atomic.AddInt64(&s.stats.HandledTelnetConnections, 1)
2015-09-09 20:16:52 +00:00
// Get connection details.
remoteAddr := conn.RemoteAddr().String()
// Wrap connection in a text protocol reader.
r := textproto.NewReader(bufio.NewReader(conn))
for {
line, err := r.ReadLine()
if err != nil {
if err != io.EOF {
atomic.AddInt64(&s.stats.TelnetReadError, 1)
s.Logger.Info("Error reading from OpenTSDB connection", zap.Error(err))
}
return
}
atomic.AddInt64(&s.stats.TelnetPointsReceived, 1)
atomic.AddInt64(&s.stats.TelnetBytesReceived, int64(len(line)))
inputStrs := strings.Fields(line)
if len(inputStrs) == 1 && inputStrs[0] == "version" {
conn.Write([]byte("InfluxDB TSDB proxy"))
continue
}
if len(inputStrs) < 4 || inputStrs[0] != "put" {
atomic.AddInt64(&s.stats.TelnetBadLine, 1)
if s.LogPointErrors {
s.Logger.Info("Malformed line", zap.String("line", line), zap.String("remote_addr", remoteAddr))
}
continue
}
measurement := inputStrs[1]
tsStr := inputStrs[2]
valueStr := inputStrs[3]
tagStrs := inputStrs[4:]
var t time.Time
ts, err := strconv.ParseInt(tsStr, 10, 64)
if err != nil {
atomic.AddInt64(&s.stats.TelnetBadTime, 1)
if s.LogPointErrors {
s.Logger.Info("Malformed time", zap.String("time", tsStr), zap.String("remote_addr", remoteAddr))
}
}
switch len(tsStr) {
case 10:
t = time.Unix(ts, 0)
case 13:
t = time.Unix(ts/1000, (ts%1000)*1000)
default:
atomic.AddInt64(&s.stats.TelnetBadTime, 1)
if s.LogPointErrors {
s.Logger.Info("Time must be 10 or 13 chars", zap.String("time", tsStr), zap.String("remote_addr", remoteAddr))
}
continue
}
tags := make(map[string]string)
for t := range tagStrs {
parts := strings.SplitN(tagStrs[t], "=", 2)
2015-07-22 01:40:43 +00:00
if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
atomic.AddInt64(&s.stats.TelnetBadTag, 1)
if s.LogPointErrors {
s.Logger.Info("Malformed tag data", zap.String("tag", tagStrs[t]), zap.String("remote_addr", remoteAddr))
}
continue
}
k := parts[0]
tags[k] = parts[1]
}
fields := make(map[string]interface{})
fv, err := strconv.ParseFloat(valueStr, 64)
if err != nil {
atomic.AddInt64(&s.stats.TelnetBadFloat, 1)
if s.LogPointErrors {
s.Logger.Info("Bad float", zap.String("value", valueStr), zap.String("remote_addr", remoteAddr))
}
continue
}
fields["value"] = fv
pt, err := models.NewPoint(measurement, models.NewTags(tags), fields, t)
if err != nil {
atomic.AddInt64(&s.stats.TelnetBadFloat, 1)
if s.LogPointErrors {
s.Logger.Info("Bad float", zap.String("value", valueStr), zap.String("remote_addr", remoteAddr))
}
continue
}
s.batcher.In() <- pt
}
}
// serveHTTP handles connections in HTTP format.
func (s *Service) serveHTTP() {
handler := &Handler{
Database: s.Database,
RetentionPolicy: s.RetentionPolicy,
PointsWriter: s.PointsWriter,
Logger: s.Logger,
stats: s.stats,
}
srv := &http.Server{Handler: handler}
srv.Serve(s.httpln)
}
// processBatches continually drains the given batcher and writes the batches to the database.
func (s *Service) processBatches(batcher *tsdb.PointBatcher) {
for {
select {
case <-s.done:
return
case batch := <-batcher.Out():
// Will attempt to create database if not yet created.
if err := s.createInternalStorage(); err != nil {
s.Logger.Info("Required database does not yet exist", logger.Database(s.Database), zap.Error(err))
continue
}
feat: measurement metrics by login (#20687) After turning on authentication and both forms of ingress metrics: "ingress": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"cq","rp":"monitor"},"values":{"pointsWritten":38,"valuesWritten":76}}, "ingress:1": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"database","rp":"monitor"},"values":{"pointsWritten":76,"valuesWritten":152}}, "ingress:2": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"httpd","rp":"monitor"},"values":{"pointsWritten":38,"valuesWritten":874}}, "ingress:3": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"ingress","rp":"monitor"},"values":{"pointsWritten":534,"valuesWritten":1068}}, "ingress:4": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"localStore","rp":"monitor"},"values":{"pointsWritten":38,"valuesWritten":76}}, "ingress:5": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"queryExecutor","rp":"monitor"},"values":{"pointsWritten":38,"valuesWritten":190}}, "ingress:6": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"runtime","rp":"monitor"},"values":{"pointsWritten":38,"valuesWritten":570}}, "ingress:7": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"shard","rp":"monitor"},"values":{"pointsWritten":76,"valuesWritten":836}}, "ingress:8": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"subscriber","rp":"monitor"},"values":{"pointsWritten":38,"valuesWritten":114}}, "ingress:9": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"tsm1_cache","rp":"monitor"},"values":{"pointsWritten":76,"valuesWritten":684}}, "ingress:10": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"tsm1_engine","rp":"monitor"},"values":{"pointsWritten":76,"valuesWritten":2204}}, "ingress:11": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"tsm1_filestore","rp":"monitor"},"values":{"pointsWritten":76,"valuesWritten":152}}, "ingress:12": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"tsm1_wal","rp":"monitor"},"values":{"pointsWritten":76,"valuesWritten":304}}, "ingress:13": {"name":"ingress","tags":{"db":"_internal","login":"_systemuser_monitor","measurement":"write","rp":"monitor"},"values":{"pointsWritten":38,"valuesWritten":342}}, "ingress:14": {"name":"ingress","tags":{"db":"telegraf","login":"admin","measurement":"cpu","rp":"autogen"},"values":{"pointsWritten":1,"valuesWritten":1}}, "ingress:15": {"name":"ingress","tags":{"db":"telegraf","login":"telegraf","measurement":"cpu","rp":"autogen"},"values":{"pointsWritten":1316,"valuesWritten":13160}}, "ingress:16": {"name":"ingress","tags":{"db":"telegraf","login":"telegraf","measurement":"disk","rp":"autogen"},"values":{"pointsWritten":642,"valuesWritten":4494}}, "ingress:17": {"name":"ingress","tags":{"db":"telegraf","login":"telegraf","measurement":"diskio","rp":"autogen"},"values":{"pointsWritten":214,"valuesWritten":2354}}, "ingress:18": {"name":"ingress","tags":{"db":"telegraf","login":"telegraf","measurement":"mem","rp":"autogen"},"values":{"pointsWritten":107,"valuesWritten":963}}, "ingress:19": {"name":"ingress","tags":{"db":"telegraf","login":"telegraf","measurement":"processes","rp":"autogen"},"values":{"pointsWritten":107,"valuesWritten":856}}, "ingress:20": {"name":"ingress","tags":{"db":"telegraf","login":"telegraf","measurement":"swap","rp":"autogen"},"values":{"pointsWritten":214,"valuesWritten":642}}, "ingress:21": {"name":"ingress","tags":{"db":"telegraf","login":"telegraf","measurement":"system","rp":"autogen"},"values":{"pointsWritten":321,"valuesWritten":749}}, Only by login: "ingress": {"name":"ingress","tags":{"login":"_systemuser_monitor"},"values":{"pointsWritten":42,"valuesWritten":354}}, "ingress:1": {"name":"ingress","tags":{"login":"admin"},"values":{"pointsWritten":1,"valuesWritten":1}}, "ingress:2": {"name":"ingress","tags":{"login":"telegraf"},"values":{"pointsWritten":3547,"valuesWritten":28246}}, Notice writes by users 'telegraf', '_systemuser_monitor', and 'admin'.
2021-02-04 16:52:53 +00:00
writeCtx := tsdb.WriteContext{
UserId: tsdb.OpenTsdbUser,
}
if err := s.PointsWriter.WritePointsPrivileged(writeCtx, s.Database, s.RetentionPolicy, models.ConsistencyLevelAny, batch); err == nil {
atomic.AddInt64(&s.stats.BatchesTransmitted, 1)
atomic.AddInt64(&s.stats.PointsTransmitted, int64(len(batch)))
} else {
s.Logger.Info("Failed to write point batch to database",
logger.Database(s.Database), zap.Error(err))
atomic.AddInt64(&s.stats.BatchesTransmitFail, 1)
}
}
}
}