-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcollector.go
130 lines (108 loc) · 2.68 KB
/
collector.go
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
package simple_collector
import (
"net/http"
"time"
"github.com/vidmed/logger"
"os"
"golang.org/x/net/context"
"golang.org/x/net/context/ctxhttp"
)
const (
userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) " +
"AppleWebKit/537.36 (KHTML, like Gecko) " +
"Chrome/53.0.2785.143 " +
"Safari/537.36"
)
var (
requestTimeout = 5
)
func Run(sourceFile, outputFile, outputFileType string, maxWorkerCount, timeout int) {
// init timeout
requestTimeout = timeout
// init output method
output, err := NewOutput(getWriter(outputFileType))
if err != nil {
logger.Get().Errorln(err)
os.Exit(1)
}
u, err := getJobs(sourceFile)
if err != nil {
logger.Get().Errorln(err)
os.Exit(1)
}
if maxWorkerCount > len(u) {
maxWorkerCount = len(u)
}
jobs := make(chan string, len(u))
results := make(chan *ResponseData, maxWorkerCount)
countTimeoutErr := make(chan int64, maxWorkerCount)
go func(countTimeoutErr chan int64) {
logger.Get().Infoln("Context error counter ran")
var count, total int64
var ok bool
BrakeLoop:
for {
select {
case count, ok = <-countTimeoutErr:
if !ok {
break BrakeLoop
}
total += count
default:
}
}
logger.Get().Infof("context error count %d", total)
}(countTimeoutErr)
for w := 1; w <= maxWorkerCount; w++ {
go worker(jobs, results, countTimeoutErr)
}
for _, j := range u {
jobs <- j
}
close(jobs)
logger.Get().Infof("%d jobs sent.", len(u))
data := make([]*ResponseData, len(u))
for k := range data {
r := <-results
data[k] = r
}
logger.Get().Infoln("Getting from result channel done")
close(countTimeoutErr)
logger.Get().Infoln("Response data writer ran")
output.ResponseData = data
err = output.writeResult(outputFile)
if err != nil {
logger.Get().Errorln(err)
os.Exit(1)
}
logger.Get().Info("Well done.")
}
func worker(jobs <-chan string, results chan<- *ResponseData, countTimeoutErr chan<- int64) {
for j := range jobs {
res := &ResponseData{Url: j}
resp, latency, err := Send(j)
if err != nil {
res.Error = err.Error()
countTimeoutErr <- 1
} else {
res.ResponseCode = resp.StatusCode
}
res.Latency = latency.String()
results <- res
}
}
func Send(url string) (response *http.Response, latency time.Duration, err error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(requestTimeout)*time.Second)
defer cancel()
client := &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("User-Agent", userAgent)
start := time.Now()
response, err = ctxhttp.Do(ctx, client, req)
latency = time.Since(start)
return
}