예제 #1
0
func Test_DecodeNameAndTags(t *testing.T) {
	var tests = []struct {
		test      string
		str       string
		name      string
		tags      map[string]string
		position  string
		separator string
		err       string
	}{
		{test: "metric only", str: "cpu", name: "cpu"},
		{test: "metric with single series", str: "cpu.hostname.server01", name: "cpu", tags: map[string]string{"hostname": "server01"}},
		{test: "metric with multiple series", str: "cpu.region.us-west.hostname.server01", name: "cpu", tags: map[string]string{"hostname": "server01", "region": "us-west"}},
		{test: "no metric", tags: make(map[string]string), err: `no name specified for metric. ""`},
		{test: "wrong metric format", str: "foo.cpu", tags: make(map[string]string), err: `received "foo.cpu" which doesn't conform to format of key.value.key.value.name or name`},
	}

	for _, test := range tests {
		t.Logf("testing %q...", test.test)

		p := graphite.NewParser()
		if test.separator != "" {
			p.Separator = test.separator
		}

		name, tags, err := p.DecodeNameAndTags(test.str)
		if errstr(err) != test.err {
			t.Fatalf("err does not match.  expected %v, got %v", test.err, err)
		}
		if name != test.name {
			t.Fatalf("name parse failer.  expected %v, got %v", test.name, name)
		}
		if len(tags) != len(test.tags) {
			t.Fatalf("unexpected number of tags.  expected %d, got %d", len(test.tags), len(tags))
		}
		for k, v := range test.tags {
			if tags[k] != v {
				t.Fatalf("unexpected tag value for tags[%s].  expected %q, got %q", k, v, tags[k])
			}
		}
	}
}
예제 #2
0
func Test_DecodeMetric(t *testing.T) {
	testTime := time.Now()
	epochTime := testTime.UnixNano() / 1000000 // nanos to milliseconds
	strTime := strconv.FormatInt(epochTime, 10)

	var tests = []struct {
		test                string
		line                string
		name                string
		tags                map[string]string
		isInt               bool
		iv                  int64
		fv                  float64
		timestamp           time.Time
		position, separator string
		err                 string
	}{
		{
			test:      "position first by default",
			line:      `cpu.foo.bar 50 ` + strTime,
			name:      "cpu",
			tags:      map[string]string{"foo": "bar"},
			isInt:     true,
			iv:        50,
			timestamp: testTime,
		},
		{
			test:      "position first if unable to determine",
			position:  "foo",
			line:      `cpu.foo.bar 50 ` + strTime,
			name:      "cpu",
			tags:      map[string]string{"foo": "bar"},
			isInt:     true,
			iv:        50,
			timestamp: testTime,
		},
		{
			test:      "position last if specified",
			position:  "last",
			line:      `foo.bar.cpu 50 ` + strTime,
			name:      "cpu",
			tags:      map[string]string{"foo": "bar"},
			isInt:     true,
			iv:        50,
			timestamp: testTime,
		},
		{
			test:      "position first if specified with no series",
			position:  "first",
			line:      `cpu 50 ` + strTime,
			name:      "cpu",
			tags:      map[string]string{},
			isInt:     true,
			iv:        50,
			timestamp: testTime,
		},
		{
			test:      "position last if specified with no series",
			position:  "last",
			line:      `cpu 50 ` + strTime,
			name:      "cpu",
			tags:      map[string]string{},
			isInt:     true,
			iv:        50,
			timestamp: testTime,
		},
		{
			test:      "sepeartor is . by default",
			line:      `cpu.foo.bar 50 ` + strTime,
			name:      "cpu",
			tags:      map[string]string{"foo": "bar"},
			isInt:     true,
			iv:        50,
			timestamp: testTime,
		},
		{
			test:      "sepeartor is . if specified",
			separator: ".",
			line:      `cpu.foo.bar 50 ` + strTime,
			name:      "cpu",
			tags:      map[string]string{"foo": "bar"},
			isInt:     true,
			iv:        50,
			timestamp: testTime,
		},
		{
			test:      "sepeartor is - if specified",
			separator: "-",
			line:      `cpu-foo-bar 50 ` + strTime,
			name:      "cpu",
			tags:      map[string]string{"foo": "bar"},
			isInt:     true,
			iv:        50,
			timestamp: testTime,
		},
		{
			test:      "sepeartor is boo if specified",
			separator: "boo",
			line:      `cpuboofooboobar 50 ` + strTime,
			name:      "cpu",
			tags:      map[string]string{"foo": "bar"},
			isInt:     true,
			iv:        50,
			timestamp: testTime,
		},

		{
			test:      "series + metric + integer value",
			line:      `cpu.foo.bar 50 ` + strTime,
			name:      "cpu",
			tags:      map[string]string{"foo": "bar"},
			isInt:     true,
			iv:        50,
			timestamp: testTime,
		},
		{
			test:      "metric only with float value",
			line:      `cpu 50.554 ` + strTime,
			name:      "cpu",
			isInt:     false,
			fv:        50.554,
			timestamp: testTime,
		},
		{
			test: "missing metric",
			line: `50.554 1419972457825`,
			err:  `received "50.554 1419972457825" which doesn't have three fields`,
		},
		{
			test: "should fail on invalid key",
			line: `foo.cpu 50.554 1419972457825`,
			err:  `received "foo.cpu" which doesn't conform to format of key.value.key.value.name or name`,
		},
		{
			test: "should fail parsing invalid float",
			line: `cpu 50.554z 1419972457825`,
			err:  `strconv.ParseFloat: parsing "50.554z": invalid syntax`,
		},
		{
			test: "should fail parsing invalid int",
			line: `cpu 50z 1419972457825`,
			err:  `strconv.ParseFloat: parsing "50z": invalid syntax`,
		},
		{
			test: "should fail parsing invalid time",
			line: `cpu 50.554 14199724z57825`,
			err:  `strconv.ParseInt: parsing "14199724z57825": invalid syntax`,
		},
	}

	for _, test := range tests {
		t.Logf("testing %q...", test.test)

		p := graphite.NewParser()
		if test.separator != "" {
			p.Separator = test.separator
		}
		p.LastEnabled = (test.position == "last")

		point, err := p.Parse(test.line)
		if errstr(err) != test.err {
			t.Fatalf("err does not match.  expected %v, got %v", test.err, err)
		}
		if err != nil {
			// If we erred out,it was intended and the following tests won't work
			continue
		}
		if point.Name != test.name {
			t.Fatalf("name parse failer.  expected %v, got %v", test.name, point.Name)
		}
		if len(point.Tags) != len(test.tags) {
			t.Fatalf("tags len mismatch.  expected %d, got %d", len(test.tags), len(point.Tags))
		}
		if test.isInt {
			i := point.Fields[point.Name].(int64)
			if i != test.iv {
				t.Fatalf("integerValue value mismatch.  expected %v, got %v", test.iv, point.Fields[point.Name])
			}
		} else {
			f := point.Fields[point.Name].(float64)
			if point.Fields[point.Name] != f {
				t.Fatalf("floatValue value mismatch.  expected %v, got %v", test.fv, f)
			}
		}
		if point.Timestamp.UnixNano()/1000000 != test.timestamp.UnixNano()/1000000 {
			t.Fatalf("timestamp value mismatch.  expected %v, got %v", test.timestamp.UnixNano(), point.Timestamp.UnixNano())
		}
	}
}
예제 #3
0
파일: run.go 프로젝트: pcn/influxdb
// execRun runs the "run" command.
func execRun(args []string) {
	// Parse command flags.
	fs := flag.NewFlagSet("", flag.ExitOnError)
	var (
		configPath = fs.String("config", "", "")
		pidPath    = fs.String("pidfile", "", "")
		hostname   = fs.String("hostname", "", "")
		join       = fs.String("join", "", "")
	)
	fs.Usage = printRunUsage
	fs.Parse(args)

	// Print sweet InfluxDB logo and write the process id to file.
	log.Print(logo)
	log.SetPrefix(`[srvr] `)
	log.SetFlags(log.LstdFlags)
	writePIDFile(*pidPath)

	// Parse the configuration and determine if a broker and/or server exist.
	config := parseConfig(*configPath, *hostname)
	configExists := *configPath != ""
	initializing := !fileExists(config.BrokerDir()) && !fileExists(config.DataDir())

	// Parse join urls from the --join flag.
	var joinURLs []*url.URL
	if *join == "" {
		joinURLs = parseURLs(config.JoinURLs())
	} else {
		joinURLs = parseURLs(*join)
	}

	// Open broker, initialize or join as necessary.
	b := openBroker(config.BrokerDir(), config.BrokerURL(), initializing, joinURLs)

	// Start the broker handler.
	var h *Handler
	if b != nil {
		h = &Handler{brokerHandler: messaging.NewHandler(b)}
		go func() { log.Fatal(http.ListenAndServe(config.BrokerAddr(), h)) }()
		log.Printf("broker listening on %s", config.BrokerAddr())
	}

	// Open server, initialize or join as necessary.
	s := openServer(config.DataDir(), config.DataURL(), b, initializing, configExists, joinURLs)

	// Start the server handler. Attach to broker if listening on the same port.
	if s != nil {
		sh := httpd.NewHandler(s, config.Authentication.Enabled, version)
		if h != nil && config.BrokerAddr() == config.DataAddr() {
			h.serverHandler = sh
		} else {
			go func() { log.Fatal(http.ListenAndServe(config.DataAddr(), sh)) }()
		}
		log.Printf("data node #%d listening on %s", s.ID(), config.DataAddr())

		// Spin up the collectd server
		if config.Collectd.Enabled {
			c := config.Collectd
			cs := collectd.NewServer(s, c.TypesDB)
			cs.Database = c.Database
			err := collectd.ListenAndServe(cs, c.ConnectionString(config.BindAddress))
			if err != nil {
				log.Printf("failed to start collectd Server: %v\n", err.Error())
			}
		}
		// Spin up any Graphite servers
		for _, c := range config.Graphites {
			if !c.Enabled {
				continue
			}

			// Configure Graphite parsing.
			parser := graphite.NewParser()
			parser.Separator = c.NameSeparatorString()
			parser.LastEnabled = c.LastEnabled()

			// Start the relevant server.
			if strings.ToLower(c.Protocol) == "tcp" {
				g := graphite.NewTCPServer(parser, s)
				g.Database = c.Database
				err := g.ListenAndServe(c.ConnectionString(config.BindAddress))
				if err != nil {
					log.Printf("failed to start TCP Graphite Server: %v\n", err.Error())
				}
			} else if strings.ToLower(c.Protocol) == "udp" {
				g := graphite.NewUDPServer(parser, s)
				g.Database = c.Database
				err := g.ListenAndServe(c.ConnectionString(config.BindAddress))
				if err != nil {
					log.Printf("failed to start UDP Graphite Server: %v\n", err.Error())
				}
			} else {
				log.Fatalf("unrecognized Graphite Server prototcol %s", c.Protocol)
			}
		}
	}

	// Wait indefinitely.
	<-(chan struct{})(nil)
}
예제 #4
0
파일: run.go 프로젝트: yinlei/influxdb
func Run(config *Config, join, version string, logWriter *os.File) (*messaging.Broker, *influxdb.Server) {
	log.Printf("influxdb started, version %s, commit %s", version, commit)

	// Parse the configuration and determine if a broker and/or server exist.
	configExists := config != nil
	if config == nil {
		config = NewConfig()
	}

	var initBroker, initServer bool
	if initBroker = !fileExists(config.BrokerDir()); initBroker {
		log.Printf("Broker directory missing. Need to create a broker.")
	}

	if initServer = !fileExists(config.DataDir()); initServer {
		log.Printf("Data directory missing. Need to create data directory.")
	}
	initServer = initServer || initBroker

	// Parse join urls from the --join flag.
	var joinURLs []*url.URL
	if join == "" {
		joinURLs = parseURLs(config.JoinURLs())
	} else {
		joinURLs = parseURLs(join)
	}

	// Open broker, initialize or join as necessary.
	b := openBroker(config.BrokerDir(), config.BrokerURL(), initBroker, joinURLs, logWriter)

	// Configure debug of Raft module.
	b.EnableRaftDebug(config.Logging.RaftTracing)

	// Start the broker handler.
	var h *Handler
	if b != nil {
		h = &Handler{brokerHandler: messaging.NewHandler(b.Broker)}
		// We want to make sure we are spun up before we exit this function, so we manually listen and serve
		listener, err := net.Listen("tcp", config.BrokerAddr())
		if err != nil {
			log.Fatalf("Broker failed to listen on %s. %s ", config.BrokerAddr(), err)
		}
		go func() {
			err := http.Serve(listener, h)
			if err != nil {
				log.Fatalf("Broker failed to server on %s.: %s", config.BrokerAddr(), err)
			}
		}()
		log.Printf("broker listening on %s", config.BrokerAddr())

		// have it occasionally tell a data node in the cluster to run continuous queries
		if config.ContinuousQuery.Disable {
			log.Printf("Not running continuous queries. [continuous_queries].disable is set to true.")
		} else {
			b.RunContinuousQueryLoop()
		}
	}

	// Open server, initialize or join as necessary.
	s := openServer(config, b, initServer, initBroker, configExists, joinURLs, logWriter)
	s.SetAuthenticationEnabled(config.Authentication.Enabled)

	// Enable retention policy enforcement if requested.
	if config.Data.RetentionCheckEnabled {
		interval := time.Duration(config.Data.RetentionCheckPeriod)
		if err := s.StartRetentionPolicyEnforcement(interval); err != nil {
			log.Fatalf("retention policy enforcement failed: %s", err.Error())
		}
		log.Printf("broker enforcing retention policies with check interval of %s", interval)
	}

	// Start shard group pre-create
	interval := config.ShardGroupPreCreateCheckPeriod()
	if err := s.StartShardGroupsPreCreate(interval); err != nil {
		log.Fatalf("shard group pre-create failed: %s", err.Error())
	}
	log.Printf("shard group pre-create with check interval of %s", interval)

	// Start the server handler. Attach to broker if listening on the same port.
	if s != nil {
		sh := httpd.NewHandler(s, config.Authentication.Enabled, version)
		sh.SetLogOutput(logWriter)
		sh.WriteTrace = config.Logging.WriteTracing

		if h != nil && config.BrokerAddr() == config.DataAddr() {
			h.serverHandler = sh
		} else {
			// We want to make sure we are spun up before we exit this function, so we manually listen and serve
			listener, err := net.Listen("tcp", config.DataAddr())
			if err != nil {
				log.Fatal(err)
			}
			go func() { log.Fatal(http.Serve(listener, sh)) }()
		}
		log.Printf("data node #%d listening on %s", s.ID(), config.DataAddr())

		// Start the admin interface on the default port
		if config.Admin.Enabled {
			port := fmt.Sprintf(":%d", config.Admin.Port)
			log.Printf("starting admin server on %s", port)
			a := admin.NewServer(port)
			go a.ListenAndServe()
		}

		// Spin up the collectd server
		if config.Collectd.Enabled {
			c := config.Collectd
			cs := collectd.NewServer(s, c.TypesDB)
			cs.Database = c.Database
			err := collectd.ListenAndServe(cs, c.ConnectionString(config.BindAddress))
			if err != nil {
				log.Printf("failed to start collectd Server: %v\n", err.Error())
			}
		}

		// Start the server bound to a UDP listener
		if config.UDP.Enabled {
			log.Printf("Starting UDP listener on %s", config.DataAddrUDP())
			u := udp.NewUDPServer(s)
			if err := u.ListenAndServe(config.DataAddrUDP()); err != nil {
				log.Printf("Failed to start UDP listener on %s: %s", config.DataAddrUDP(), err)
			}

		}

		// Spin up any Graphite servers
		for _, c := range config.Graphites {
			if !c.Enabled {
				continue
			}

			// Configure Graphite parsing.
			parser := graphite.NewParser()
			parser.Separator = c.NameSeparatorString()
			parser.LastEnabled = c.LastEnabled()

			if err := s.CreateDatabaseIfNotExists(c.DatabaseString()); err != nil {
				log.Fatalf("failed to create database for %s Graphite server: %s", c.Protocol, err.Error())
			}

			// Spin up the server.
			var g graphite.Server
			g, err := graphite.NewServer(c.Protocol, parser, s, c.DatabaseString())
			if err != nil {
				log.Fatalf("failed to initialize %s Graphite server: %s", c.Protocol, err.Error())
			}
			g.SetLogOutput(logWriter)

			err = g.ListenAndServe(c.ConnectionString(config.BindAddress))
			if err != nil {
				log.Fatalf("failed to start %s Graphite server: %s", c.Protocol, err.Error())
			}
		}
	}

	// unless disabled, start the loop to report anonymous usage stats every 24h
	if !config.ReportingDisabled {
		// Make sure we have a config object b4 we try to use it.
		if configObj := b.Broker.Log().Config(); configObj != nil {
			clusterID := configObj.ClusterID
			go s.StartReportingLoop(version, clusterID)
		}
	}

	return b.Broker, s
}