-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
173 lines (148 loc) · 3.53 KB
/
Copy pathmain.go
File metadata and controls
173 lines (148 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"os/signal"
"path"
"path/filepath"
"strings"
"text/template"
"github.com/Sirupsen/logrus"
"golang.org/x/net/websocket"
)
// will be populated at build time
var version string
// Config holds the program configuration
type Config struct {
Paths []string
Host string
NoStdout bool
NoOpen bool
NoHTTP bool
Verbose bool
Version bool
}
var cfg = &Config{Paths: DefaultPaths}
func init() {
log.SetOutput(os.Stderr)
flag.StringVar(&cfg.Host, "host", "localhost:48245", "Address on which the htail will listen for connections")
flag.BoolVar(&cfg.NoStdout, "no-stdout", false, "Disable output to stdout")
flag.BoolVar(&cfg.NoHTTP, "no-http", false, "Disable output to http")
flag.BoolVar(&cfg.Verbose, "v", false, "Verbose output")
flag.BoolVar(&cfg.Version, "version", false, "Verbose output")
}
func scanDir(dir string) []string {
files := make([]string, 0)
fis, err := ioutil.ReadDir(dir)
if err != nil {
log.Printf("Error while reading directory %#v: %s\n", dir, err)
return files
}
for _, fi := range fis {
if fi.IsDir() {
f := scanDir(path.Join(dir, fi.Name()))
files = append(files, f...)
continue
}
files = append(files, path.Join(dir, fi.Name()))
}
return files
}
func ScanPaths(paths []string) []string {
files := make([]string, 0)
for _, path := range paths {
matches, err := filepath.Glob(path)
if err != nil {
log.Printf("Pattern %#v is not valid\n", path)
continue
}
for i := range matches {
p := matches[i]
fi, err := os.Stat(p)
if err != nil && !os.IsNotExist(err) {
logrus.Errorf("Error while stating %#v: %s", p, err)
continue
}
if !fi.IsDir() {
files = append(files, p)
continue
}
f := scanDir(p)
files = append(files, f...)
}
}
return files
}
func main() {
flag.Parse()
if cfg.Version {
log.Printf("%s - Version %s", os.Args[0], version)
os.Exit(0)
}
paths := flag.Args()
// if there's nothing on the argument line, we check for the environment variable
if len(paths) == 0 {
paths = strings.Split(os.Getenv("HTAIL_PATH"), ":")
// if there's nothing in the env var, we switch to the default
if len(paths) == 1 && paths[0] == "" {
paths = DefaultPaths
}
}
cfg.Paths = paths
files := ScanPaths(cfg.Paths)
tailer := NewTailer()
tailer.AddReader("stdin", os.Stdin)
for _, f := range files {
if cfg.Verbose {
log.Printf("Tailing %s\n", f)
}
if err := tailer.AddFile(f); err != nil {
log.Println(err)
continue
}
}
if !cfg.NoStdout {
tailer.AddOutput(NewOutputStdout())
}
if !cfg.NoHTTP {
hub := newWebsocketHub()
tailer.AddOutput(hub)
http.HandleFunc("/", func(rw http.ResponseWriter, req *http.Request) {
tmpl, err := template.New("index").Parse(templateIndex)
if err != nil {
log.Panicln(err)
}
rw.Header().Set("Content-Type", "text/html; charset=UTF-8")
tmpl.Execute(rw, cfg)
})
http.Handle("/ws", websocket.Handler(func(ws *websocket.Conn) {
hub.addConn(ws)
select {}
}))
go func() {
if cfg.Verbose {
log.Println("Listening to", cfg.Host)
}
go func() {
err := http.ListenAndServe(cfg.Host, nil)
if err != nil {
log.Fatalf("Error starting HTTP server: %s\n", err)
}
}()
if !cfg.NoOpen {
if err := openBrowser(fmt.Sprintf("http://%s", cfg.Host)); err != nil {
log.Printf("Error while trying to open browser: %s\n", err)
}
}
}()
}
tailer.Run()
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, os.Kill)
_ = <-c
tailer.Close()
}