OpenTracing for Fission (#1079)
Added Opentracing integration using opencensus libraries for all Fission components.
This commit is contained in:
@@ -2,6 +2,7 @@ package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
@@ -9,18 +10,25 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go.opencensus.io/plugin/ochttp"
|
||||
"golang.org/x/net/context/ctxhttp"
|
||||
|
||||
"github.com/fission/fission"
|
||||
)
|
||||
|
||||
type (
|
||||
Client struct {
|
||||
url string
|
||||
url string
|
||||
httpClient *http.Client
|
||||
}
|
||||
)
|
||||
|
||||
func MakeClient(fetcherUrl string) *Client {
|
||||
return &Client{
|
||||
url: strings.TrimSuffix(fetcherUrl, "/"),
|
||||
httpClient: &http.Client{
|
||||
Transport: &ochttp.Transport{},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,18 +44,18 @@ func (c *Client) getUploadUrl() string {
|
||||
return c.url + "/upload"
|
||||
}
|
||||
|
||||
func (c *Client) Specialize(req *fission.FunctionSpecializeRequest) error {
|
||||
_, err := sendRequest(req, c.getSpecializeUrl())
|
||||
func (c *Client) Specialize(ctx context.Context, req *fission.FunctionSpecializeRequest) error {
|
||||
_, err := sendRequest(ctx, c.httpClient, req, c.getSpecializeUrl())
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) Fetch(fr *fission.FunctionFetchRequest) error {
|
||||
_, err := sendRequest(fr, c.getFetchUrl())
|
||||
func (c *Client) Fetch(ctx context.Context, fr *fission.FunctionFetchRequest) error {
|
||||
_, err := sendRequest(ctx, c.httpClient, fr, c.getFetchUrl())
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) Upload(fr *fission.ArchiveUploadRequest) (*fission.ArchiveUploadResponse, error) {
|
||||
body, err := sendRequest(fr, c.getUploadUrl())
|
||||
func (c *Client) Upload(ctx context.Context, fr *fission.ArchiveUploadRequest) (*fission.ArchiveUploadResponse, error) {
|
||||
body, err := sendRequest(ctx, c.httpClient, fr, c.getUploadUrl())
|
||||
|
||||
uploadResp := fission.ArchiveUploadResponse{}
|
||||
err = json.Unmarshal(body, &uploadResp)
|
||||
@@ -58,7 +66,7 @@ func (c *Client) Upload(fr *fission.ArchiveUploadRequest) (*fission.ArchiveUploa
|
||||
return &uploadResp, nil
|
||||
}
|
||||
|
||||
func sendRequest(req interface{}, url string) ([]byte, error) {
|
||||
func sendRequest(ctx context.Context, httpClient *http.Client, req interface{}, url string) ([]byte, error) {
|
||||
body, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -68,7 +76,7 @@ func sendRequest(req interface{}, url string) ([]byte, error) {
|
||||
var resp *http.Response
|
||||
|
||||
for i := 0; i < maxRetries; i++ {
|
||||
resp, err = http.Post(url, "application/json", bytes.NewReader(body))
|
||||
resp, err = ctxhttp.Post(ctx, httpClient, url, "application/json", bytes.NewReader(body))
|
||||
|
||||
if err == nil {
|
||||
if resp.StatusCode == 200 {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
@@ -11,6 +12,10 @@ import (
|
||||
"runtime/debug"
|
||||
"syscall"
|
||||
|
||||
"go.opencensus.io/exporter/jaeger"
|
||||
"go.opencensus.io/plugin/ochttp"
|
||||
"go.opencensus.io/trace"
|
||||
|
||||
"github.com/fission/fission"
|
||||
"github.com/fission/fission/environments/fetcher"
|
||||
)
|
||||
@@ -19,6 +24,29 @@ func dumpStackTrace() {
|
||||
debug.PrintStack()
|
||||
}
|
||||
|
||||
func registerTraceExporter(collectorEndpoint string) error {
|
||||
if collectorEndpoint == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
serviceName := "Fission-Fetcher"
|
||||
exporter, err := jaeger.NewExporter(jaeger.Options{
|
||||
CollectorEndpoint: collectorEndpoint,
|
||||
Process: jaeger.Process{
|
||||
ServiceName: serviceName,
|
||||
Tags: []jaeger.Tag{
|
||||
jaeger.BoolTag("fission", true),
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
trace.RegisterExporter(exporter)
|
||||
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Usage: fetcher <shared volume path>
|
||||
func main() {
|
||||
// register signal handler for dumping stack trace.
|
||||
@@ -32,6 +60,7 @@ func main() {
|
||||
}()
|
||||
|
||||
flag.Usage = fetcherUsage
|
||||
collectorEndpoint := flag.String("jaeger-collector-endpoint", "", "")
|
||||
specializeOnStart := flag.Bool("specialize-on-startup", false, "Flag to activate specialize process at pod starup")
|
||||
specializePayload := flag.String("specialize-request", "", "JSON payload for specialize request")
|
||||
secretDir := flag.String("secret-dir", "", "Path to shared secrets directory")
|
||||
@@ -53,6 +82,10 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
if err := registerTraceExporter(*collectorEndpoint); err != nil {
|
||||
log.Fatalf("Could not register trace exporter: %v", err)
|
||||
}
|
||||
|
||||
f, err := fetcher.MakeFetcher(dir, *secretDir, *configDir)
|
||||
if err != nil {
|
||||
log.Fatalf("Error making fetcher: %v", err)
|
||||
@@ -70,7 +103,8 @@ func main() {
|
||||
log.Fatalf("Error decoding specialize request: %v", err)
|
||||
}
|
||||
|
||||
err = f.SpecializePod(specializeReq.FetchReq, specializeReq.LoadReq)
|
||||
ctx := context.Background()
|
||||
err = f.SpecializePod(ctx, specializeReq.FetchReq, specializeReq.LoadReq)
|
||||
if err != nil {
|
||||
log.Fatalf("Error specialing function poadt: %v", err)
|
||||
}
|
||||
@@ -96,7 +130,9 @@ func main() {
|
||||
})
|
||||
|
||||
log.Println("Fetcher ready to receive requests")
|
||||
http.ListenAndServe(":8000", mux)
|
||||
http.ListenAndServe(":8000", &ochttp.Handler{
|
||||
Handler: mux,
|
||||
})
|
||||
}
|
||||
|
||||
func fetcherUsage() {
|
||||
|
||||
@@ -2,6 +2,7 @@ package fetcher
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
@@ -18,7 +19,9 @@ import (
|
||||
|
||||
"github.com/mholt/archiver"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/satori/go.uuid"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"go.opencensus.io/plugin/ochttp"
|
||||
"golang.org/x/net/context/ctxhttp"
|
||||
k8serr "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
@@ -35,6 +38,7 @@ type (
|
||||
sharedConfigPath string
|
||||
fissionClient *crd.FissionClient
|
||||
kubeClient *kubernetes.Clientset
|
||||
httpClient *http.Client
|
||||
}
|
||||
)
|
||||
|
||||
@@ -60,11 +64,14 @@ func MakeFetcher(sharedVolumePath string, sharedSecretPath string, sharedConfigP
|
||||
sharedConfigPath: sharedConfigPath,
|
||||
fissionClient: fissionClient,
|
||||
kubeClient: kubeClient,
|
||||
httpClient: &http.Client{
|
||||
Transport: &ochttp.Transport{},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func downloadUrl(url string, localPath string) error {
|
||||
resp, err := http.Get(url)
|
||||
func downloadUrl(ctx context.Context, httpClient *http.Client, url string, localPath string) error {
|
||||
resp, err := ctxhttp.Get(ctx, httpClient, url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -116,15 +123,11 @@ func getChecksum(path string) (*fission.Checksum, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func verifyChecksum(path string, checksum *fission.Checksum) error {
|
||||
func verifyChecksum(fileChecksum, checksum *fission.Checksum) error {
|
||||
if checksum.Type != fission.ChecksumTypeSHA256 {
|
||||
return fission.MakeError(fission.ErrorInvalidArgument, "Unsupported checksum type")
|
||||
}
|
||||
c, err := getChecksum(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c.Sum != checksum.Sum {
|
||||
if fileChecksum.Sum != checksum.Sum {
|
||||
return fission.MakeError(fission.ErrorChecksumFail, "Checksum validation failed")
|
||||
}
|
||||
return nil
|
||||
@@ -175,8 +178,7 @@ func (fetcher *Fetcher) FetchHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("fetcher received fetch request and started downloading: %v", req)
|
||||
code, err := fetcher.Fetch(req)
|
||||
code, err := fetcher.Fetch(r.Context(), req)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), code)
|
||||
return
|
||||
@@ -217,7 +219,7 @@ func (fetcher *Fetcher) SpecializeHandler(w http.ResponseWriter, r *http.Request
|
||||
|
||||
//log.Printf("fetcher received fetch request and started downloading: %v", req)
|
||||
|
||||
err = fetcher.SpecializePod(req.FetchReq, req.LoadReq)
|
||||
err = fetcher.SpecializePod(r.Context(), req.FetchReq, req.LoadReq)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
@@ -229,7 +231,7 @@ func (fetcher *Fetcher) SpecializeHandler(w http.ResponseWriter, r *http.Request
|
||||
|
||||
// Fetch takes FetchRequest and makes the fetch call
|
||||
// It returns the HTTP code and error if any
|
||||
func (fetcher *Fetcher) Fetch(req fission.FunctionFetchRequest) (int, error) {
|
||||
func (fetcher *Fetcher) Fetch(ctx context.Context, req fission.FunctionFetchRequest) (int, error) {
|
||||
// check that the requested filename is not an empty string and error out if so
|
||||
if len(req.Filename) == 0 {
|
||||
e := fmt.Sprintf("Fetch request received for an empty file name, request: %v", req)
|
||||
@@ -248,7 +250,7 @@ func (fetcher *Fetcher) Fetch(req fission.FunctionFetchRequest) (int, error) {
|
||||
|
||||
if req.FetchType == fission.FETCH_URL {
|
||||
// fetch the file and save it to the tmp path
|
||||
err := downloadUrl(req.Url, tmpPath)
|
||||
err := downloadUrl(ctx, fetcher.httpClient, req.Url, tmpPath)
|
||||
if err != nil {
|
||||
e := fmt.Sprintf("Failed to download url %v: %v", req.Url, err)
|
||||
log.Printf(e)
|
||||
@@ -289,14 +291,21 @@ func (fetcher *Fetcher) Fetch(req fission.FunctionFetchRequest) (int, error) {
|
||||
}
|
||||
} else {
|
||||
// download and verify
|
||||
err = downloadUrl(archive.URL, tmpPath)
|
||||
err := downloadUrl(ctx, fetcher.httpClient, archive.URL, tmpPath)
|
||||
if err != nil {
|
||||
e := fmt.Sprintf("Failed to download url %v: %v", req.Url, err)
|
||||
log.Printf(e)
|
||||
return http.StatusBadRequest, errors.New(e)
|
||||
}
|
||||
|
||||
err = verifyChecksum(tmpPath, &archive.Checksum)
|
||||
checksum, err := getChecksum(tmpPath)
|
||||
if err != nil {
|
||||
e := fmt.Sprintf("Failed to get checksum: %v", err)
|
||||
log.Printf(e)
|
||||
return http.StatusBadRequest, errors.New(e)
|
||||
}
|
||||
|
||||
err = verifyChecksum(checksum, &archive.Checksum)
|
||||
if err != nil {
|
||||
e := fmt.Sprintf("Failed to verify checksum: %v", err)
|
||||
log.Printf(e)
|
||||
@@ -454,7 +463,7 @@ func (fetcher *Fetcher) UploadHandler(w http.ResponseWriter, r *http.Request) {
|
||||
log.Println("Starting upload...")
|
||||
ssClient := storageSvcClient.MakeClient(req.StorageSvcUrl)
|
||||
|
||||
fileID, err := ssClient.Upload(dstFilepath, nil)
|
||||
fileID, err := ssClient.Upload(r.Context(), dstFilepath, nil)
|
||||
if err != nil {
|
||||
e := fmt.Sprintf("Error uploading zip file: %v", err)
|
||||
log.Println(e)
|
||||
@@ -526,14 +535,14 @@ func (fetcher *Fetcher) unarchive(src string, dst string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fetcher *Fetcher) SpecializePod(fetchReq fission.FunctionFetchRequest, loadReq fission.FunctionLoadRequest) error {
|
||||
func (fetcher *Fetcher) SpecializePod(ctx context.Context, fetchReq fission.FunctionFetchRequest, loadReq fission.FunctionLoadRequest) error {
|
||||
startTime := time.Now()
|
||||
defer func() {
|
||||
elapsed := time.Since(startTime)
|
||||
log.Printf("Elapsed time in fetch request = %v", elapsed)
|
||||
}()
|
||||
|
||||
_, err := fetcher.Fetch(fetchReq)
|
||||
_, err := fetcher.Fetch(ctx, fetchReq)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error fetching deploy package")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user