Example #1
0
func tailFile(filename string, config tail.Config, done chan bool) {
	defer func() { done <- true }()
	t, err := tail.TailFile(filename, config)
	if err != nil {
		fmt.Println(err)
		return
	}
	for line := range t.Lines {
		fmt.Println(line.Text)
	}
	err = t.Wait()
	if err != nil {
		fmt.Println(err)
	}
}
Example #2
0
// Read old log lines from a logfile.
func (l *Log) Read(lines int, follow bool, ch chan Data, done chan struct{}) error {
	name := l.l.Filename

	var seek int64
	if lines == 0 {
		f, err := os.Open(name)
		defer f.Close()
		if err != nil {
			return err
		}
		if seek, err = f.Seek(0, os.SEEK_END); err != nil {
			return err
		}
	} else if lines == -1 {
		// return all lines
		dir := filepath.Dir(name)
		files, err := ioutil.ReadDir(dir)
		if err != nil {
			return err
		}
		basename := filepath.Base(name)
		ext := filepath.Ext(basename)
		id := strings.TrimSuffix(basename, ext)
		for _, f := range files {
			if !(strings.HasPrefix(f.Name(), id+"-") && strings.HasSuffix(f.Name(), ext)) {
				continue
			}

			t, err := tail.TailFile(filepath.Join(dir, f.Name()), tail.Config{
				Logger: tail.DiscardingLogger,
			})
			if err != nil {
				return err
			}
			for line := range t.Lines {
				data := Data{}
				if err := json.Unmarshal([]byte(line.Text), &data); err != nil {
					return err
				}
				ch <- data
			}
		}
	}

	t, err := tail.TailFile(name, tail.Config{
		Follow: follow,
		ReOpen: follow,
		Logger: tail.DiscardingLogger,
		Location: &tail.SeekInfo{
			Offset: seek,
			Whence: os.SEEK_SET,
		},
	})
	if err != nil {
		return err
	}
outer:
	for {
		select {
		case line, ok := <-t.Lines:
			if !ok {
				break outer
			}
			data := Data{}
			if err := json.Unmarshal([]byte(line.Text), &data); err != nil {
				return err
			}
			ch <- data
		case <-done:
			break outer
		case <-time.After(200 * time.Millisecond):
			if !l.closed {
				continue
			}
			break outer
		}
	}
	close(ch) // send a close event so we know everything was read
	return nil
}