// Test that a registered stats client results in the correct SHOW STATS output. func Test_RegisterStats(t *testing.T) { monitor := openMonitor(t) executor := &StatementExecutor{Monitor: monitor} // Register stats without tags. statMap := influxdb.NewStatistics("foo", "foo", nil) statMap.Add("bar", 1) statMap.AddFloat("qux", 2.4) json := executeShowStatsJSON(t, executor) if !strings.Contains(json, `"columns":["bar","qux"],"values":[[1,2.4]]`) || !strings.Contains(json, `"name":"foo"`) { t.Fatalf("SHOW STATS response incorrect, got: %s\n", json) } // Register a client with tags. statMap = influxdb.NewStatistics("bar", "baz", map[string]string{"proto": "tcp"}) statMap.Add("bar", 1) statMap.AddFloat("qux", 2.4) json = executeShowStatsJSON(t, executor) if !strings.Contains(json, `"columns":["bar","qux"],"values":[[1,2.4]]`) || !strings.Contains(json, `"name":"baz"`) || !strings.Contains(json, `"proto":"tcp"`) { t.Fatalf("SHOW STATS response incorrect, got: %s\n", json) } }
func NewPartition(id uint8, path string, segmentSize int64, sizeThreshold uint64, readySeriesSize int, flushColdInterval time.Duration, index IndexWriter) (*Partition, error) { // Configure expvar monitoring. It's OK to do this even if the service fails to open and // should be done before any data could arrive for the service. key := strings.Join([]string{"partition", strconv.Itoa(int(id)), path}, ":") tags := map[string]string{"partition": path, "id": strconv.Itoa(int(id))} p := &Partition{ id: id, path: path, maxSegmentSize: segmentSize, sizeThreshold: sizeThreshold, lastWriteTime: time.Now(), cache: make(map[string]*cacheEntry), readySeriesSize: readySeriesSize, index: index, flushColdInterval: flushColdInterval, statMap: influxdb.NewStatistics(key, "partition", tags), } p.os.OpenCompactionFile = os.OpenFile p.os.OpenSegmentFile = os.OpenFile p.os.Rename = os.Rename p.buf = make([]byte, partitionBufLen) p.snappybuf = make([]byte, snappy.MaxEncodedLen(partitionBufLen)) return p, nil }
func (s *Service) Open() (err error) { // Configure expvar monitoring. It's OK to do this even if the service fails to open and // should be done before any data could arrive for the service. key := strings.Join([]string{"udp", s.config.BindAddress}, ":") tags := map[string]string{"bind": s.config.BindAddress} s.statMap = influxdb.NewStatistics(key, "udp", tags) if s.config.BindAddress == "" { return errors.New("bind address has to be specified in config") } if s.config.Database == "" { return errors.New("database has to be specified in config") } s.addr, err = net.ResolveUDPAddr("udp", s.config.BindAddress) if err != nil { s.Logger.Printf("Failed to resolve UDP address %s: %s", s.config.BindAddress, err) return err } s.conn, err = net.ListenUDP("udp", s.addr) if err != nil { s.Logger.Printf("Failed to set up UDP listener at address %s: %s", s.addr, err) return err } s.Logger.Printf("Started listening on UDP: %s", s.config.BindAddress) s.wg.Add(2) go s.serve() go s.writePoints() return nil }
// NewService returns a new instance of Service. func NewService(c Config) *Service { return &Service{ closing: make(chan struct{}), Logger: log.New(os.Stderr, "[cluster] ", log.LstdFlags), statMap: influxdb.NewStatistics("cluster", "cluster", nil), } }
// NewEngine returns a new instance of Engine. func NewEngine(path string, walPath string, opt tsdb.EngineOptions) tsdb.Engine { // Configure statistics collection. key := fmt.Sprintf("engine:%s:%s", opt.EngineVersion, path) tags := map[string]string{"path": path, "version": opt.EngineVersion} statMap := influxdb.NewStatistics(key, "engine", tags) // create the writer with a directory of the same name as the shard, but with the wal extension w := wal.NewLog(walPath) w.ReadySeriesSize = opt.Config.WALReadySeriesSize w.FlushColdInterval = time.Duration(opt.Config.WALFlushColdInterval) w.MaxSeriesSize = opt.Config.WALMaxSeriesSize w.CompactionThreshold = opt.Config.WALCompactionThreshold w.PartitionSizeThreshold = opt.Config.WALPartitionSizeThreshold w.ReadySeriesSize = opt.Config.WALReadySeriesSize w.LoggingEnabled = opt.Config.WALLoggingEnabled e := &Engine{ path: path, statMap: statMap, BlockSize: DefaultBlockSize, WAL: w, } w.Index = e return e }
// Open starts the service func (s *Service) Open() error { s.Logger.Println("Starting OpenTSDB service") // Configure expvar monitoring. It's OK to do this even if the service fails to open and // should be done before any data could arrive for the service. key := strings.Join([]string{"opentsdb", s.BindAddress}, ":") tags := map[string]string{"bind": s.BindAddress} s.statMap = influxdb.NewStatistics(key, "opentsdb", tags) if err := s.MetaStore.WaitForLeader(leaderWaitTimeout); err != nil { s.Logger.Printf("Failed to detect a cluster leader: %s", err.Error()) return err } if _, err := s.MetaStore.CreateDatabaseIfNotExists(s.Database); err != nil { s.Logger.Printf("Failed to ensure target database %s exists: %s", s.Database, err.Error()) return err } s.batcher = tsdb.NewPointBatcher(s.batchSize, s.batchPending, s.batchTimeout) s.batcher.Start() // Start processing batches. s.wg.Add(1) go s.processBatches(s.batcher) // Open listener. if s.tls { cert, err := tls.LoadX509KeyPair(s.cert, s.cert) if err != nil { return err } listener, err := tls.Listen("tcp", s.BindAddress, &tls.Config{ Certificates: []tls.Certificate{cert}, }) if err != nil { return err } s.Logger.Println("Listening on TLS:", listener.Addr().String()) s.ln = listener } else { listener, err := net.Listen("tcp", s.BindAddress) if err != nil { return err } s.Logger.Println("Listening on:", listener.Addr().String()) s.ln = listener } s.httpln = newChanListener(s.ln.Addr()) // Begin listening for connections. s.wg.Add(2) go s.serveHTTP() go s.serve() return nil }
// NewPointsWriter returns a new instance of PointsWriter for a node. func NewPointsWriter() *PointsWriter { return &PointsWriter{ closing: make(chan struct{}), WriteTimeout: DefaultWriteTimeout, Logger: log.New(os.Stderr, "[write] ", log.LstdFlags), statMap: influxdb.NewStatistics("write", "write", nil), } }
func NewService(c Config) *Service { return &Service{ subs: make(map[subEntry]PointsWriter), NewPointsWriter: newPointsWriter, Logger: log.New(os.Stderr, "[subscriber] ", log.LstdFlags), statMap: influxdb.NewStatistics("subscriber", "subscriber", nil), points: make(chan *cluster.WritePointsRequest), } }
func (p *Processor) updateShardStats(shardID uint64, stat string, inc int64) { m, ok := p.shardStatMaps[shardID] if !ok { key := fmt.Sprintf("hh_processor:shard:%d", shardID) tags := map[string]string{"shardID": strconv.FormatUint(shardID, 10)} p.shardStatMaps[shardID] = influxdb.NewStatistics(key, "hh_processor", tags) m = p.shardStatMaps[shardID] } m.Add(stat, inc) }
// NewHandler returns a new instance of Handler. func NewHandler(requireAuthentication bool) *Handler { statMap := influxdb.NewStatistics("httpd", "httpd", nil) h := &Handler{ Handler: httpd.NewHandler(requireAuthentication, true, false, statMap), } h.Handler.MetaStore = &h.MetaStore h.Handler.QueryExecutor = &h.QueryExecutor h.Handler.Version = "0.0.0" return h }
// NewService returns a new instance of Service. func NewService(c Config) *Service { s := &Service{ Config: &c, RunInterval: time.Second, RunCh: make(chan *RunRequest), loggingEnabled: c.LogEnabled, statMap: influxdb.NewStatistics("cq", "cq", nil), Logger: log.New(os.Stderr, "[continuous_querier] ", log.LstdFlags), lastRuns: map[string]time.Time{}, } return s }
// NewService returns a new instance of Service. func NewService(c Config, w shardWriter, m metaStore) *Service { key := strings.Join([]string{"hh", c.Dir}, ":") tags := map[string]string{"path": c.Dir} return &Service{ cfg: c, closing: make(chan struct{}), processors: make(map[uint64]*NodeProcessor), statMap: influxdb.NewStatistics(key, "hh", tags), Logger: log.New(os.Stderr, "[handoff] ", log.LstdFlags), shardWriter: w, metastore: m, } }
// Open starts the Graphite input processing data. func (s *Service) Open() error { s.logger.Printf("Starting graphite service, batch size %d, batch timeout %s", s.batchSize, s.batchTimeout) // Configure expvar monitoring. It's OK to do this even if the service fails to open and // should be done before any data could arrive for the service. key := strings.Join([]string{"graphite", s.protocol, s.bindAddress}, ":") tags := map[string]string{"proto": s.protocol, "bind": s.bindAddress} s.statMap = influxdb.NewStatistics(key, "graphite", tags) // One Graphite service hooks up diagnostics for all Graphite functionality. monitorOnce.Do(func() { if s.Monitor == nil { s.logger.Println("no monitor service available, no monitoring will be performed") return } s.Monitor.RegisterDiagnosticsClient("graphite", monitor.DiagsClientFunc(handleDiagnostics)) }) if err := s.MetaStore.WaitForLeader(leaderWaitTimeout); err != nil { s.logger.Printf("Failed to detect a cluster leader: %s", err.Error()) return err } if _, err := s.MetaStore.CreateDatabaseIfNotExists(s.database); err != nil { s.logger.Printf("Failed to ensure target database %s exists: %s", s.database, err.Error()) return err } s.batcher = tsdb.NewPointBatcher(s.batchSize, s.batchTimeout) s.batcher.Start() // Start processing batches. s.wg.Add(1) go s.processBatches(s.batcher) var err error if strings.ToLower(s.protocol) == "tcp" { s.addr, err = s.openTCPServer() } else if strings.ToLower(s.protocol) == "udp" { s.addr, err = s.openUDPServer() } else { return fmt.Errorf("unrecognized Graphite input protocol %s", s.protocol) } if err != nil { return err } s.logger.Printf("Listening on %s: %s", strings.ToUpper(s.protocol), s.addr.String()) return nil }
func (s *Service) Open() (err error) { // Configure expvar monitoring. It's OK to do this even if the service fails to open and // should be done before any data could arrive for the service. key := strings.Join([]string{"udp", s.config.BindAddress}, ":") tags := map[string]string{"bind": s.config.BindAddress} s.statMap = influxdb.NewStatistics(key, "udp", tags) if s.config.BindAddress == "" { return errors.New("bind address has to be specified in config") } if s.config.Database == "" { return errors.New("database has to be specified in config") } s.addr, err = net.ResolveUDPAddr("udp", s.config.BindAddress) if err != nil { s.Logger.Printf("E! Failed to resolve UDP address %s: %s", s.config.BindAddress, err) return err } s.conn, err = net.ListenUDP("udp", s.addr) if err != nil { s.Logger.Printf("E! Failed to set up UDP listener at address %s: %s", s.addr, err) return err } if s.config.ReadBuffer != 0 { err = s.conn.SetReadBuffer(s.config.ReadBuffer) if err != nil { s.Logger.Printf("E! Failed to set UDP read buffer to %d: %s", s.config.ReadBuffer, err) return err } } //save fully resolved and bound addr. Useful if port given was '0'. s.addr = s.conn.LocalAddr().(*net.UDPAddr) s.Logger.Printf("I! Started listening on UDP: %s", s.addr.String()) // Start reading and processing packets s.packets = make(chan []byte, s.config.Buffer) s.wg.Add(1) go s.serve() s.wg.Add(1) go s.processPackets() return nil }
// NewShard returns a new initialized Shard. walPath doesn't apply to the b1 type index func NewShard(id uint64, index *DatabaseIndex, path string, walPath string, options EngineOptions) *Shard { // Configure statistics collection. key := fmt.Sprintf("shard:%s:%d", path, id) tags := map[string]string{"path": path, "id": fmt.Sprintf("%d", id), "engine": options.EngineVersion} statMap := influxdb.NewStatistics(key, "shard", tags) return &Shard{ index: index, path: path, walPath: walPath, id: id, options: options, measurementFields: make(map[string]*MeasurementFields), statMap: statMap, LogOutput: os.Stderr, } }
// NewNodeProcessor returns a new NodeProcessor for the given node, using dir for // the hinted-handoff data. func NewNodeProcessor(nodeID uint64, dir string, w shardWriter, m metaStore) *NodeProcessor { key := strings.Join([]string{"hh_processor", dir}, ":") tags := map[string]string{"node": fmt.Sprintf("%d", nodeID), "path": dir} return &NodeProcessor{ PurgeInterval: DefaultPurgeInterval, RetryInterval: DefaultRetryInterval, RetryMaxInterval: DefaultRetryMaxInterval, MaxSize: DefaultMaxSize, MaxAge: DefaultMaxAge, nodeID: nodeID, dir: dir, writer: w, meta: m, statMap: influxdb.NewStatistics(key, "hh_processor", tags), Logger: log.New(os.Stderr, "[handoff] ", log.LstdFlags), } }
// Open starts the Graphite input processing data. func (s *Service) Open() error { s.mu.Lock() defer s.mu.Unlock() s.logger.Printf("Starting graphite service, batch size %d, batch timeout %s", s.batchSize, s.batchTimeout) // Configure expvar monitoring. It's OK to do this even if the service fails to open and // should be done before any data could arrive for the service. key := strings.Join([]string{"graphite", s.protocol, s.bindAddress}, ":") tags := map[string]string{"proto": s.protocol, "bind": s.bindAddress} s.statMap = influxdb.NewStatistics(key, "graphite", tags) // Register diagnostics if a Monitor service is available. if s.Monitor != nil { s.Monitor.RegisterDiagnosticsClient(key, s) } if _, err := s.MetaClient.CreateDatabase(s.database); err != nil { s.logger.Printf("Failed to ensure target database %s exists: %s", s.database, err.Error()) return err } s.batcher = tsdb.NewPointBatcher(s.batchSize, s.batchPending, s.batchTimeout) s.batcher.Start() // Start processing batches. s.wg.Add(1) go s.processBatches(s.batcher) var err error if strings.ToLower(s.protocol) == "tcp" { s.addr, err = s.openTCPServer() } else if strings.ToLower(s.protocol) == "udp" { s.addr, err = s.openUDPServer() } else { return fmt.Errorf("unrecognized Graphite input protocol %s", s.protocol) } if err != nil { return err } s.logger.Printf("Listening on %s: %s", strings.ToUpper(s.protocol), s.addr.String()) return nil }
// NewService returns a new instance of Service. func NewService(c Config, w shardWriter) *Service { key := strings.Join([]string{"hh", c.Dir}, ":") tags := map[string]string{"path": c.Dir} s := &Service{ cfg: c, statMap: influxdb.NewStatistics(key, "hh", tags), Logger: log.New(os.Stderr, "[handoff] ", log.LstdFlags), } processor, err := NewProcessor(c.Dir, w, ProcessorOptions{ MaxSize: c.MaxSize, RetryRateLimit: c.RetryRateLimit, }) if err != nil { s.Logger.Fatalf("Failed to start hinted handoff processor: %v", err) } processor.Logger = s.Logger s.HintedHandoff = processor return s }
// addQueue adds a hinted-handoff queue for the given node. This function is not thread-safe // and the caller must ensure this function is not called concurrently. func (p *Processor) addQueue(nodeID uint64) (*queue, error) { path := filepath.Join(p.dir, strconv.FormatUint(nodeID, 10)) if err := os.MkdirAll(path, 0700); err != nil { return nil, err } queue, err := newQueue(path, p.maxSize) if err != nil { return nil, err } if err := queue.Open(); err != nil { return nil, err } p.queues[nodeID] = queue // Create node stats for this queue. key := fmt.Sprintf("hh_processor:node:%d", nodeID) tags := map[string]string{"nodeID": strconv.FormatUint(nodeID, 10)} p.nodeStatMaps[nodeID] = influxdb.NewStatistics(key, "hh_processor", tags) return queue, nil }
func (s *Service) createSubscription(se subEntry, mode string, destinations []string) (PointsWriter, error) { var bm BalanceMode switch mode { case "ALL": bm = ALL case "ANY": bm = ANY default: return nil, fmt.Errorf("unknown balance mode %q", mode) } writers := make([]PointsWriter, len(destinations)) statMaps := make([]*expvar.Map, len(writers)) for i, dest := range destinations { u, err := url.Parse(dest) if err != nil { return nil, err } w, err := s.NewPointsWriter(*u) if err != nil { return nil, err } writers[i] = w tags := map[string]string{ "database": se.db, "retention_policy": se.rp, "name": se.name, "mode": mode, "destination": dest, } key := strings.Join([]string{"subscriber", se.db, se.rp, se.name, dest}, ":") statMaps[i] = influxdb.NewStatistics(key, "subscriber", tags) } s.Logger.Println("created new subscription for", se.db, se.rp) return &balancewriter{ bm: bm, writers: writers, statMaps: statMaps, }, nil }
// NewLog creates a new Log object with certain default values. func NewLog(path string) *Log { // Configure expvar monitoring. It's OK to do this even if the service fails to open and // should be done before any data could arrive for the service. key := strings.Join([]string{"wal", path}, ":") tags := map[string]string{"path": path} return &Log{ path: path, flush: make(chan int, 1), // these options should be overriden by any options in the config LogOutput: os.Stderr, FlushColdInterval: tsdb.DefaultFlushColdInterval, SegmentSize: DefaultSegmentSize, MaxSeriesSize: tsdb.DefaultMaxSeriesSize, CompactionThreshold: tsdb.DefaultCompactionThreshold, PartitionSizeThreshold: tsdb.DefaultPartitionSizeThreshold, ReadySeriesSize: tsdb.DefaultReadySeriesSize, flushCheckInterval: defaultFlushCheckInterval, logger: log.New(os.Stderr, "[wal] ", log.LstdFlags), statMap: influxdb.NewStatistics(key, "wal", tags), } }
// NewService returns a new instance of Service. func NewService(c Config) *Service { // Configure expvar monitoring. It's OK to do this even if the service fails to open and // should be done before any data could arrive for the service. key := strings.Join([]string{"httpd", c.BindAddress}, ":") tags := map[string]string{"bind": c.BindAddress} statMap := influxdb.NewStatistics(key, "httpd", tags) s := &Service{ addr: c.BindAddress, https: c.HTTPSEnabled, cert: c.HTTPSCertificate, err: make(chan error), Handler: NewHandler( c.AuthEnabled, c.LogEnabled, c.WriteTracing, statMap, ), Logger: log.New(os.Stderr, "[httpd] ", log.LstdFlags), } s.Handler.Logger = s.Logger return s }
// Open starts the service. func (s *Service) Open() error { s.Logger.Printf("Starting collectd service") // Configure expvar monitoring. It's OK to do this even if the service fails to open and // should be done before any data could arrive for the service. key := strings.Join([]string{"collectd", s.Config.BindAddress}, ":") tags := map[string]string{"bind": s.Config.BindAddress} s.statMap = influxdb.NewStatistics(key, "collectd", tags) if s.Config.BindAddress == "" { return fmt.Errorf("bind address is blank") } else if s.Config.Database == "" { return fmt.Errorf("database name is blank") } else if s.PointsWriter == nil { return fmt.Errorf("PointsWriter is nil") } if err := s.MetaStore.WaitForLeader(leaderWaitTimeout); err != nil { s.Logger.Printf("Failed to detect a cluster leader: %s", err.Error()) return err } if _, err := s.MetaStore.CreateDatabaseIfNotExists(s.Config.Database); err != nil { s.Logger.Printf("Failed to ensure target database %s exists: %s", s.Config.Database, err.Error()) return err } if s.typesdb == nil { // Open collectd types. typesdb, err := gollectd.TypesDBFile(s.Config.TypesDB) if err != nil { return fmt.Errorf("Open(): %s", err) } s.typesdb = typesdb } // Resolve our address. addr, err := net.ResolveUDPAddr("udp", s.Config.BindAddress) if err != nil { return fmt.Errorf("unable to resolve UDP address: %s", err) } s.addr = addr // Start listening ln, err := net.ListenUDP("udp", addr) if err != nil { return fmt.Errorf("unable to listen on UDP: %s", err) } s.ln = ln s.Logger.Println("Listening on UDP: ", ln.LocalAddr().String()) // Start the points batcher. s.batcher = tsdb.NewPointBatcher(s.Config.BatchSize, s.Config.BatchPending, time.Duration(s.Config.BatchDuration)) s.batcher.Start() // Create channel and wait group for signalling goroutines to stop. s.stop = make(chan struct{}) s.wg.Add(2) // Start goroutines that process collectd packets. go s.serve() go s.writePoints() return nil }