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, } c := hydra.NewContext() outForward, err := hydra.NewOutForward(configServers) if err != nil { t.Error(err) return } c.RunProcess(outForward) sleep(1) recordSet := prepareRecordSet() c.MessageCh <- recordSet sleep(1) if n := atomic.LoadInt64(&counter); n != int64(len(TestMessageLines)) { t.Error("insufficient recieved messages. sent", len(TestMessageLines), "recieved", n) } c.Shutdown() close(secondaryCloser) sleep(1) }
func TestMonitorServer(t *testing.T) { config := &hydra.Config{ Monitor: &hydra.ConfigMonitor{ Host: "localhost", Port: 0, }, } c := hydra.NewContext() monitor, _ := hydra.NewMonitor(config) c.RunProcess(monitor) 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) c.MonitorCh <- &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)) }
func TestTrailRegexp(t *testing.T) { tmpdir, _ := ioutil.TempDir(os.TempDir(), "hydra-test") file, _ := ioutil.TempFile(tmpdir, "logfile.") defer os.RemoveAll(tmpdir) reg := hydra.RegexpApache configLogfile := &hydra.ConfigLogfile{ Tag: "test", File: file.Name(), Format: hydra.FormatRegexp, Regexp: &hydra.Regexp{Regexp: reg}, FieldName: "message", ConvertMap: hydra.NewConvertMap("size:integer,code:integer"), TimeParse: true, TimeFormat: hydra.TimeFormatApache, TimeKey: "time", } c := hydra.NewContext() watcher, err := hydra.NewWatcher() if err != nil { t.Error(err) } inTail, err := hydra.NewInTail(configLogfile, watcher) if err != nil { t.Error(err) } c.RunProcess(inTail) c.RunProcess(watcher) go func() { time.Sleep(1 * time.Second) fileWriter(t, file, RegexpLogs) }() i := 0 for i < len(RegexpLogs) { recordSet := <-c.MessageCh if recordSet.Tag != "test" { t.Errorf("got %v\nwant %v", recordSet.Tag, "test") } for _, _record := range recordSet.Records { record := _record.(*fluent.TinyFluentRecord) d := record.GetAllData() e := RegexpParsed[i] if ts, ok := e["_time"]; ok { if ts.(time.Time).Unix() != record.Timestamp { t.Errorf("expected record[%d] timestamp %s got %s", i, ts, record.Timestamp) } delete(e, "_time") } if !reflect.DeepEqual(e, d) { t.Errorf("expected %#v got %#v", d, e) } i++ } } }
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.FormatLTSV, ConvertMap: hydra.NewConvertMap("foo:integer"), FieldName: "message", TimeParse: true, TimeFormat: hydra.DefaultTimeFormat, TimeKey: hydra.DefaultTimeKey, } c := hydra.NewContext() watcher, err := hydra.NewWatcher() if err != nil { t.Error(err) } inTail, err := hydra.NewInTail(configLogfile, watcher) if err != nil { t.Error(err) } c.RunProcess(inTail) c.RunProcess(watcher) go func() { time.Sleep(1 * time.Second) fileWriter(t, file, LTSVLogs) }() i := 0 for i < len(LTSVLogs) { recordSet := <-c.MessageCh 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, } c := hydra.NewContext() inForward, err := hydra.NewInForward(config) if err != nil { t.Error(err) } c.RunProcess(inForward) 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 <-c.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) c := hydra.NewContext() outForward, err := hydra.NewOutForward([]*hydra.ConfigServer{configServer}) if err != nil { t.Error(err) } c.RunProcess(outForward) recordSet := prepareRecordSet() c.MessageCh <- 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) c.MessageCh <- recordSet // Afeter unexpected server closing, first Write() will be succeeded and lost... sleep(1) c.MessageCh <- 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) c.Shutdown() sleep(1) }
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", } c := hydra.NewContext() watcher, err := hydra.NewWatcher() if err != nil { t.Error(err) } inTail, err := hydra.NewInTail(configLogfile, watcher) if err != nil { t.Error(err) } c.RunProcess(inTail) c.RunProcess(watcher) resultCh := make(chan string) go reciever(t, c.MessageCh, "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) c := hydra.NewContext() outForward, err := hydra.NewOutForward([]*hydra.ConfigServer{configServer}) if err != nil { t.Error(err) } c.RunProcess(outForward) recordSet := prepareRecordSet() c.MessageCh <- recordSet sleep(3) if n := atomic.LoadInt64(&counter); n != int64(len(TestMessageLines)) { t.Error("insufficient recieved messages. sent", len(TestMessageLines), "recieved", n) } c.Shutdown() close(mockCloser) sleep(1) }