Add gzip response compression; Update to latest version

Add a test to ensure this keeps working!
This commit is contained in:
Evan Jones 2020-06-02 14:59:11 -04:00
parent 54eef48143
commit aa0a1a2e87
6 changed files with 479 additions and 21 deletions

View File

@ -1,17 +1,15 @@
FROM golang:1.14.2-buster AS builder
COPY go.mod go.sum pprofweb.go /go/src/pprofweb/
WORKDIR /go/src/pprofweb
RUN go build --mod=readonly pprofweb.go
# Extract graphviz and dependencies
FROM golang:1.14.2-buster AS deb_extractor
FROM golang:1.14.3-buster AS deb_extractor
RUN cd /tmp && \
apt-get update && apt-get download \
graphviz libgvc6 libcgraph6 libltdl7 libxdot4 libcdt5 libpathplan4 libexpat1 zlib1g && \
mkdir /dpkg && \
for deb in *.deb; do dpkg --extract $deb /dpkg || exit 10; done
FROM golang:1.14.3-buster AS builder
COPY go.mod go.sum pprofweb.go /go/src/pprofweb/
WORKDIR /go/src/pprofweb
RUN go build --mod=readonly pprofweb.go
FROM gcr.io/distroless/base-debian10:latest AS run
COPY --from=builder /go/src/pprofweb/pprofweb /pprofweb

View File

@ -1,5 +1,7 @@
# build with:
# gcloud builds submit . --substitutions=SHORT_SHA=$(git rev-parse --short=10 HEAD)
steps:
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '--tag=us.gcr.io/$PROJECT_ID/pprofweb', '.']
args: ['build', '--tag=us.gcr.io/$PROJECT_ID/pprofweb:$SHORT_SHA', '.']
images:
- 'us.gcr.io/$PROJECT_ID/pprofweb'
- 'us.gcr.io/$PROJECT_ID/pprofweb:$SHORT_SHA'

8
go.mod
View File

@ -2,4 +2,10 @@ module github.com/evanj/pprofweb
go 1.13
require github.com/google/pprof v0.0.0-20200407193738-d6d2dc122c20
require (
github.com/NYTimes/gziphandler v1.1.1
// commit 427632fa3b1c fails as user nobody:
// https://github.com/google/pprof/pull/542
github.com/google/pprof v0.0.0-20200504201735-160c4290d1d8
github.com/ianlancetaylor/demangle v0.0.0-20200524003926-2c5affb30a03 // indirect
)

15
go.sum
View File

@ -1,10 +1,21 @@
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/google/pprof v0.0.0-20200407193738-d6d2dc122c20 h1:ckvXA2EKYK4RORZWjE+V7VrWRBLYeQHe4J4pmoMLgT0=
github.com/google/pprof v0.0.0-20200407193738-d6d2dc122c20/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/pprof v0.0.0-20200504201735-160c4290d1d8 h1:ZgqXCvT0BTD13IbwObhtnwUMzfgA+/MTn7dhqb9x9EI=
github.com/google/pprof v0.0.0-20200504201735-160c4290d1d8/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6 h1:UDMh68UUwekSh5iP2OMhRRZJiiBccgV7axzUG8vi56c=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200524003926-2c5affb30a03 h1:FjiybxAA4IL7VWbzhdskUDIXM2yIyE+/PRchayObTC4=
github.com/ianlancetaylor/demangle v0.0.0-20200524003926-2c5affb30a03/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e h1:9vRrk9YW2BTzLP0VCB9ZDjU4cPqkg+IDWL7XgxA1yxQ=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -8,8 +8,10 @@ import (
"net/http/pprof"
"os"
"path"
"path/filepath"
"strings"
"github.com/NYTimes/gziphandler"
"github.com/google/pprof/driver"
)
@ -17,19 +19,21 @@ const portEnvVar = "PORT"
const defaultPort = "8080"
const maxUploadSize = 32 << 20 // 32 MiB
const pprofFilePath = "/tmp/pprofweb-temp"
const fileFormID = "file"
const uploadPath = "/upload"
const pprofWebPath = "/pprofweb/"
// use the system-specified temporary directory
// TODO: do something smarter with a real temporary directory
var pprofFilePath = filepath.Join(os.TempDir(), "pprofweb-temp")
type server struct {
// serves pprof handlers after it is loaded
pprofMux *http.ServeMux
pprofMux http.Handler
}
func (s *server) startHTTP(args *driver.HTTPServerArgs) error {
s.pprofMux = http.NewServeMux()
mux := http.NewServeMux()
for pattern, handler := range args.Handlers {
var joinedPattern string
if pattern == "/" {
@ -37,8 +41,12 @@ func (s *server) startHTTP(args *driver.HTTPServerArgs) error {
} else {
joinedPattern = path.Join(pprofWebPath, pattern)
}
s.pprofMux.Handle(joinedPattern, handler)
mux.Handle(joinedPattern, handler)
}
// enable gzip compression: flamegraphs can be big!
s.pprofMux = gziphandler.GzipHandler(mux)
return nil
}
@ -72,6 +80,7 @@ func (s *server) uploadHandlerErrHandler(w http.ResponseWriter, r *http.Request)
}
err := s.uploadHandler(w, r)
if err != nil {
log.Printf("upload error: %s", err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
@ -121,9 +130,8 @@ func (s *server) uploadHandler(w http.ResponseWriter, r *http.Request) error {
return nil
}
func main() {
s := &server{}
// handler returns a handler that servers the pprof web UI.
func (s *server) handler() *http.ServeMux {
mux := http.NewServeMux()
mux.HandleFunc("/", rootHandler)
mux.HandleFunc(uploadPath, s.uploadHandlerErrHandler)
@ -135,6 +143,12 @@ func main() {
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
return mux
}
func main() {
s := &server{}
handler := s.handler()
port := os.Getenv(portEnvVar)
if port == "" {
@ -144,7 +158,7 @@ func main() {
addr := ":" + port
log.Printf("listen addr %s (http://localhost:%s/)", addr, port)
if err := http.ListenAndServe(addr, mux); err != nil {
if err := http.ListenAndServe(addr, handler); err != nil {
panic(err)
}
}

427
pprofweb_test.go Normal file
View File

@ -0,0 +1,427 @@
package main
import (
"bytes"
"encoding/base64"
"mime/multipart"
"net/http"
"net/http/httptest"
"testing"
)
func TestE2E(t *testing.T) {
allocsPprof, err := base64.StdEncoding.DecodeString(b64AllocsPprof)
if err != nil {
t.Fatal(err)
}
s := &server{}
handler := s.handler()
// write the pprof request
uploadReqBody := &bytes.Buffer{}
writer := multipart.NewWriter(uploadReqBody)
part, err := writer.CreateFormFile(fileFormID, "file.pprof")
if err != nil {
t.Fatal(err)
}
_, err = part.Write(allocsPprof)
if err != nil {
t.Fatal(err)
}
err = writer.Close()
if err != nil {
t.Fatal(err)
}
// send the request!
req := httptest.NewRequest(http.MethodPost, uploadPath, uploadReqBody)
req.Header.Set("Content-Type", writer.FormDataContentType())
w := httptest.NewRecorder()
handler.ServeHTTP(w, req)
resp := w.Result()
if resp.StatusCode != http.StatusSeeOther {
t.Error("unexpected Status:", resp.Status)
}
if resp.Header.Get("Location") != pprofWebPath {
t.Error("unexpected Location header:", resp.Header.Get("Location"))
}
// load the flame graph!
req = httptest.NewRequest(http.MethodGet, pprofWebPath+"flamegraph", nil)
w = httptest.NewRecorder()
handler.ServeHTTP(w, req)
resp = w.Result()
if resp.StatusCode != http.StatusOK {
t.Error("unexpected Status:", resp.Status)
}
if resp.Header.Get("Content-Type") != "text/html" {
t.Error("unexpected Content-Type:", resp.Header.Get("Content-Type"))
}
if resp.Header.Get("Content-Encoding") != "" {
t.Error("request without Accept-Encoding: should not set Content-Encoding:",
resp.Header.Get("Content-Encoding"))
}
// Chrome sends "gzip, deflate, br"
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding
// req.Header.Set("Accept-Encoding", "deflate;q=0.1, gzip;q=1.0, *, identity, br")
req.Header.Set("Accept-Encoding", "gzip")
w = httptest.NewRecorder()
handler.ServeHTTP(w, req)
resp = w.Result()
if resp.StatusCode != http.StatusOK {
t.Error("unexpected Status:", resp.Status)
}
if resp.Header.Get("Content-Type") != "text/html" {
t.Error("unexpected Content-Type:", resp.Header.Get("Content-Type"))
}
if resp.Header.Get("Content-Encoding") != "gzip" {
t.Error("request with Accept-Encoding: should set Content-Encoding:",
resp.Header.Get("Content-Encoding"))
}
}
const b64AllocsPprof = `
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
qRlZU+ytqPjL/wsAAP//89xlkkbAAAA=
`