Skip to content

Commit

Permalink
Restrict history and analytics to logs
Browse files Browse the repository at this point in the history
Only log history and analytics actions, don't put them in a journal. It
looks strange when every time you run `whistory` it adds a new entry to
`whistory`.

Fixes puppetlabs-toy-chest#652.

Signed-off-by: Michael Smith <[email protected]>
  • Loading branch information
MikaelSmith committed Dec 10, 2019
1 parent 228eba5 commit 596ed79
Show file tree
Hide file tree
Showing 13 changed files with 49 additions and 44 deletions.
4 changes: 2 additions & 2 deletions api/analytics.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
// Responses:
// 200:
// 404: errorResp
var screenviewHandler handler = func(w http.ResponseWriter, r *http.Request) *errorResponse {
var screenviewHandler = handler{logOnly: true, fn: func(w http.ResponseWriter, r *http.Request) *errorResponse {
var body apitypes.ScreenviewBody
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
return badRequestResponse(fmt.Sprintf("Error unmarshalling the request body: %v", err))
Expand All @@ -37,4 +37,4 @@ var screenviewHandler handler = func(w http.ResponseWriter, r *http.Request) *er
return badRequestResponse(err.Error())
}
return nil
}
}}
4 changes: 2 additions & 2 deletions api/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
// Responses:
// 200:
// 500: errorResp
var cacheHandler handler = func(w http.ResponseWriter, r *http.Request) *errorResponse {
var cacheHandler = handler{fn: func(w http.ResponseWriter, r *http.Request) *errorResponse {
path, errResp := getWashPathFromRequest(r)
if errResp != nil {
return errResp
Expand All @@ -37,4 +37,4 @@ var cacheHandler handler = func(w http.ResponseWriter, r *http.Request) *errorRe
return unknownErrorResponse(fmt.Errorf("Could not marshal deleted keys for %v: %v", path, err))
}
return nil
}
}}
4 changes: 2 additions & 2 deletions api/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
// 400: errorResp
// 404: errorResp
// 500: errorResp
var deleteHandler handler = func(w http.ResponseWriter, r *http.Request) *errorResponse {
var deleteHandler = handler{fn: func(w http.ResponseWriter, r *http.Request) *errorResponse {
ctx := r.Context()
entry, path, errResp := getEntryFromRequest(r)
if errResp != nil {
Expand All @@ -42,4 +42,4 @@ var deleteHandler handler = func(w http.ResponseWriter, r *http.Request) *errorR
return unknownErrorResponse(fmt.Errorf("Could not marshal delete's result for %v: %v", path, err))
}
return nil
}
}}
4 changes: 2 additions & 2 deletions api/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ type execResponse struct {
// 400: errorResp
// 404: errorResp
// 500: errorResp
var execHandler handler = func(w http.ResponseWriter, r *http.Request) *errorResponse {
var execHandler = handler{fn: func(w http.ResponseWriter, r *http.Request) *errorResponse {
ctx := r.Context()
entry, path, errResp := getEntryFromRequest(r)
if errResp != nil {
Expand Down Expand Up @@ -123,4 +123,4 @@ var execHandler handler = func(w http.ResponseWriter, r *http.Request) *errorRes
sendPacket(ctx, enc, &packet)

return nil
}
}}
17 changes: 11 additions & 6 deletions api/history.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/gorilla/mux"
"github.com/puppetlabs/wash/activity"
apitypes "github.com/puppetlabs/wash/api/types"
log "github.com/sirupsen/logrus"
)

// swagger:parameters retrieveHistory getJournal
Expand Down Expand Up @@ -39,7 +40,7 @@ type historyParams struct {
// 400: errorResp
// 404: errorResp
// 500: errorResp
var historyHandler handler = func(w http.ResponseWriter, r *http.Request) *errorResponse {
var historyHandler = handler{logOnly: true, fn: func(w http.ResponseWriter, r *http.Request) *errorResponse {
follow, err := getBoolParam(r.URL, "follow")
if err != nil {
return err
Expand Down Expand Up @@ -83,7 +84,7 @@ var historyHandler handler = func(w http.ResponseWriter, r *http.Request) *error
}
}
return nil
}
}}

func writeHistory(ctx context.Context, enc *json.Encoder, history []activity.Journal) *errorResponse {
var act apitypes.Activity
Expand Down Expand Up @@ -115,7 +116,7 @@ func writeHistory(ctx context.Context, enc *json.Encoder, history []activity.Jou
// 400: errorResp
// 404: errorResp
// 500: errorResp
var historyEntryHandler handler = func(w http.ResponseWriter, r *http.Request) *errorResponse {
var historyEntryHandler = handler{logOnly: true, fn: func(w http.ResponseWriter, r *http.Request) *errorResponse {
history := activity.History()
index := mux.Vars(r)["index"]

Expand All @@ -133,6 +134,10 @@ var historyEntryHandler handler = func(w http.ResponseWriter, r *http.Request) *
}

journal := history[idx]
streamCleanup := func(cleanup func() error) {
<-r.Context().Done()
log.Printf("API: Journal %v closed by completed context: %v", journal, cleanup())
}

if follow {
// Ensure every write is a flush.
Expand All @@ -147,7 +152,7 @@ var historyEntryHandler handler = func(w http.ResponseWriter, r *http.Request) *
}

// Ensure the reader is closed when context stops.
streamCleanup(r.Context(), "Journal "+journal.String(), func() error {
go streamCleanup(func() error {
rdr.Cleanup()
return rdr.Stop()
})
Expand All @@ -172,11 +177,11 @@ var historyEntryHandler handler = func(w http.ResponseWriter, r *http.Request) *
return journalUnavailableResponse(journal.String(), err.Error())
}

streamCleanup(r.Context(), "Journal "+journal.String(), rdr.Close)
go streamCleanup(rdr.Close)

if _, err := io.Copy(w, rdr); err != nil {
return unknownErrorResponse(fmt.Errorf("Could not read journal %v: %v", journal, err))
}
}
return nil
}
}}
4 changes: 2 additions & 2 deletions api/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
// 400: errorResp
// 404: errorResp
// 500: errorResp
var infoHandler handler = func(w http.ResponseWriter, r *http.Request) *errorResponse {
var infoHandler = handler{fn: func(w http.ResponseWriter, r *http.Request) *errorResponse {
entry, path, errResp := getEntryFromRequest(r)
if errResp != nil {
return errResp
Expand All @@ -36,4 +36,4 @@ var infoHandler handler = func(w http.ResponseWriter, r *http.Request) *errorRes
return unknownErrorResponse(fmt.Errorf("Could not marshal %v: %v", path, err))
}
return nil
}
}}
4 changes: 2 additions & 2 deletions api/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type entryList struct {
// 400: errorResp
// 404: errorResp
// 500: errorResp
var listHandler handler = func(w http.ResponseWriter, r *http.Request) *errorResponse {
var listHandler = handler{fn: func(w http.ResponseWriter, r *http.Request) *errorResponse {
ctx := r.Context()
entry, path, errResp := getEntryFromRequest(r)
if errResp != nil {
Expand Down Expand Up @@ -71,4 +71,4 @@ var listHandler handler = func(w http.ResponseWriter, r *http.Request) *errorRes
return unknownErrorResponse(fmt.Errorf("Could not marshal list results for %v: %v", path, err))
}
return nil
}
}}
4 changes: 2 additions & 2 deletions api/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type entryMetadata struct {
// 200: entryMetadata
// 404: errorResp
// 500: errorResp
var metadataHandler handler = func(w http.ResponseWriter, r *http.Request) *errorResponse {
var metadataHandler = handler{fn: func(w http.ResponseWriter, r *http.Request) *errorResponse {
ctx := r.Context()
entry, path, errResp := getEntryFromRequest(r)
if errResp != nil {
Expand All @@ -49,4 +49,4 @@ var metadataHandler handler = func(w http.ResponseWriter, r *http.Request) *erro
return unknownErrorResponse(fmt.Errorf("Could not marshal metadata for %v: %v", path, err))
}
return nil
}
}}
4 changes: 2 additions & 2 deletions api/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type schemaResponse struct {
// 400: errorResp
// 404: errorResp
// 500: errorResp
var schemaHandler handler = func(w http.ResponseWriter, r *http.Request) *errorResponse {
var schemaHandler = handler{fn: func(w http.ResponseWriter, r *http.Request) *errorResponse {
entry, path, errResp := getEntryFromRequest(r)
if errResp != nil {
return errResp
Expand All @@ -48,4 +48,4 @@ var schemaHandler handler = func(w http.ResponseWriter, r *http.Request) *errorR
return unknownErrorResponse(fmt.Errorf("Could not marshal schema for %v: %v", path, err))
}
return nil
}
}}
19 changes: 14 additions & 5 deletions api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,22 @@ type octetResponse struct {
Reader io.Reader
}

type handler func(http.ResponseWriter, *http.Request) *errorResponse
type handler struct {
fn func(http.ResponseWriter, *http.Request) *errorResponse
logOnly bool
}

func (handle handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
activity.Record(r.Context(), "API: %v %v", r.Method, r.URL)
var record func(msg string, a ...interface{})
if handle.logOnly {
record = log.Printf
} else {
record = func(msg string, a ...interface{}) { activity.Record(r.Context(), msg, a...) }
}
record("API: %v %v", r.Method, r.URL)

if err := handle(w, r); err != nil {
activity.Record(r.Context(), "API: %v %v: %v", r.Method, r.URL, err)
if err := handle.fn(w, r); err != nil {
record("API: %v %v: %v", r.Method, r.URL, err)
w.WriteHeader(err.statusCode)

// NOTE: Do not set these headers in the middleware because not
Expand All @@ -60,7 +69,7 @@ func (handle handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
log.Warnf("API: Failed writing error response: %v", err)
}
} else {
activity.Record(r.Context(), "API: %v %v complete", r.Method, r.URL)
record("API: %v %v complete", r.Method, r.URL)
}
}

Expand Down
4 changes: 2 additions & 2 deletions api/signal.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (
// 400: errorResp
// 404: errorResp
// 500: errorResp
var signalHandler handler = func(w http.ResponseWriter, r *http.Request) *errorResponse {
var signalHandler = handler{fn: func(w http.ResponseWriter, r *http.Request) *errorResponse {
ctx := r.Context()
entry, path, errResp := getEntryFromRequest(r)
if errResp != nil {
Expand Down Expand Up @@ -55,4 +55,4 @@ var signalHandler handler = func(w http.ResponseWriter, r *http.Request) *errorR

activity.Record(ctx, "API: Signal %v %v", path, body.Signal)
return nil
}
}}
9 changes: 6 additions & 3 deletions api/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
// 200: octetResponse
// 404: errorResp
// 500: errorResp
var streamHandler handler = func(w http.ResponseWriter, r *http.Request) *errorResponse {
var streamHandler = handler{fn: func(w http.ResponseWriter, r *http.Request) *errorResponse {
entry, path, errResp := getEntryFromRequest(r)
if errResp != nil {
return errResp
Expand Down Expand Up @@ -53,12 +53,15 @@ var streamHandler handler = func(w http.ResponseWriter, r *http.Request) *errorR
f.Flush()

// Ensure it's closed when the context is cancelled.
streamCleanup(ctx, "Stream "+path, rdr.Close)
go func() {
<-ctx.Done()
activity.Record(ctx, "API: Stream %v closed by completed context: %v", path, rdr.Close())
}()

// Ensure every write is a flush with streamableResponseWriter.
if _, err := io.Copy(&streamableResponseWriter{f}, rdr); err != nil {
// Common for copy to error when the caller closes the connection.
activity.Record(ctx, "API: Streaming %v errored: %v", path, err)
}
return nil
}
}}
12 changes: 0 additions & 12 deletions api/streamableResponseWriter.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package api

import (
"context"
"io"
"net/http"

"github.com/puppetlabs/wash/activity"
)

// Inspired by Docker's WriteFlusher: https://github.com/moby/moby/blob/17.05.x/pkg/ioutils/writeflusher.go
Expand All @@ -23,12 +20,3 @@ func (wf *streamableResponseWriter) Write(b []byte) (n int, err error) {
wf.Flush()
return n, err
}

type cleanupFunc = func() error

func streamCleanup(ctx context.Context, desc string, cleanup cleanupFunc) {
go func() {
<-ctx.Done()
activity.Record(ctx, "API: %v closed by completed context: %v", desc, cleanup())
}()
}

0 comments on commit 596ed79

Please sign in to comment.