Skip to content

Commit f37a969

Browse files
authored
Feature/customize log and lift test coverage (#28)
* complete the structure of influxlog * add cache tests * refactor influx db writer
1 parent e2ff3de commit f37a969

File tree

18 files changed

+651
-19
lines changed

18 files changed

+651
-19
lines changed

backends/redis_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ func (suite *RedisBackendTestSuite) TestWriteCacheInRedis() {
5252

5353
suite.Equal(len(content), backend.Length())
5454

55-
backend.Close()
55+
err = backend.Close()
56+
suite.Nil(err)
5657

5758
reader, err := backend.GetReader()
5859
suite.Nil(err)

cache_test.go

Lines changed: 80 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package httpcache
22

33
import (
4+
"io/ioutil"
45
"net/http"
56
"net/http/httptest"
67
"testing"
78
"time"
89

10+
"github.com/sillygod/cdp-cache/backends"
911
"github.com/stretchr/testify/suite"
1012
)
1113

@@ -16,10 +18,10 @@ func makeRequest(url string, headers http.Header) *http.Request {
1618
}
1719

1820
func makeResponse(code int, headers http.Header) *Response {
19-
return &Response{
20-
Code: code,
21-
snapHeader: headers,
22-
}
21+
response := NewResponse()
22+
response.Code = code
23+
response.snapHeader = headers
24+
return response
2325
}
2426

2527
func makeHeader(key string, value string) http.Header {
@@ -142,7 +144,81 @@ func (suite *RuleMatcherTestSuite) TestHeaderNotMatched() {
142144
suite.False(match)
143145
}
144146

147+
type EntryTestSuite struct {
148+
suite.Suite
149+
config *Config
150+
}
151+
152+
func (suite *EntryTestSuite) SetupSuite() {
153+
err := backends.InitGroupCacheRes(50 * 1024 * 1024)
154+
suite.Nil(err)
155+
suite.config = getDefaultConfig()
156+
}
157+
158+
func (suite *EntryTestSuite) TestEntryWritePublicResponse() {
159+
160+
req := makeRequest("/", http.Header{})
161+
res := makeResponse(200, makeHeader("Cache-Control", "max-age=43200"))
162+
entry := NewEntry("unique_key", req, res, suite.config)
163+
164+
suite.Equal("unique_key", entry.Key())
165+
rw := httptest.NewRecorder()
166+
167+
suite.config.Type = inMemory
168+
input := []byte(`rain cats and dogs`)
169+
170+
go func() {
171+
entry.Response.Write(input)
172+
entry.Response.Close() // we can write the entry's body to rw after closing upstream response
173+
}()
174+
175+
entry.setBackend(req.Context(), suite.config)
176+
177+
entry.WriteBodyTo(rw)
178+
result, err := ioutil.ReadAll(rw.Result().Body)
179+
suite.Nil(err)
180+
suite.Equal(input, result)
181+
}
182+
183+
func (suite *EntryTestSuite) TestEntryWritePrivateResponse() {
184+
req := makeRequest("/", http.Header{})
185+
res := makeResponse(502, http.Header{})
186+
entry := NewEntry("unique_key2", req, res, suite.config)
187+
188+
go func() {
189+
entry.Response.Close()
190+
}()
191+
192+
rw := httptest.NewRecorder()
193+
entry.WriteBodyTo(rw)
194+
suite.Equal(502, rw.Code)
195+
}
196+
197+
func (suite *EntryTestSuite) TearDownSuite() {
198+
err := backends.ReleaseGroupCacheRes()
199+
suite.Nil(err)
200+
}
201+
202+
type HTTPCacheTestSuite struct {
203+
suite.Suite
204+
config *Config
205+
}
206+
207+
func (suite *HTTPCacheTestSuite) SetupSuite() {
208+
err := backends.InitGroupCacheRes(50 * 1024 * 1024)
209+
suite.Nil(err)
210+
suite.config = getDefaultConfig()
211+
}
212+
213+
// TODO: add http cache test
214+
215+
func (suite *HTTPCacheTestSuite) TearDownSuite() {
216+
err := backends.ReleaseGroupCacheRes()
217+
suite.Nil(err)
218+
}
219+
145220
func TestCacheStatusTestSuite(t *testing.T) {
146221
suite.Run(t, new(CacheStatusTestSuite))
147222
suite.Run(t, new(RuleMatcherTestSuite))
223+
suite.Run(t, new(EntryTestSuite))
148224
}

caddyfile.go

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ var (
4343
defaultcacheBucketsNum = 256
4444
defaultCacheMaxMemorySize = GB // default is 1 GB
4545
defaultRedisConnectionSetting = "localhost:6379 0"
46-
defaultCacheKeyTemplate = "{http.request.method} {http.request.host}{http.request.uri.path} {http.request.uri.query}"
46+
defaultCacheKeyTemplate = "{http.request.method} {http.request.host}{http.request.uri.path}?{http.request.uri.query}"
4747
// Note: prevent character space in the key
4848
// the key is refereced from github.com/caddyserver/caddy/v2/modules/caddyhttp.addHTTPVarsToReplacer
4949
)
@@ -63,7 +63,9 @@ const (
6363
// format: addr db password or addr db or addr
6464
// ex.
6565
// localhost:6789 0 => connect without password. only index and host:port provided
66+
// the following are keys for extensions
6667
keyDistributed = "distributed"
68+
keyInfluxLog = "influxlog"
6769
)
6870

6971
func init() {
@@ -190,23 +192,23 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
190192
}
191193

192194
cacheRule := &HeaderRuleMatcher{Header: args[0], Value: args[1:]}
193-
d, _ := json.Marshal(cacheRule)
195+
data, _ := json.Marshal(cacheRule)
194196

195197
config.RuleMatchersRaws = append(config.RuleMatchersRaws, RuleMatcherRawWithType{
196198
Type: MatcherTypeHeader,
197-
Data: d,
199+
Data: data,
198200
})
199201

200202
case keyMatchPath:
201203
if len(args) != 1 {
202204
return d.Err("Invalid usage of match_path in cache config.")
203205
}
204206
cacheRule := &PathRuleMatcher{Path: args[0]}
205-
d, _ := json.Marshal(cacheRule)
207+
data, _ := json.Marshal(cacheRule)
206208

207209
config.RuleMatchersRaws = append(config.RuleMatchersRaws, RuleMatcherRawWithType{
208210
Type: MatcherTypePath,
209-
Data: d,
211+
Data: data,
210212
})
211213

212214
case keyCacheKey:
@@ -238,7 +240,7 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
238240

239241
unm, ok := mod.New().(caddyfile.Unmarshaler)
240242
if !ok {
241-
return d.Errf("distributed module '%s' is not a Caddfile unmarshaler", mod)
243+
return d.Errf("distributed module '%s' is not a Caddyfile unmarshaler", mod)
242244
}
243245

244246
err = unm.UnmarshalCaddyfile(d.NewFromNextSegment())
@@ -248,6 +250,13 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
248250

249251
h.DistributedRaw = caddyconfig.JSONModuleObject(unm, "distributed", "consul", nil)
250252

253+
// case keyInfluxLog:
254+
// raw, err := setupInfluxLog(keyInfluxLog, d, args)
255+
// if err != nil {
256+
// return err
257+
// }
258+
// h.InfluxLogRaw = raw
259+
251260
default:
252261
return d.Err("Unknown cache parameter: " + parameter)
253262
}
@@ -259,6 +268,28 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
259268
return nil
260269
}
261270

271+
func setupInfluxLog(key string, d *caddyfile.Dispenser, args []string) (json.RawMessage, error) {
272+
273+
mod, err := caddy.GetModule("caddy.logging.writers." + key)
274+
if err != nil {
275+
return nil, d.Errf("getting influxlog module '%s': '%v'", mod, err)
276+
}
277+
278+
unm, ok := mod.New().(caddyfile.Unmarshaler)
279+
if !ok {
280+
return nil, d.Errf("influxlog module '%s' is not a Caddyfile unmarshaler", mod)
281+
}
282+
283+
err = unm.UnmarshalCaddyfile(d.NewFromNextSegment())
284+
if err != nil {
285+
return nil, err
286+
}
287+
288+
raw := caddyconfig.JSONModuleObject(unm, "mylog", "influxlog", nil)
289+
290+
return raw, nil
291+
}
292+
262293
// Interface guards
263294
var (
264295
_ caddyfile.Unmarshaler = (*Handler)(nil)

caddyfile_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,19 @@ func (suite *CaddyfileTestSuite) TestInvalidParameter() {
6363
suite.Error(err, "invalid parameter")
6464
}
6565

66+
func (suite *CaddyfileTestSuite) TestRedisConnectionSetting() {
67+
h := httpcaddyfile.Helper{
68+
Dispenser: caddyfile.NewTestDispenser(`
69+
http_cache {
70+
redis_connection_setting localhost:6379 2 pass 5
71+
}
72+
`),
73+
}
74+
75+
_, err := parseCaddyfile(h)
76+
suite.Error(err, "invalid usage of redis_connection_setting in cache config.")
77+
}
78+
6679
func (suite *CaddyfileTestSuite) TestDistributedCacheConfig() {
6780
h := httpcaddyfile.Helper{
6881
Dispenser: caddyfile.NewTestDispenser(`

cmd/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131

3232
// plug in Caddy modules here
3333
_ "github.com/sillygod/cdp-cache"
34+
_ "github.com/sillygod/cdp-cache/extends/influxlog"
3435

3536
_ "github.com/caddyserver/caddy/v2/modules/standard"
3637
)

example/influxdb_monitor/Caddyfile

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
order http_cache before reverse_proxy
3+
admin 0.0.0.0:7777
4+
debug
5+
}
6+
7+
:9991 {
8+
reverse_proxy {
9+
to localhost:9995
10+
}
11+
12+
http_cache {
13+
cache_type in_memory
14+
match_path /
15+
16+
}
17+
18+
log {
19+
output influxlog {
20+
addr http://localhost:8086
21+
token "user:pass1234"
22+
organization ""
23+
bucket telegraf
24+
# For influxDB 1.8 the token should follow the rule below
25+
# https://github.com/influxdata/influxdb-client-go#influxdb-18-api-compatibility
26+
}
27+
level debug
28+
}
29+
30+
31+
}
32+
33+
:9995 {
34+
header Cache-control "public"
35+
root * /tmp/caddy-benchmark
36+
file_server
37+
38+
log {
39+
level info
40+
}
41+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
version: "3.7"
2+
3+
services:
4+
influxdb:
5+
image: influxdb:1.8.1
6+
volumes:
7+
- influxdb:/var/lib/influxdb
8+
- ./example/influxdb_monitor/influxdb.conf:/etc/influxdb/influxdb.conf
9+
environment:
10+
- INFLUXDB_ADMIN_USER=admin
11+
- INFLUXDB_ADMIN_PASSWORD=pass1234
12+
- INFLUXDB_USER=user
13+
- INFLUXDB_USER_PASSWORD=pass1234
14+
15+
restart: always
16+
networks:
17+
- influxdata
18+
19+
20+
ports:
21+
- "8086:8086"
22+
- "8082:8082"
23+
24+
# telegraf to collects the syslog
25+
telegraf:
26+
image: telegraf:1.15.1
27+
environment:
28+
- HOSTNAME=songa-telegraf
29+
volumes:
30+
- /var/run/docker.sock:/var/run/docker.sock
31+
- ./example/influxdb_monitor/telegraf.conf:/etc/telegraf/telegraf.conf
32+
33+
restart: always
34+
35+
networks:
36+
- influxdata
37+
38+
depends_on:
39+
- influxdb
40+
41+
chronograf:
42+
image: chronograf:1.8.4
43+
environment:
44+
- RESOURCES_PATH=/usr/share/chronograf/resources
45+
volumes:
46+
- chronograf:/var/lib/chronograf
47+
ports:
48+
- "8888:8888"
49+
50+
restart: always
51+
52+
networks:
53+
- influxdata
54+
55+
depends_on:
56+
- influxdb
57+
- telegraf
58+
59+
# in the future add the grafana log panel
60+
61+
# cdp to write the log as syslog
62+
cdp: &cdp-source
63+
image: golang:1.14.2
64+
container_name: cdp
65+
volumes:
66+
- cdp:/go/
67+
- go-build-cache:/root/.cache/go-build
68+
- .:${PROJECT_PATH}
69+
70+
command: >
71+
sh -c "echo 'spin up caddy proxy cache...' &&
72+
cd ${PROJECT_PATH} &&
73+
go run $PROJECT_PATH/cmd/main.go run --config example/influxdb_monitor/Caddyfile"
74+
75+
ports:
76+
- "9991:9991"
77+
environment:
78+
- PROJECT_PATH=${PROJECT_PATH}
79+
80+
81+
volumes:
82+
cdp:
83+
go-build-cache:
84+
influxdb:
85+
chronograf:
86+
87+
networks:
88+
influxdata:

0 commit comments

Comments
 (0)