-
Notifications
You must be signed in to change notification settings - Fork 472
feat(proxy): Tracing prefetch api #551
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 29 commits
10f9113
ba94f3c
bba1aae
32bb846
c56651d
e480321
fceac88
299db87
c267118
ce87a86
ed5ea03
ff8f723
0441e8a
98587d6
25aac66
d432533
f2c8b22
e0847ed
8f71806
9ecc727
16ad6d1
f1c7884
2f4f623
507411f
8ae75b4
b27beb7
4aa8e3d
767ae7c
b4d9847
8bedd68
5b535ed
ce80978
45b9950
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -22,7 +22,11 @@ import ( | |||||||||||
| "github.com/uber/kraken/origin/blobclient" | ||||||||||||
| "github.com/uber/kraken/utils/httputil" | ||||||||||||
| "github.com/uber/kraken/utils/log" | ||||||||||||
| "go.uber.org/zap" | ||||||||||||
|
|
||||||||||||
| "go.opentelemetry.io/otel" | ||||||||||||
| "go.opentelemetry.io/otel/attribute" | ||||||||||||
| "go.opentelemetry.io/otel/codes" | ||||||||||||
| "go.opentelemetry.io/otel/trace" | ||||||||||||
| ) | ||||||||||||
|
|
||||||||||||
| // Constants for prefetch status. | ||||||||||||
|
|
@@ -43,6 +47,7 @@ type PrefetchHandler struct { | |||||||||||
| metrics tally.Scope | ||||||||||||
| getManifestLatency tally.Histogram | ||||||||||||
| getTagLatency tally.Histogram | ||||||||||||
| tracer trace.Tracer | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // blobInfo holds digest and size information for a blob. | ||||||||||||
|
|
@@ -53,24 +58,21 @@ type blobInfo struct { | |||||||||||
|
|
||||||||||||
| // Request and response payloads. | ||||||||||||
| type prefetchBody struct { | ||||||||||||
| Tag string `json:"tag"` | ||||||||||||
| TraceId string `json:"trace_id"` | ||||||||||||
| Tag string `json:"tag"` | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| type prefetchResponse struct { | ||||||||||||
| Tag string `json:"tag"` | ||||||||||||
| Prefetched bool `json:"prefetched"` | ||||||||||||
| Status string `json:"status"` | ||||||||||||
| Message string `json:"message"` | ||||||||||||
| TraceId string `json:"trace_id"` | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| type prefetchError struct { | ||||||||||||
| Error string `json:"error"` | ||||||||||||
| Prefetched bool `json:"prefetched"` | ||||||||||||
| Status string `json:"status"` | ||||||||||||
| Message string `json:"message"` | ||||||||||||
| TraceId string `json:"trace_id,omitempty"` | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| type TagParser interface { | ||||||||||||
|
|
@@ -121,28 +123,27 @@ func NewPrefetchHandler( | |||||||||||
| metrics: m, | ||||||||||||
| getManifestLatency: m.Histogram("download_manifest_latency", tally.MustMakeExponentialDurationBuckets(1*time.Second, 2, 12)), | ||||||||||||
| getTagLatency: m.Histogram("get_tag_latency", tally.MustMakeExponentialDurationBuckets(100*time.Millisecond, 2, 10)), | ||||||||||||
| tracer: otel.Tracer("kraken-proxy-prefetch"), | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // newPrefetchSuccessResponse constructs a successful response. | ||||||||||||
| func newPrefetchSuccessResponse(tag, msg, traceId string) *prefetchResponse { | ||||||||||||
| func newPrefetchSuccessResponse(tag, msg string) *prefetchResponse { | ||||||||||||
| return &prefetchResponse{ | ||||||||||||
| Tag: tag, | ||||||||||||
| Prefetched: true, | ||||||||||||
| Status: StatusSuccess, | ||||||||||||
| Message: msg, | ||||||||||||
| TraceId: traceId, | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // newPrefetchError constructs an error response. | ||||||||||||
| func newPrefetchError(status int, msg, traceId string) *prefetchError { | ||||||||||||
| func newPrefetchError(status int, msg string) *prefetchError { | ||||||||||||
| return &prefetchError{ | ||||||||||||
| Error: http.StatusText(status), | ||||||||||||
| Prefetched: false, | ||||||||||||
| Status: StatusFailure, | ||||||||||||
| Message: msg, | ||||||||||||
| TraceId: traceId, | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
|
|
@@ -164,16 +165,16 @@ func writeJSON(w http.ResponseWriter, status int, payload interface{}) { | |||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| func writeBadRequestError(w http.ResponseWriter, msg, traceId string) { | ||||||||||||
| writeJSON(w, http.StatusBadRequest, newPrefetchError(http.StatusBadRequest, msg, traceId)) | ||||||||||||
| func writeBadRequestError(w http.ResponseWriter, msg string) { | ||||||||||||
| writeJSON(w, http.StatusBadRequest, newPrefetchError(http.StatusBadRequest, msg)) | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| func writeInternalError(w http.ResponseWriter, msg, traceId string) { | ||||||||||||
| writeJSON(w, http.StatusInternalServerError, newPrefetchError(http.StatusInternalServerError, msg, traceId)) | ||||||||||||
| func writeInternalError(w http.ResponseWriter, msg string) { | ||||||||||||
| writeJSON(w, http.StatusInternalServerError, newPrefetchError(http.StatusInternalServerError, msg)) | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| func writePrefetchResponse(w http.ResponseWriter, tag, msg, traceId string) { | ||||||||||||
| writeJSON(w, http.StatusOK, newPrefetchSuccessResponse(tag, msg, traceId)) | ||||||||||||
| func writePrefetchResponse(w http.ResponseWriter, tag, msg string) { | ||||||||||||
| writeJSON(w, http.StatusOK, newPrefetchSuccessResponse(tag, msg)) | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // HandleV1 processes the prefetch request. | ||||||||||||
|
|
@@ -184,7 +185,7 @@ func (ph *PrefetchHandler) HandleV1(w http.ResponseWriter, r *http.Request) { | |||||||||||
| } | ||||||||||||
|
|
||||||||||||
| ph.metrics.Counter("initiated").Inc(1) | ||||||||||||
| writePrefetchResponse(w, input.tag, "prefetching initiated successfully", input.traceID) | ||||||||||||
| writePrefetchResponse(w, input.tag, "prefetching initiated successfully") | ||||||||||||
|
|
||||||||||||
| if ph.v1Synchronous { | ||||||||||||
| ph.downloadBlobs(input) | ||||||||||||
|
|
@@ -195,88 +196,124 @@ func (ph *PrefetchHandler) HandleV1(w http.ResponseWriter, r *http.Request) { | |||||||||||
| } | ||||||||||||
|
|
||||||||||||
| type prefetchInput struct { | ||||||||||||
| ctx context.Context | ||||||||||||
| blobs []blobInfo | ||||||||||||
| namespace string | ||||||||||||
| logger *zap.SugaredLogger | ||||||||||||
| tag string | ||||||||||||
| traceID string | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // preparePrefetch parses the request, calls build-index to get the image manifest SHA, | ||||||||||||
| // downloads the manifest(s) from the origin cluster, parses them, and returns the blobs layers to prefetch. | ||||||||||||
| // If an error occurs, preparePrefetch returns the appropriate HTTP response. | ||||||||||||
| func (ph *PrefetchHandler) preparePrefetch(w http.ResponseWriter, r *http.Request) (res *prefetchInput, errOccurred bool) { | ||||||||||||
| ctx, span := ph.tracer.Start(r.Context(), "prefetch.prepare", | ||||||||||||
| trace.WithSpanKind(trace.SpanKindServer), | ||||||||||||
| trace.WithAttributes( | ||||||||||||
| attribute.String("component", "proxy-prefetch"), | ||||||||||||
| attribute.String("operation", "prepare_prefetch"), | ||||||||||||
| ), | ||||||||||||
|
hweawer marked this conversation as resolved.
|
||||||||||||
| ) | ||||||||||||
| defer span.End() | ||||||||||||
|
||||||||||||
| defer span.End() | |
| defer span.End() | |
| // Use the original request context for downstream work to avoid returning | |
| // a context tied to a span that will be ended before it is used. | |
| ctx = r.Context() |
Uh oh!
There was an error while loading. Please reload this page.