forked from prysmaticlabs/prysm
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Tracing Request Sink to E2E (prysmaticlabs#9341)
* add tracing request sink * fix struct order * add in base64 encode and gzip * add encoding and gzip * tracing sink and replay tool * post * replay * include latest sink and replay tool * capture the gzout file instead * rem time sleep * handle err * better handling * add documentation * changes * working sync * working * added more logging
- Loading branch information
1 parent
0dd7a8b
commit c128086
Showing
8 changed files
with
222 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package components | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/base64" | ||
"io" | ||
"net/http" | ||
"os" | ||
"os/signal" | ||
"syscall" | ||
|
||
"github.com/prysmaticlabs/prysm/endtoend/helpers" | ||
e2e "github.com/prysmaticlabs/prysm/endtoend/params" | ||
) | ||
|
||
// TracingSink to capture HTTP requests from opentracing pushes. This is meant | ||
// to capture all opentracing spans from Prysm during an end-to-end test. Spans | ||
// are normally sent to a jaeger (https://www.jaegertracing.io/docs/1.25/getting-started/) | ||
// endpoint, but here we instead replace that with our own http request sink. | ||
// The request sink receives any requests, raw marshals them and base64-encodes them, | ||
// then writes them newline-delimited into a file. | ||
// | ||
// The output file from this component can then be used by tools/replay-http in | ||
// the Prysm repository to replay requests to a jaeger collector endpoint. This | ||
// can then be used to visualize the spans themselves in the jaeger UI. | ||
type TracingSink struct { | ||
started chan struct{} | ||
endpoint string | ||
server *http.Server | ||
} | ||
|
||
// NewTracingSink initializes the tracing sink component. | ||
func NewTracingSink(endpoint string) *TracingSink { | ||
return &TracingSink{ | ||
started: make(chan struct{}, 1), | ||
endpoint: endpoint, | ||
} | ||
} | ||
|
||
// Start the tracing sink. | ||
func (ts *TracingSink) Start(ctx context.Context) error { | ||
go ts.initializeSink() | ||
close(ts.started) | ||
return nil | ||
} | ||
|
||
// Started checks whether a tracing sink is started and ready to be queried. | ||
func (ts *TracingSink) Started() <-chan struct{} { | ||
return ts.started | ||
} | ||
|
||
// Initialize an http handler that writes all requests to a file. | ||
func (ts *TracingSink) initializeSink() { | ||
ts.server = &http.Server{Addr: ts.endpoint} | ||
defer func() { | ||
if err := ts.server.Close(); err != nil { | ||
log.WithError(err).Error("Failed to close http server") | ||
return | ||
} | ||
}() | ||
stdOutFile, err := helpers.DeleteAndCreateFile(e2e.TestParams.LogPath, e2e.TracingRequestSinkFileName) | ||
if err != nil { | ||
log.WithError(err).Error("Failed to create stdout file") | ||
return | ||
} | ||
cleanup := func() { | ||
if err := stdOutFile.Close(); err != nil { | ||
log.WithError(err).Error("Could not close stdout file") | ||
} | ||
} | ||
|
||
http.HandleFunc("/", func(_ http.ResponseWriter, r *http.Request) { | ||
if err := captureRequest(stdOutFile, r); err != nil { | ||
log.WithError(err).Error("Failed to capture http request") | ||
return | ||
} | ||
}) | ||
sigs := make(chan os.Signal, 1) | ||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) | ||
go func() { | ||
<-sigs | ||
cleanup() | ||
os.Exit(0) | ||
}() | ||
if err := ts.server.ListenAndServe(); err != http.ErrServerClosed { | ||
log.WithError(err).Error("Failed to serve http") | ||
} | ||
} | ||
|
||
// Captures raw requests in base64 encoded form in a line-delimited file. | ||
func captureRequest(f io.Writer, r *http.Request) error { | ||
buf := bytes.NewBuffer(nil) | ||
err := r.Write(buf) | ||
if err != nil { | ||
return err | ||
} | ||
encoded := make([]byte, base64.StdEncoding.EncodedLen(len(buf.Bytes()))) | ||
base64.StdEncoding.Encode(encoded, buf.Bytes()) | ||
encoded = append(encoded, []byte("\n")...) | ||
_, err = f.Write(encoded) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
load("@io_bazel_rules_go//go:def.bzl", "go_binary") | ||
load("@prysm//tools/go:def.bzl", "go_library") | ||
|
||
go_library( | ||
name = "go_default_library", | ||
srcs = ["main.go"], | ||
importpath = "github.com/prysmaticlabs/prysm/tools/replay-http", | ||
visibility = ["//visibility:private"], | ||
deps = ["@com_github_sirupsen_logrus//:go_default_library"], | ||
) | ||
|
||
go_binary( | ||
name = "replay-http", | ||
embed = [":go_default_library"], | ||
visibility = ["//visibility:public"], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/** | ||
Tool for replaying http requests from a file of base64 encoded, line-delimited | ||
Go http raw requests. Credits to https://gist.github.com/kasey/c9e663eae5baebbf8fbe548c2b1d961b. | ||
*/ | ||
package main | ||
|
||
import ( | ||
"bufio" | ||
"bytes" | ||
"encoding/base64" | ||
"flag" | ||
"io" | ||
"net/http" | ||
"net/url" | ||
"os" | ||
"path" | ||
|
||
log "github.com/sirupsen/logrus" | ||
) | ||
|
||
var ( | ||
filePath = flag.String("file", "", "file of line-delimited, base64-encoded Go http requests") | ||
endpoint = flag.String("endpoint", "http://localhost:14268/api/traces", "host:port endpoint to make HTTP requests to") | ||
) | ||
|
||
func main() { | ||
flag.Parse() | ||
if *filePath == "" { | ||
log.Fatal("Must provide --file") | ||
} | ||
|
||
f, err := os.Open(path.Clean(*filePath)) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
defer func() { | ||
if err := f.Close(); err != nil { | ||
log.WithError(err).Error("Could not close stdout file") | ||
} | ||
}() | ||
lr := bufio.NewReader(f) | ||
for { | ||
line, err := lr.ReadBytes([]byte("\n")[0]) | ||
if err == io.EOF { | ||
os.Exit(0) | ||
} | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
line = line[0 : len(line)-1] | ||
decoded := make([]byte, base64.StdEncoding.DecodedLen(len(line))) | ||
_, err = base64.StdEncoding.Decode(decoded, line) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
dbuf := bytes.NewBuffer(decoded) | ||
req, err := http.ReadRequest(bufio.NewReader(dbuf)) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
parsed, err := url.Parse(*endpoint) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
req.URL = parsed | ||
req.RequestURI = "" | ||
log.Println(req) | ||
resp, err := http.DefaultClient.Do(req) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
respBuf := bytes.NewBuffer(nil) | ||
if err := resp.Write(respBuf); err != nil { | ||
log.Fatal(err) | ||
} | ||
log.Println(respBuf.String()) | ||
} | ||
} |