Example #1
0
func main() {
	if len(os.Args) != 2 {
		fmt.Println("Usage\ntail-f filename\n")
		os.Exit(1)
	}
	filename, err := hydra.Rel2Abs(os.Args[1])
	if err != nil {
		panic(err)
	}
	watcher, err := hydra.NewWatcher()
	if err != nil {
		panic(err)
	}
	messageCh, monitorCh := hydra.NewChannel()
	config := &hydra.ConfigLogfile{
		Tag:       "dummy",
		File:      filename,
		FieldName: "message",
	}
	inTail, err := hydra.NewInTail(config, watcher, messageCh, monitorCh)
	go watcher.Run()
	go inTail.Run()
	done := make(chan interface{})
	for {
		recordSet := <-messageCh
		for _, record := range recordSet.Records {
			b, ok := record.GetData("message")
			if ok {
				fmt.Println(string(b.([]byte)))
			}
		}
	}
	<-done
}
func TestForwardFailOver(t *testing.T) {
	log.Println("---- TestForwardFailOver ----")
	counter := int64(0)

	primaryAddr, primaryCloser := runMockServer(t, "", &counter)
	close(primaryCloser) // shutdown primary server immediately
	sleep(1)
	primaryConfigServer := newConfigServer(primaryAddr)
	secondaryAddr, secondaryCloser := runMockServer(t, "", &counter)
	secondaryConfigServer := newConfigServer(secondaryAddr)
	configServers := []*hydra.ConfigServer{
		primaryConfigServer,
		secondaryConfigServer,
	}
	msgCh, monCh := hydra.NewChannel()
	outForward, err := hydra.NewOutForward(configServers, msgCh, monCh)
	if err != nil {
		t.Error(err)
		return
	}
	go outForward.Run()

	sleep(1)

	recordSet := prepareRecordSet()
	msgCh <- recordSet
	sleep(1)

	if n := atomic.LoadInt64(&counter); n != int64(len(TestMessageLines)) {
		t.Error("insufficient recieved messages. sent", len(TestMessageLines), "recieved", n)
	}
	close(msgCh)
	close(secondaryCloser)
	sleep(1)
}
Example #3
0
func TestMonitorServer(t *testing.T) {
	config := &hydra.Config{
		Monitor: &hydra.ConfigMonitor{
			Host: "localhost",
			Port: 0,
		},
	}
	_, ch := hydra.NewChannel()
	monitor, _ := hydra.NewMonitor(config, ch)
	go monitor.Run()

	expectedMessages := make(map[string]int64)
	expectedBytes := make(map[string]int64)
	tags := []string{"foo", "bar", "dummy.test"}
	for _, tag := range tags {
		for i := 1; i <= 100; i++ {
			m := rand.Int63n(10)
			b := rand.Int63n(2560)
			ch <- &hydra.SentStat{
				Tag:      tag,
				Messages: m,
				Bytes:    b,
			}
			expectedMessages[tag] += m
			expectedBytes[tag] += b
		}
	}
	sleep(1)

	resp, err := http.Get(fmt.Sprintf("http://%s/", monitor.Addr))
	if err != nil {
		t.Error(err)
	}
	defer resp.Body.Close()
	if ct := resp.Header.Get("Content-Type"); ct != "application/json" {
		t.Error("invalid content-type", ct)
	}
	body, _ := ioutil.ReadAll(resp.Body)
	js := bytes.NewReader(body)
	for tag, n := range expectedMessages {
		js.Seek(int64(0), os.SEEK_SET)
		var got int64
		scan.ScanJSON(js, "/sent/"+tag+"/messages", &got)
		if got != n {
			t.Errorf("/sent/%s/messages got %d expected %d", tag, got, n)
		}
	}
	for tag, n := range expectedBytes {
		js.Seek(int64(0), os.SEEK_SET)
		var got int64
		scan.ScanJSON(js, "/sent/"+tag+"/bytes", &got)
		if got != n {
			t.Errorf("/sent/%s/bytes got %d expected %d", tag, got, n)
		}
	}

	log.Println(string(body))
}
Example #4
0
func run(config *hydra.Config) {
	messageCh, monitorCh := hydra.NewChannel()

	if config.ReadBufferSize > 0 {
		hydra.ReadBufferSize = config.ReadBufferSize
		log.Println("[info] set ReadBufferSize", hydra.ReadBufferSize)
	}

	// start monitor server
	monitor, err := hydra.NewMonitor(config, monitorCh)
	if err != nil {
		log.Println("[error] Couldn't start monitor server.", err)
	} else {
		go monitor.Run()
	}

	// start out_forward
	outForward, err := hydra.NewOutForward(config.Servers, messageCh, monitorCh)
	if err != nil {
		log.Println("[error]", err)
	} else {
		outForward.RoundRobin = config.ServerRoundRobin
		if outForward.RoundRobin {
			log.Println("[info] ServerRoundRobin enabled")
		}
		go outForward.Run()
	}

	// start watcher && in_tail
	if len(config.Logs) > 0 {
		watcher, err := hydra.NewWatcher()
		if err != nil {
			log.Println("[error]", err)
		}
		for _, configLogfile := range config.Logs {
			tail, err := hydra.NewInTail(configLogfile, watcher, messageCh, monitorCh)
			if err != nil {
				log.Println("[error]", err)
			} else {
				go tail.Run()
			}
		}
		go watcher.Run()
	}

	// start in_forward
	if config.Receiver != nil {
		if runtime.GOMAXPROCS(0) < 2 {
			log.Println("[warning] When using Receiver, recommend to set GOMAXPROCS >= 2.")
		}
		inForward, err := hydra.NewInForward(config.Receiver, messageCh, monitorCh)
		if err != nil {
			log.Println("[error]", err)
		} else {
			go inForward.Run()
		}
	}
}
func TestTrailLTSV(t *testing.T) {
	tmpdir, _ := ioutil.TempDir(os.TempDir(), "hydra-test")
	file, _ := ioutil.TempFile(tmpdir, "logfile.")
	defer os.RemoveAll(tmpdir)

	configLogfile := &hydra.ConfigLogfile{
		Tag:        "test",
		File:       file.Name(),
		Format:     hydra.LTSV,
		ConvertMap: hydra.NewConvertMap("foo:integer"),
		FieldName:  "message",
		TimeParse:  true,
		TimeFormat: hydra.DefaultTimeFormat,
		TimeKey:    hydra.DefaultTimeKey,
	}
	msgCh, monCh := hydra.NewChannel()
	watcher, err := hydra.NewWatcher()
	if err != nil {
		t.Error(err)
	}
	inTail, err := hydra.NewInTail(configLogfile, watcher, msgCh, monCh)
	if err != nil {
		t.Error(err)
	}
	go inTail.Run()
	go watcher.Run()
	go func() {
		time.Sleep(1 * time.Second)
		fileWriter(t, file, LTSVLogs)
	}()

	i := 0
	for i < len(LTSVLogs) {
		recordSet := <-msgCh
		if recordSet.Tag != "test" {
			t.Errorf("got %v\nwant %v", recordSet.Tag, "test")
		}
		for _, _record := range recordSet.Records {
			record := _record.(*fluent.TinyFluentRecord)
			if foo, _ := record.GetData("foo"); foo != LTSVParsed[i]["foo"] {
				t.Errorf("unexpected record %v", record)
			}
			if bar, _ := record.GetData("bar"); bar != LTSVParsed[i]["bar"] {
				t.Errorf("unexpected record %v", record)
			}
			if ts, ok := LTSVParsed[i]["_time"]; ok {
				if ts.(time.Time).Unix() != record.Timestamp {
					t.Errorf("expected timestamp %s got %s", ts, record.Timestamp)
				}
			}
			i++
		}
	}
}
func TestInForward(t *testing.T) {
	config := &hydra.ConfigReceiver{
		Host:              "127.0.0.1",
		Port:              0,
		MaxBufferMessages: 1000,
	}
	messageCh, monitorCh := hydra.NewChannel()
	inForward, err := hydra.NewInForward(config, messageCh, monitorCh)
	if err != nil {
		t.Error(err)
	}
	go inForward.Run()

	host, _port, _ := net.SplitHostPort(inForward.Addr.String())
	port, _ := strconv.Atoi(_port)
	logger, err := client.New(client.Config{
		FluentHost: host,
		FluentPort: port,
	})
	if err != nil {
		t.Error(err)
	}
	log.Println("logger", logger)
	defer logger.Close()

	tag := "myapp.access"
	for i := 0; i < 10; i++ {
		var data = map[string]interface{}{
			"foo":  "bar",
			"hoge": "hoge",
		}
		logger.Post(tag, data)
	}
	n := 0
RECEIVE:
	for {
		select {
		case <-messageCh:
			n++
			continue
		case <-time.After(1 * time.Second):
			break RECEIVE
		}
	}
	if n != 10 {
		t.Errorf("arrived messages %d expected %d", n, 10)
	}
}
func TestForwardReconnect(t *testing.T) {
	log.Println("---- TestForwardReconnect ----")
	counter := int64(0)

	addr, mockCloser := runMockServer(t, "", &counter)
	configServer := newConfigServer(addr)
	msgCh, monCh := hydra.NewChannel()
	outForward, err := hydra.NewOutForward([]*hydra.ConfigServer{configServer}, msgCh, monCh)
	if err != nil {
		t.Error(err)
	}
	go outForward.Run()

	recordSet := prepareRecordSet()
	msgCh <- recordSet
	sleep(1)

	t.Log("notify shutdown mockServer")
	close(mockCloser)
	t.Log("waiting for shutdown complated 3 sec")
	sleep(3)

	t.Log("restarting mock server on same addr", addr)
	_, mockCloser = runMockServer(t, addr, &counter)
	sleep(1)
	msgCh <- recordSet // Afeter unexpected server closing, first Write() will be succeeded and lost...
	sleep(1)
	msgCh <- recordSet
	t.Log("waiting for reconnect & resend completed 5 sec")
	sleep(3)

	if n := atomic.LoadInt64(&counter); n != int64(len(TestMessageLines)*2) {
		t.Error("insufficient recieved messages. sent", len(TestMessageLines)*2, "recieved", n)
	}
	close(mockCloser)
	close(msgCh)
	sleep(1)
}
Example #8
0
func TestTrail(t *testing.T) {
	hydra.ReadBufferSize = ReadBufferSizeForTest

	tmpdir, _ := ioutil.TempDir(os.TempDir(), "hydra-test")
	file, _ := ioutil.TempFile(tmpdir, "logfile.")
	defer os.RemoveAll(tmpdir)

	go fileWriter(t, file, Logs)

	configLogfile := &hydra.ConfigLogfile{
		Tag:       "test",
		File:      file.Name(),
		FieldName: "message",
	}
	msgCh, monCh := hydra.NewChannel()
	watcher, err := hydra.NewWatcher()
	if err != nil {
		t.Error(err)
	}
	inTail, err := hydra.NewInTail(configLogfile, watcher, msgCh, monCh)
	if err != nil {
		t.Error(err)
	}
	go inTail.Run()
	go watcher.Run()

	resultCh := make(chan string)
	go reciever(t, msgCh, "test", resultCh)

	recieved := <-resultCh
	sent := strings.Join(Logs, "")
	if recieved != sent {
		t.Errorf("sent logs and recieved logs is different. sent %d bytes, recieved %d bytes", len(sent), len(recieved))
		fmt.Print(sent)
		fmt.Print(recieved)
	}
}
func TestForwardSingle(t *testing.T) {
	log.Println("---- TestForwardSingle ----")
	counter := int64(0)

	addr, mockCloser := runMockServer(t, "", &counter)
	configServer := newConfigServer(addr)
	msgCh, monCh := hydra.NewChannel()
	outForward, err := hydra.NewOutForward([]*hydra.ConfigServer{configServer}, msgCh, monCh)
	if err != nil {
		t.Error(err)
	}
	go outForward.Run()

	recordSet := prepareRecordSet()
	msgCh <- recordSet
	sleep(3)

	if n := atomic.LoadInt64(&counter); n != int64(len(TestMessageLines)) {
		t.Error("insufficient recieved messages. sent", len(TestMessageLines), "recieved", n)
	}
	close(msgCh)
	close(mockCloser)
	sleep(1)
}