Skip to content

Commit 47b30b2

Browse files
authored
Use health check endpoint (#19)
Use health check endpoint to verify HEC connection
1 parent 7e451b1 commit 47b30b2

File tree

4 files changed

+126
-9
lines changed

4 files changed

+126
-9
lines changed

hec_client.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ type hecClient struct {
3333
client *http.Client
3434
transport *http.Transport
3535

36-
url string
37-
auth string
36+
url string
37+
healthCheckURL string
38+
auth string
3839

3940
// http compression
4041
gzipCompression bool
@@ -146,7 +147,7 @@ func (hec *hecClient) tryPostMessages(messages []*splunkMessage) error {
146147
}
147148

148149
func (hec *hecClient) verifySplunkConnection(l *splunkLogger) error {
149-
req, err := http.NewRequest(http.MethodOptions, hec.url, nil)
150+
req, err := http.NewRequest(http.MethodGet, hec.healthCheckURL, nil)
150151
if err != nil {
151152
return err
152153
}

splunk_logger.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ func New(info logger.Info) (logger.Logger, error) {
255255
client: client,
256256
transport: transport,
257257
url: splunkURL.String(),
258+
healthCheckURL: composeHealthCheckURL(splunkURL),
258259
auth: "Splunk " + splunkToken,
259260
gzipCompression: gzipCompression,
260261
gzipCompressionLevel: gzipCompressionLevel,
@@ -266,8 +267,8 @@ func New(info logger.Info) (logger.Logger, error) {
266267
stream: make(chan *splunkMessage, streamChannelSize),
267268
}
268269

269-
// By default we verify connection, but we allow use to skip that
270-
verifyConnection := true
270+
// By default we don't verify connection, but we allow user to enable that
271+
verifyConnection := false
271272
if verifyConnectionStr, ok := info.Config[splunkVerifyConnectionKey]; ok {
272273
var err error
273274
verifyConnection, err = strconv.ParseBool(verifyConnectionStr)
@@ -399,6 +400,13 @@ func parseURL(info logger.Info) (*url.URL, error) {
399400
return splunkURL, nil
400401
}
401402

403+
/*
404+
parseURL() makes sure that the URL is the format of: scheme://dns_name_or_ip:port
405+
*/
406+
func composeHealthCheckURL(splunkURL *url.URL) string {
407+
return splunkURL.Scheme + "://" + splunkURL.Host + "/services/collector/health"
408+
}
409+
402410
func getAdvancedOptionDuration(envName string, defaultValue time.Duration) time.Duration {
403411
valueStr := os.Getenv(envName)
404412
if valueStr == "" {

splunk_test.go

Lines changed: 111 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"compress/gzip"
2121
"fmt"
2222
"os"
23+
"strings"
2324
"testing"
2425
"time"
2526

@@ -82,6 +83,113 @@ func TestNewMissedUrl(t *testing.T) {
8283
}
8384
}
8485

86+
//splunk-url needs to be in the format of scheme://dns_name_or_ip<:port>
87+
func TestUrlFormat(t *testing.T) {
88+
info := logger.Info{
89+
Config: map[string]string{
90+
splunkURLKey: "127.0.0.1",
91+
},
92+
}
93+
_, err := parseURL(info)
94+
if err.Error() != "splunk: expected format scheme://dns_name_or_ip:port for splunk-url" {
95+
t.Fatal("Logger driver should fail when no schema is specified")
96+
}
97+
98+
info = logger.Info{
99+
Config: map[string]string{
100+
splunkURLKey: "www.google.com",
101+
},
102+
}
103+
_, err = parseURL(info)
104+
if err.Error() != "splunk: expected format scheme://dns_name_or_ip:port for splunk-url" {
105+
t.Fatal("Logger driver should fail when schema is not specified")
106+
}
107+
108+
info = logger.Info{
109+
Config: map[string]string{
110+
splunkURLKey: "ftp://127.0.0.1",
111+
},
112+
}
113+
_, err = parseURL(info)
114+
if err.Error() != "splunk: expected format scheme://dns_name_or_ip:port for splunk-url" {
115+
t.Fatal("Logger driver should fail when schema is not http or https")
116+
}
117+
118+
info = logger.Info{
119+
Config: map[string]string{
120+
splunkURLKey: "http://127.0.0.1:8088/test",
121+
},
122+
}
123+
_, err = parseURL(info)
124+
if err.Error() != "splunk: expected format scheme://dns_name_or_ip:port for splunk-url" {
125+
t.Fatal("Logger driver should fail when path is specified")
126+
}
127+
128+
info = logger.Info{
129+
Config: map[string]string{
130+
splunkURLKey: "testURL",
131+
},
132+
}
133+
_, err = parseURL(info)
134+
if err.Error() != "splunk: expected format scheme://dns_name_or_ip:port for splunk-url" {
135+
t.Fatal("Logger driver should fail when no schema is specified")
136+
}
137+
138+
info = logger.Info{
139+
Config: map[string]string{
140+
splunkURLKey: "http://www.host.com/?q=hello",
141+
},
142+
}
143+
_, err = parseURL(info)
144+
if err.Error() != "splunk: expected format scheme://dns_name_or_ip:port for splunk-url" {
145+
t.Fatal("Logger driver should fail when query parameter is specified")
146+
}
147+
148+
info = logger.Info{
149+
Config: map[string]string{
150+
splunkURLKey: "http://www.host.com#hello",
151+
},
152+
}
153+
_, err = parseURL(info)
154+
if err.Error() != "splunk: expected format scheme://dns_name_or_ip:port for splunk-url" {
155+
t.Fatal("Logger driver should fail when fragment is specified")
156+
}
157+
158+
info = logger.Info{
159+
Config: map[string]string{
160+
splunkURLKey: "127.0.1:8000",
161+
},
162+
}
163+
_, err = parseURL(info)
164+
if !strings.HasPrefix(err.Error(), "splunk: failed to parse") {
165+
t.Fatal("Logger driver should fail when path is specified")
166+
}
167+
168+
info = logger.Info{
169+
Config: map[string]string{
170+
splunkURLKey: "https://127.0.1:8000",
171+
},
172+
}
173+
174+
url, err := parseURL(info)
175+
176+
if url.String() != "https://127.0.1:8000/services/collector/event/1.0" {
177+
t.Fatalf("%s is not the right format of HEC endpoint.", url.String())
178+
}
179+
180+
info = logger.Info{
181+
Config: map[string]string{
182+
splunkURLKey: "https://127.0.1:8000/",
183+
},
184+
}
185+
186+
url, err = parseURL(info)
187+
188+
if url.String() != "https://127.0.1:8000/services/collector/event/1.0" {
189+
t.Fatalf("%s is not the right format of HEC endpoint.", url.String())
190+
}
191+
}
192+
85193
// Driver require user to specify splunk-token
86194
func TestNewMissedToken(t *testing.T) {
87195
info := logger.Info{
@@ -126,8 +234,8 @@ func TestDefault(t *testing.T) {
126234
t.Fatal("Unexpected logger driver name")
127235
}
128236

129-
if !hec.connectionVerified {
130-
t.Fatal("By default connection should be verified")
237+
if hec.connectionVerified {
238+
t.Fatal("By default connection should not be verified")
131239
}
132240

133241
splunkLoggerDriver, ok := loggerDriver.(*splunkLoggerInline)
@@ -1088,7 +1196,7 @@ func TestSkipVerify(t *testing.T) {
10881196
}
10891197

10901198
if len(hec.messages) != defaultStreamChannelSize*4 {
1091-
t.Fatal("Not all messages delivered")
1199+
t.Fatal("Not all messages delivered %s ")
10921200
}
10931201

10941202
for i, message := range hec.messages {

splunkhecmock_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func (hec *HTTPEventCollectorMock) ServeHTTP(writer http.ResponseWriter, request
9797
}
9898

9999
switch request.Method {
100-
case http.MethodOptions:
100+
case http.MethodGet:
101101
// Verify that options method is getting called only once
102102
if hec.connectionVerified {
103103
hec.test.Errorf("Connection should not be verified more than once. Got second request with %s method.", request.Method)

0 commit comments

Comments
 (0)