Skip to content

Commit b00685e

Browse files
Initial commit for pg-ping
Co-authored-by: prabhu43 <j.prabhu91@gmail.com>
0 parents  commit b00685e

File tree

4 files changed

+160
-0
lines changed

4 files changed

+160
-0
lines changed

.gitignore

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
# Created by https://www.gitignore.io/api/go,visualstudiocode
3+
# Edit at https://www.gitignore.io/?templates=go,visualstudiocode
4+
5+
### Go ###
6+
# Binaries for programs and plugins
7+
*.exe
8+
*.exe~
9+
*.dll
10+
*.so
11+
*.dylib
12+
13+
# Test binary, built with `go test -c`
14+
*.test
15+
16+
# Output of the go coverage tool, specifically when used with LiteIDE
17+
*.out
18+
19+
### Go Patch ###
20+
/vendor/
21+
/Godeps/
22+
23+
### VisualStudioCode ###
24+
.vscode/*
25+
!.vscode/settings.json
26+
!.vscode/tasks.json
27+
!.vscode/launch.json
28+
!.vscode/extensions.json
29+
30+
### VisualStudioCode Patch ###
31+
# Ignore all local history of files
32+
.history
33+
34+
# End of https://www.gitignore.io/api/go,visualstudiocode
35+
.env
36+
pg-ping

go.mod

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module pg-ping
2+
3+
go 1.12
4+
5+
require (
6+
github.com/kelseyhightower/envconfig v1.3.0
7+
github.com/lib/pq v1.0.0
8+
)

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
github.com/kelseyhightower/envconfig v1.3.0 h1:IvRS4f2VcIQy6j4ORGIf9145T/AsUB+oY8LyvN8BXNM=
2+
github.com/kelseyhightower/envconfig v1.3.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
3+
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
4+
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=

main.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"database/sql"
6+
"encoding/json"
7+
"fmt"
8+
"log"
9+
"os"
10+
"time"
11+
12+
"github.com/kelseyhightower/envconfig"
13+
_ "github.com/lib/pq"
14+
)
15+
16+
// PGConfig contains configurations to connect to a PG database
17+
type PGConfig struct {
18+
Username string
19+
Password string
20+
Host string
21+
DBName string
22+
Query string
23+
FrequencyInMS int32
24+
}
25+
26+
// ConnStr returns a connection string to connect to postgres
27+
func (c *PGConfig) ConnStr() string {
28+
return fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=disable", c.Username, c.Password, c.Host, c.DBName)
29+
}
30+
31+
// GetQuery returns the query to use to ping
32+
func (c *PGConfig) GetQuery() string {
33+
if c.Query == "" {
34+
return "select 1"
35+
}
36+
37+
return c.Query
38+
}
39+
40+
// GetFrequency returns the frequence in MS in which the query should be run
41+
func (c *PGConfig) GetFrequency() time.Duration {
42+
if c.FrequencyInMS == 0 {
43+
return time.Second
44+
}
45+
46+
return time.Duration(c.FrequencyInMS) * time.Millisecond
47+
}
48+
49+
func main() {
50+
var conf PGConfig
51+
err := envconfig.Process("PGPING", &conf)
52+
if err != nil {
53+
log.Fatal(err)
54+
}
55+
56+
json.NewEncoder(os.Stdout).Encode(conf)
57+
58+
db, err := sql.Open("postgres", conf.ConnStr())
59+
if err != nil {
60+
log.Fatal(err)
61+
}
62+
defer db.Close()
63+
64+
ticker := time.NewTicker(conf.GetFrequency())
65+
encoder := json.NewEncoder(os.Stdout)
66+
for range ticker.C {
67+
encoder.Encode(executeQuery(db, conf.GetQuery()))
68+
}
69+
}
70+
71+
// SQLResult tracks sql response and time taken
72+
type SQLResult struct {
73+
Value string
74+
TimeTakenInMS float64
75+
Failed bool
76+
FailureMessage string
77+
}
78+
79+
func executeQuery(db *sql.DB, query string) SQLResult {
80+
res := SQLResult{}
81+
82+
ctx, cancelFunc := context.WithCancel(context.Background())
83+
tenSecondTimer := time.NewTimer(10 * time.Second)
84+
go func() {
85+
<-tenSecondTimer.C
86+
cancelFunc()
87+
}()
88+
89+
start := time.Now()
90+
rows, err := db.QueryContext(ctx, query)
91+
res.TimeTakenInMS = time.Since(start).Seconds() * 1000
92+
93+
if err != nil {
94+
res.Failed = true
95+
res.FailureMessage = err.Error()
96+
return res
97+
}
98+
defer rows.Close()
99+
100+
for rows.Next() {
101+
var name string
102+
if err := rows.Scan(&name); err != nil {
103+
res.Failed = true
104+
res.FailureMessage = err.Error()
105+
return res
106+
}
107+
108+
res.Value = name
109+
}
110+
111+
return res
112+
}

0 commit comments

Comments
 (0)