Skip to content

Commit 7c52fe6

Browse files
committed
first commit
0 parents  commit 7c52fe6

5 files changed

Lines changed: 207 additions & 0 deletions

File tree

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
samples/*
2+
*.log
3+
*.notes
4+
main

cmd/main.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"time"
7+
8+
"github.com/devops-works/slowql"
9+
"github.com/sirupsen/logrus"
10+
)
11+
12+
func main() {
13+
if len(os.Args) != 2 {
14+
fmt.Printf("Usage: %s file.log\n", os.Args[0])
15+
os.Exit(1)
16+
}
17+
18+
fd, err := os.Open(os.Args[1])
19+
if err != nil {
20+
panic(err)
21+
}
22+
p := slowql.NewParser(fd)
23+
24+
time.Sleep(time.Second)
25+
_, err = p.GetNext()
26+
if err != nil {
27+
logrus.Error(err)
28+
}
29+
}

go.mod

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module github.com/devops-works/slowql
2+
3+
go 1.15
4+
5+
require (
6+
github.com/eze-kiel/dbg v0.0.0-20210216174248-80e92443539f
7+
github.com/sirupsen/logrus v1.8.0
8+
)

go.sum

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/eze-kiel/dbg v0.0.0-20210216174248-80e92443539f h1:2pd4IQWawG8ODp/32eHZUdHgF34duToORzHk2l4CN2c=
4+
github.com/eze-kiel/dbg v0.0.0-20210216174248-80e92443539f/go.mod h1:Rf/ZwTBI7xz4GEeErDZxZso3QMbWPxnx75TRJn6qhCc=
5+
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
6+
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
7+
github.com/magefile/mage v1.10.0 h1:3HiXzCUY12kh9bIuyXShaVe529fJfyqoVM42o/uom2g=
8+
github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
9+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
10+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
11+
github.com/sirupsen/logrus v1.8.0 h1:nfhvjKcUMhBMVqbKHJlk5RPrrfYr/NMo3692g0dwfWU=
12+
github.com/sirupsen/logrus v1.8.0/go.mod h1:4GuYW9TZmE769R5STWrRakJc4UqQ3+QQ95fyz7ENv1A=
13+
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
14+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
15+
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
16+
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

slowql.go

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
package slowql
2+
3+
import (
4+
"bufio"
5+
"io"
6+
"strings"
7+
"time"
8+
9+
"github.com/eze-kiel/dbg"
10+
"github.com/sirupsen/logrus"
11+
)
12+
13+
type Parser struct {
14+
Source io.Reader
15+
StackSize int
16+
stack chan Query
17+
rawBlocs chan []string
18+
scanner bufio.Scanner
19+
}
20+
21+
// Query contains query informations
22+
type Query struct {
23+
Time time.Time
24+
User string
25+
Host string
26+
IP string
27+
ID int
28+
QueryTime time.Time
29+
LockTime time.Time
30+
RowsSent int
31+
RowsExamined int
32+
Timestamp time.Time
33+
Query string
34+
}
35+
36+
// GetNext returns the next query
37+
func (p Parser) GetNext() (Query, error) {
38+
var q Query
39+
40+
select {
41+
case q := <-p.stack:
42+
return q, nil
43+
default:
44+
return q, io.EOF
45+
}
46+
}
47+
48+
// NewParser creates the stack channel and launches background goroutines
49+
func NewParser(r io.Reader) *Parser {
50+
var p Parser
51+
52+
p.StackSize = 1024
53+
p.Source = r
54+
p.scanner = *bufio.NewScanner(r)
55+
56+
p.stack = make(chan Query, p.StackSize)
57+
p.rawBlocs = make(chan []string, p.StackSize)
58+
59+
go p.consume()
60+
go p.scan()
61+
62+
return &p
63+
}
64+
65+
// scan reads the source line by line, and send those lines to the parser one
66+
// after each other
67+
func (p *Parser) scan() {
68+
var bloc []string
69+
inHeader, inQuery := false, false
70+
71+
for p.scanner.Scan() {
72+
line := p.scanner.Text()
73+
74+
// Drop useless lines
75+
if p.scanner.Text()[0] == '#' && strings.Contains(p.scanner.Text(), "Quit;") {
76+
continue
77+
}
78+
79+
/*
80+
This big if/else statement detects if the curernt line in a header
81+
or a request, and if it belongs to the same bloc or not
82+
*/
83+
// In header
84+
if strings.HasPrefix(line, "#") {
85+
inHeader = true
86+
if inQuery {
87+
// A new bloc is starting, we send the previous one if it is not
88+
// the first one
89+
inQuery = false
90+
dbg.Point(len(bloc))
91+
if len(bloc) != 0 {
92+
p.rawBlocs <- bloc
93+
}
94+
} else {
95+
// We are in the same header as before
96+
bloc = append(bloc, line)
97+
}
98+
} else { // In request
99+
inQuery = true
100+
if inHeader {
101+
// We were in an header, and now are in a request, but in the
102+
// same bloc
103+
inHeader = false
104+
}
105+
bloc = append(bloc, line)
106+
}
107+
}
108+
109+
// In case of error, log it
110+
if err := p.scanner.Err(); err != nil {
111+
logrus.Error(err)
112+
}
113+
114+
logrus.Infof("all the file has been parsed")
115+
116+
// Send the last bloc
117+
p.rawBlocs <- bloc
118+
119+
close(p.rawBlocs)
120+
}
121+
122+
// consume consumes the received line to extract the informations, and send the
123+
// Query object to the stack
124+
125+
// TODO(ezekiel): here do excatly the same thing as before, so instead of sending
126+
// bloc, we could conusme the lines and return the query instead
127+
func (p *Parser) consume() {
128+
select {
129+
case bloc := <-p.rawBlocs:
130+
dbg.Printf("received new bloc\n")
131+
var q Query
132+
133+
// consume each line of the bloc
134+
for _, line := range bloc {
135+
if strings.HasPrefix(line, "#") {
136+
q.parseHeader(line)
137+
} else {
138+
q.parseRequest(line)
139+
}
140+
}
141+
}
142+
}
143+
144+
func (q *Query) parseHeader(line string) {
145+
146+
}
147+
148+
func (q *Query) parseRequest(line string) {
149+
150+
}

0 commit comments

Comments
 (0)