Skip to content

Commit

Permalink
Merge pull request #68 from jranson/caching
Browse files Browse the repository at this point in the history
Don't cache generically-handled paths
  • Loading branch information
LimitlessEarth authored Jun 30, 2018
2 parents a3c9d5d + b4965c2 commit b7131e0
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 101 deletions.
6 changes: 2 additions & 4 deletions deploy/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,13 @@ RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -a -installsuffix cgo -o tric
FROM alpine:3.7
LABEL maintainer "The Trickster Authors <[email protected]>"

RUN addgroup trickgrp && adduser -D -g '' trickusr && adduser trickusr trickgrp

COPY --from=builder /go/src/github.com/Comcast/trickster/trickster /usr/local/bin/trickster
COPY conf/example.conf /etc/trickster/trickster.conf
RUN chown trickusr /usr/local/bin/trickster
RUN chown nobody /usr/local/bin/trickster
RUN chmod +x /usr/local/bin/trickster

RUN apk update && apk add ca-certificates && rm -rf /var/cache/apk/*

EXPOSE 9090 8082
USER trickusr
USER nobody
ENTRYPOINT ["trickster"]
23 changes: 0 additions & 23 deletions handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,29 +142,6 @@ func (t *TricksterHandler) promFullProxyHandler(w http.ResponseWriter, r *http.R
w.Write(body)
}

// promAPIProxyHandler handles proxying of non-query/query_range API calls such as the labels path
func (t *TricksterHandler) promAPIProxyHandler(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
vars := mux.Vars(r)

// clear out the origin moniker from the front of the API path
if originName, ok := vars["originMoniker"]; ok {
if strings.HasPrefix(path, "/"+originName) {
path = strings.Replace(path, "/"+originName, "", 1)
}
}

originURL := t.getOrigin(r).OriginURL + strings.Replace(path, "//", "/", 1)
body, resp, err := t.fetchPromQuery(originURL, r.URL.Query(), r)
if err != nil {
level.Error(t.Logger).Log(lfEvent, "error fetching data from origin Prometheus", lfDetail, err.Error())
w.WriteHeader(http.StatusBadGateway)
return
}

writeResponse(w, body, resp)
}

// promQueryHandler handles calls to /query (for instantaneous values)
func (t *TricksterHandler) promQueryHandler(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
Expand Down
120 changes: 49 additions & 71 deletions handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,25 @@
package main

import (
"bytes"
"encoding/json"
"fmt"
"github.com/go-kit/kit/log"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"github.com/go-kit/kit/log"
"fmt"
"encoding/json"
"bytes"
"io/ioutil"
)

const (
nonexistantOrigin = "http://nonexistent-origin:54321"
exampleQuery = "/api/v1/query?query=up&time=2015-07-01T20:11:15.781Z"
exampleRangeQuery = "/api/v1/query_range?query=up&start=2015-07-01T20:10:30.781Z&end=2015-07-01T20:11:00.781Z&step=15"
nonexistantOrigin = "http://nonexistent-origin:54321"
exampleQuery = "/api/v1/query?query=up&time=2015-07-01T20:11:15.781Z"
exampleRangeQuery = "/api/v1/query_range?query=up&start=2015-07-01T20:10:30.781Z&end=2015-07-01T20:11:00.781Z&step=15"
exampleRangeQuery_query = "up"
exampleRangeQuery_start = "2015-07-01T20:10:30.781Z"
exampleRangeQuery_end = "2015-07-01T20:11:00.781Z"
exampleRangeQuery_step = "15"
exampleRangeQuery_end = "2015-07-01T20:11:00.781Z"
exampleRangeQuery_step = "15"

// this example should have 2 data points later than those in exampleRangeResponse
exampleResponse = `{
Expand Down Expand Up @@ -95,7 +95,6 @@ const (
]
}
}`

)

func TestParseTime(t *testing.T) {
Expand Down Expand Up @@ -172,9 +171,6 @@ func TestUnreachableOriginReturnsStatusBadGateway(t *testing.T) {
{
handler: (*TricksterHandler).promFullProxyHandler,
},
{
handler: (*TricksterHandler).promAPIProxyHandler,
},
{
handler: (*TricksterHandler).promQueryHandler,
},
Expand Down Expand Up @@ -216,7 +212,7 @@ func TestMissingRangeQueryParametersResultInStatusBadRequest(t *testing.T) {
}

func newTestServer(body string) *httptest.Server {
handler := func( w http.ResponseWriter, r *http.Request) {
handler := func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, body)
}
s := httptest.NewServer(http.HandlerFunc(handler))
Expand All @@ -230,7 +226,7 @@ func TestTricksterHandler_getOrigin(t *testing.T) {
// it should get test origin
r := httptest.NewRequest("GET", nonexistantOrigin, nil)
o := tr.getOrigin(r)
if (o.OriginURL != nonexistantOrigin) {
if o.OriginURL != nonexistantOrigin {
t.Errorf("wanted \"%s\" got \"%s\".", nonexistantOrigin, o.OriginURL)
}
}
Expand All @@ -245,9 +241,9 @@ func TestTricksterHandler_promHealthCheckHandler(t *testing.T) {
// it should proxy request
w := httptest.NewRecorder()
r := httptest.NewRequest("GET", es.URL, nil)
tr.promHealthCheckHandler(w,r)
tr.promHealthCheckHandler(w, r)

if (w.Result().StatusCode != 200) {
if w.Result().StatusCode != 200 {
t.Errorf("wanted 200 got %d.", w.Result().StatusCode)
}
}
Expand All @@ -262,26 +258,9 @@ func TestTricksterHandler_promFullProxyHandler(t *testing.T) {
// it should proxy request
w := httptest.NewRecorder()
r := httptest.NewRequest("GET", es.URL, nil)
tr.promFullProxyHandler(w,r)
tr.promFullProxyHandler(w, r)

if (w.Result().StatusCode != 200) {
t.Errorf("wanted 200 got %d.", w.Result().StatusCode)
}
}

func TestTricksterHandler_promAPIProxyHandler(t *testing.T) {
tr, closeFn := newTestTricksterHandler(t)
defer closeFn(t)
es := newTestServer("{}")
defer es.Close()
tr.setTestOrigin(es.URL)

// it should proxy request
w := httptest.NewRecorder()
r := httptest.NewRequest("GET", es.URL, nil)
tr.promAPIProxyHandler(w,r)

if (w.Result().StatusCode != 200) {
if w.Result().StatusCode != 200 {
t.Errorf("wanted 200 got %d.", w.Result().StatusCode)
}
}
Expand All @@ -296,9 +275,9 @@ func TestTricksterHandler_promQueryHandler(t *testing.T) {
// it should proxy request
w := httptest.NewRecorder()
r := httptest.NewRequest("GET", es.URL, nil)
tr.promQueryHandler(w,r)
tr.promQueryHandler(w, r)

if (w.Result().StatusCode != 200) {
if w.Result().StatusCode != 200 {
t.Errorf("wanted 200 got %d.", w.Result().StatusCode)
}
}
Expand All @@ -312,10 +291,10 @@ func TestTricksterHandler_promQueryRangeHandler_cacheMiss(t *testing.T) {

// it should queue the proxy request
w := httptest.NewRecorder()
r := httptest.NewRequest("GET", es.URL + exampleRangeQuery, nil)
tr.promQueryRangeHandler(w,r)
r := httptest.NewRequest("GET", es.URL+exampleRangeQuery, nil)
tr.promQueryRangeHandler(w, r)

if (w.Result().StatusCode != 200) {
if w.Result().StatusCode != 200 {
t.Errorf("wanted 200 got %d.", w.Result().StatusCode)
}
}
Expand All @@ -328,35 +307,35 @@ func TestTricksterHandler_promQueryRangeHandler_cacheHit(t *testing.T) {
tr.setTestOrigin(es.URL)

// setup cache
r := httptest.NewRequest("GET", es.URL + exampleRangeQuery, nil)
tr.fetchPromQuery(es.URL + prometheusAPIv1Path + exampleRangeQuery_step, r.URL.Query(), r)
r := httptest.NewRequest("GET", es.URL+exampleRangeQuery, nil)
tr.fetchPromQuery(es.URL+prometheusAPIv1Path+exampleRangeQuery_step, r.URL.Query(), r)

// it should respond from cache
w := httptest.NewRecorder()
r = httptest.NewRequest("GET", es.URL + exampleRangeQuery, nil)
tr.promQueryRangeHandler(w,r)
r = httptest.NewRequest("GET", es.URL+exampleRangeQuery, nil)
tr.promQueryRangeHandler(w, r)

resp := w.Result()
defer resp.Body.Close()

if (resp.StatusCode != 200) {
if resp.StatusCode != 200 {
t.Errorf("wanted 200. got %d.", resp.StatusCode)
}

bodyBytes, err := ioutil.ReadAll(resp.Body)
if (err != nil) {
if err != nil {
t.Error(err)
}

fmt.Println(string(bodyBytes))

pm := PrometheusMatrixEnvelope{}
err = json.Unmarshal(bodyBytes, &pm)
if (err != nil) {
if err != nil {
t.Error(err)
}

if (pm.getValueCount() != 6) {
if pm.getValueCount() != 6 {
t.Errorf("wanted 6 got %d.", pm.getValueCount())
}
}
Expand All @@ -370,11 +349,11 @@ func TestTricksterHandler_getURL(t *testing.T) {
tr.setTestOrigin(es.URL)

// it should get from the echo server
b,_,_,err := tr.getURL("GET", es.URL, url.Values{}, nil)
if (err != nil) {
b, _, _, err := tr.getURL("GET", es.URL, url.Values{}, nil)
if err != nil {
t.Error(err)
}
if (bytes.Compare(b,[]byte(body)) != 0) {
if bytes.Compare(b, []byte(body)) != 0 {
t.Errorf("wanted \"%s\" got \"%s\"", body, b)
}
}
Expand All @@ -387,12 +366,12 @@ func TestTricksterHandler_getVectorFromPrometheus(t *testing.T) {
tr.setTestOrigin(es.URL)

// it should get an empty vector envelope
r := httptest.NewRequest("GET", es.URL + exampleQuery, nil)
pe,_,err := tr.getVectorFromPrometheus(es.URL, r.URL.Query(), r)
if (err != nil) {
r := httptest.NewRequest("GET", es.URL+exampleQuery, nil)
pe, _, err := tr.getVectorFromPrometheus(es.URL, r.URL.Query(), r)
if err != nil {
t.Error(err)
}
if (pe.Status != "success") {
if pe.Status != "success" {
t.Errorf("wanted \"success\" got \"%s\".", pe.Status)
}
}
Expand All @@ -405,12 +384,12 @@ func TestTricksterHandler_getMatrixFromPrometheus(t *testing.T) {
tr.setTestOrigin(es.URL)

// it should get an empty matrix envelope
r := httptest.NewRequest("GET", es.URL + exampleRangeQuery, nil)
pe,_,_,err := tr.getMatrixFromPrometheus(es.URL, r.URL.Query(), r)
if (err != nil) {
r := httptest.NewRequest("GET", es.URL+exampleRangeQuery, nil)
pe, _, _, err := tr.getMatrixFromPrometheus(es.URL, r.URL.Query(), r)
if err != nil {
t.Error(err)
}
if (pe.Status != "success") {
if pe.Status != "success" {
t.Errorf("wanted \"success\" got \"%s\".", pe.Status)
}
}
Expand All @@ -420,9 +399,9 @@ func TestTricksterHandler_respondToCacheHit(t *testing.T) {
defer closeTr(t)

w := httptest.NewRecorder()
r := httptest.NewRequest("GET", nonexistantOrigin + exampleRangeQuery, nil)
ctx,err := tr.buildRequestContext(w, r)
if (err != nil) {
r := httptest.NewRequest("GET", nonexistantOrigin+exampleRangeQuery, nil)
ctx, err := tr.buildRequestContext(w, r)
if err != nil {
t.Error(err)
}

Expand All @@ -431,16 +410,15 @@ func TestTricksterHandler_respondToCacheHit(t *testing.T) {
tr.respondToCacheHit(ctx)
}


func TestPrometheusMatrixEnvelope_getValueCount(t *testing.T) {
pm := PrometheusMatrixEnvelope{}
err := json.Unmarshal([]byte(exampleRangeResponse), &pm)
if (err != nil) {
if err != nil {
t.Error(err)
}

// it should count the values in the matrix
if (6 != pm.getValueCount()) {
if 6 != pm.getValueCount() {
t.Errorf("wanted 6 got %d.", pm.getValueCount())
}
}
Expand All @@ -451,20 +429,20 @@ func TestTricksterHandler_mergeVector(t *testing.T) {

pm := PrometheusMatrixEnvelope{}
err := json.Unmarshal([]byte(exampleRangeResponse), &pm)
if (err != nil) {
if err != nil {
t.Error(err)
}

pv := PrometheusVectorEnvelope{}
err = json.Unmarshal([]byte(exampleResponse), &pv)
if (err != nil) {
if err != nil {
t.Error(err)
}

// it should merge the values from the vector into the matrix
pe := tr.mergeVector(pm, pv)

if (8 != pe.getValueCount()) {
if 8 != pe.getValueCount() {
t.Errorf("wanted 8 got %d.", pe.getValueCount())
}
}
}
6 changes: 3 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (

const (
applicationName = "trickster"
applicationVersion = "0.0.13"
applicationVersion = "0.0.15"

// Log fields
lfEvent = "event"
Expand Down Expand Up @@ -81,11 +81,11 @@ func main() {
// Path-based multi-origin support - no support for full proxy of the prometheus UI, only querying
router.HandleFunc("/{originMoniker}"+prometheusAPIv1Path+mnQueryRange, t.promQueryRangeHandler).Methods("GET")
router.HandleFunc("/{originMoniker}"+prometheusAPIv1Path+mnQuery, t.promQueryHandler).Methods("GET")
router.PathPrefix("/{originMoniker}" + prometheusAPIv1Path).HandlerFunc(t.promAPIProxyHandler).Methods("GET")
router.PathPrefix("/{originMoniker}" + prometheusAPIv1Path).HandlerFunc(t.promFullProxyHandler).Methods("GET")

router.HandleFunc(prometheusAPIv1Path+mnQueryRange, t.promQueryRangeHandler).Methods("GET")
router.HandleFunc(prometheusAPIv1Path+mnQuery, t.promQueryHandler).Methods("GET")
router.PathPrefix(prometheusAPIv1Path).HandlerFunc(t.promAPIProxyHandler).Methods("GET")
router.PathPrefix(prometheusAPIv1Path).HandlerFunc(t.promFullProxyHandler).Methods("GET")

// Catch All for Single-Origin proxy
router.PathPrefix("/").HandlerFunc(t.promFullProxyHandler).Methods("GET")
Expand Down

0 comments on commit b7131e0

Please sign in to comment.