This repository has been archived by the owner on Nov 15, 2018. It is now read-only.
/
gologger.go
136 lines (102 loc) · 2.97 KB
/
gologger.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
131
132
133
134
135
136
package main
import (
"bufio"
"flag"
"fmt"
"io"
"log/syslog"
"os"
"sync"
"time"
)
// Reads lines from input and writes to queue. If queue is unavailable for
// writing, pops and drops an entry from queue to make room in order to maintain
// a stable consumption rate from input.
//
// Signals to a WaitGroup when there's nothing left to read from input.
func read(input io.ReadCloser, queue chan []byte, wg *sync.WaitGroup) {
defer wg.Done()
//reader := bufio.NewReader(input)
reader := bufio.NewScanner(input)
fmt.Println("reader started")
var totalLines int64 = 0
var drops int64 = 0
var cumuReadDuration int64 = 0 // micros
//var delim byte = '\n'
//for {
for reader.Scan() {
//line, err := reader.ReadBytes(delim)
start := time.Now()
/*
if err != nil {
fmt.Println("reader shutting down")
break
}
*/
totalLines++
select {
//case queue <- line:
case queue <- reader.Bytes():
// queued
default:
// evict the oldest entry to make room
<-queue
drops++
//queue <- line
queue <- reader.Bytes()
}
cumuReadDuration += time.Now().Sub(start).Nanoseconds() / 1000
}
avgReadLatency := float64(cumuReadDuration) / float64(totalLines)
fmt.Println("total lines read: ", totalLines)
fmt.Println("reader evictions: ", drops)
fmt.Printf("avg read latency (us): %.3v\n", avgReadLatency)
}
// Reads from a queue and writes to writer until the queue channel
// is closed. Signals to a WaitGroup when done.
func write(queue chan []byte, writer *syslog.Writer, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Println("writer started")
var totalWrites int64 = 0
var cumuWriteDuration int64 = 0
for line := range queue {
start := time.Now()
writer.Write(line)
//var _ = line
totalWrites++
cumuWriteDuration += time.Now().Sub(start).Nanoseconds() / 1000
}
fmt.Println("writer shutting down")
avgWriteDuration := float64(cumuWriteDuration) / float64(totalWrites)
fmt.Println("total lines written: ", totalWrites)
fmt.Printf("avg write duration (us): %.3v\n", avgWriteDuration)
}
func main() {
// syslog setup
logger, logErr := syslog.New(syslog.LOG_INFO, "log-gurney")
if logErr != nil {
fmt.Println("Error opening syslog: %s", logErr)
os.Exit(1)
}
// arg parsing
var queueSize int
flag.IntVar(&queueSize, "queuesize", 1000, "max size for the internal line queue")
flag.Parse()
fmt.Println("using queue size ", queueSize)
// setup
queue := make(chan []byte, queueSize)
readGroup := &sync.WaitGroup{}
writeGroup := &sync.WaitGroup{}
readGroup.Add(1)
writeGroup.Add(1)
// start writing before reading: there's still a race here, but not a problem
// for this POC.
go write(queue, logger, writeGroup)
go read(os.Stdin, queue, readGroup)
// wait for the the reader to complete
readGroup.Wait()
// shut down the writer by closing the queue
close(queue)
writeGroup.Wait()
fmt.Println("done.")
}