-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathclient.go
145 lines (124 loc) · 3.43 KB
/
client.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
137
138
139
140
141
142
143
144
145
package healthchecks
import (
"errors"
"fmt"
"io"
"net/http"
"strconv"
"sync"
"time"
"github.com/google/uuid"
)
// Client for healthchecks
// if client initialized without any options, it will be disabled by default,
// but you can override it by calling SetEnabled(true).
type Client struct {
wg sync.WaitGroup
enabled bool
http *http.Client
log func(string, error)
userAgent string
baseURL string
uuid string
rid string
create bool
done chan bool
}
// init client
func (c *Client) init(options ...Option) {
c.enabled = true
c.log = DefaultErrLog
c.baseURL = DefaultAPI
c.userAgent = DefaultUserAgent
c.http = &http.Client{Timeout: 10 * time.Second}
c.done = make(chan bool, 1)
c.uuid = ""
if len(options) == 0 {
c.enabled = false
}
for _, option := range options {
option(c)
}
if c.uuid == "" {
randomUUID, _ := uuid.NewRandom() //nolint:errcheck // ignore error
c.uuid = randomUUID.String()
c.create = true
c.log("uuid", fmt.Errorf("check UUID is not provided, using random %q with auto provision", c.uuid))
}
}
// Call API
func (c *Client) Call(operation, endpoint string, body ...io.Reader) {
if !c.enabled {
return
}
c.wg.Add(1)
go c.call(operation, endpoint, body...)
}
// call API, extracted from c.Call to reduce cyclomatic complexity
func (c *Client) call(operation, endpoint string, body ...io.Reader) {
defer c.wg.Done()
targetURL := fmt.Sprintf("%s/%s%s?rid=%s", c.baseURL, c.uuid, endpoint, c.rid)
if c.create {
targetURL += "&create=1"
}
var req *http.Request
var err error
if len(body) > 0 {
req, err = http.NewRequest(http.MethodPost, targetURL, body[0])
} else {
req, err = http.NewRequest(http.MethodHead, targetURL, http.NoBody)
}
if err != nil {
c.log(operation, err)
return
}
req.Header.Set("User-Agent", c.userAgent)
req.Header.Set("Content-Type", "text/plain; charset=utf-8")
resp, err := c.http.Do(req)
if err != nil {
c.log(operation, err)
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
respb, rerr := io.ReadAll(resp.Body)
if rerr != nil {
c.log(operation+":response", rerr)
return
}
rerr = errors.New(string(respb))
c.log(operation+":response", rerr)
return
}
}
// SetEnabled sets the enabled flag, ignoring the options
// if client initialized without any options, it will be disabled by default,
// but you can override it by calling SetEnabled(true).
func (c *Client) SetEnabled(enabled bool) {
c.enabled = enabled
}
// Start signal means the job started
func (c *Client) Start(optionalBody ...io.Reader) {
c.Call("start", "/start", optionalBody...)
}
// Success signal means the job has completed successfully (or, a continuously running process is still running and healthy).
func (c *Client) Success(optionalBody ...io.Reader) {
c.Call("success", "", optionalBody...)
}
// Fail signal means the job failed
func (c *Client) Fail(optionalBody ...io.Reader) {
c.Call("fail", "/fail", optionalBody...)
}
// Log signal just adds an event to the job log, without changing job status
func (c *Client) Log(optionalBody ...io.Reader) {
c.Call("log", "/log", optionalBody...)
}
// ExitStatus signal sends job's exit code (0-255)
func (c *Client) ExitStatus(exitCode int, optionalBody ...io.Reader) {
c.Call("exit status", "/"+strconv.Itoa(exitCode), optionalBody...)
}
// Shutdown the client
func (c *Client) Shutdown() {
c.done <- true
c.wg.Wait()
}