[#20] get/head: Add tracing support
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
parent
ad05f1eb82
commit
a945cdd42c
9 changed files with 234 additions and 50 deletions
|
@ -1,6 +1,7 @@
|
|||
package downloader
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
@ -13,6 +14,8 @@ import (
|
|||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool"
|
||||
"github.com/valyala/fasthttp"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
|
@ -25,15 +28,25 @@ const (
|
|||
hdrContainerID = "X-Container-Id"
|
||||
)
|
||||
|
||||
func (r request) headObject(clnt *pool.Pool, objectAddress oid.Address) {
|
||||
func headObject(ctx context.Context, req request, clnt *pool.Pool, objectAddress oid.Address) {
|
||||
ctx, span := utils.StartHTTPServerSpan(ctx, req.RequestCtx, "HEAD Object",
|
||||
trace.WithAttributes(
|
||||
attribute.String("cid", objectAddress.Container().EncodeToString()),
|
||||
attribute.String("oid", objectAddress.Object().EncodeToString()),
|
||||
))
|
||||
defer func() {
|
||||
utils.SetHTTPTraceInfo(ctx, span, req.RequestCtx)
|
||||
span.End()
|
||||
}()
|
||||
|
||||
var start = time.Now()
|
||||
if err := tokens.StoreBearerToken(r.RequestCtx); err != nil {
|
||||
r.log.Error("could not fetch and store bearer token", zap.Error(err))
|
||||
response.Error(r.RequestCtx, "could not fetch and store bearer token", fasthttp.StatusBadRequest)
|
||||
if err := tokens.StoreBearerToken(req.RequestCtx); err != nil {
|
||||
req.log.Error("could not fetch and store bearer token", zap.Error(err))
|
||||
response.Error(req.RequestCtx, "could not fetch and store bearer token", fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
btoken := bearerToken(r.RequestCtx)
|
||||
btoken := bearerToken(req.RequestCtx)
|
||||
|
||||
var prm pool.PrmObjectHead
|
||||
prm.SetAddress(objectAddress)
|
||||
|
@ -41,13 +54,13 @@ func (r request) headObject(clnt *pool.Pool, objectAddress oid.Address) {
|
|||
prm.UseBearer(*btoken)
|
||||
}
|
||||
|
||||
obj, err := clnt.HeadObject(r.appCtx, prm)
|
||||
obj, err := clnt.HeadObject(ctx, prm)
|
||||
if err != nil {
|
||||
r.handleFrostFSErr(err, start)
|
||||
req.handleFrostFSErr(err, start)
|
||||
return
|
||||
}
|
||||
|
||||
r.Response.Header.Set(fasthttp.HeaderContentLength, strconv.FormatUint(obj.PayloadSize(), 10))
|
||||
req.Response.Header.Set(fasthttp.HeaderContentLength, strconv.FormatUint(obj.PayloadSize(), 10))
|
||||
var contentType string
|
||||
for _, attr := range obj.Attributes() {
|
||||
key := attr.Key()
|
||||
|
@ -58,24 +71,24 @@ func (r request) headObject(clnt *pool.Pool, objectAddress oid.Address) {
|
|||
|
||||
key = utils.BackwardTransformIfSystem(key)
|
||||
|
||||
r.Response.Header.Set(utils.UserAttributeHeaderPrefix+key, val)
|
||||
req.Response.Header.Set(utils.UserAttributeHeaderPrefix+key, val)
|
||||
switch key {
|
||||
case object.AttributeTimestamp:
|
||||
value, err := strconv.ParseInt(val, 10, 64)
|
||||
if err != nil {
|
||||
r.log.Info("couldn't parse creation date",
|
||||
req.log.Info("couldn't parse creation date",
|
||||
zap.String("key", key),
|
||||
zap.String("val", val),
|
||||
zap.Error(err))
|
||||
continue
|
||||
}
|
||||
r.Response.Header.Set(fasthttp.HeaderLastModified, time.Unix(value, 0).UTC().Format(http.TimeFormat))
|
||||
req.Response.Header.Set(fasthttp.HeaderLastModified, time.Unix(value, 0).UTC().Format(http.TimeFormat))
|
||||
case object.AttributeContentType:
|
||||
contentType = val
|
||||
}
|
||||
}
|
||||
|
||||
idsToResponse(&r.Response, &obj)
|
||||
idsToResponse(&req.Response, &obj)
|
||||
|
||||
if len(contentType) == 0 {
|
||||
contentType, _, err = readContentType(obj.PayloadSize(), func(sz uint64) (io.Reader, error) {
|
||||
|
@ -86,18 +99,18 @@ func (r request) headObject(clnt *pool.Pool, objectAddress oid.Address) {
|
|||
prmRange.UseBearer(*btoken)
|
||||
}
|
||||
|
||||
resObj, err := clnt.ObjectRange(r.appCtx, prmRange)
|
||||
resObj, err := clnt.ObjectRange(ctx, prmRange)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resObj, nil
|
||||
})
|
||||
if err != nil && err != io.EOF {
|
||||
r.handleFrostFSErr(err, start)
|
||||
req.handleFrostFSErr(err, start)
|
||||
return
|
||||
}
|
||||
}
|
||||
r.SetContentType(contentType)
|
||||
req.SetContentType(contentType)
|
||||
}
|
||||
|
||||
func idsToResponse(resp *fasthttp.Response, obj *object.Object) {
|
||||
|
@ -110,10 +123,10 @@ func idsToResponse(resp *fasthttp.Response, obj *object.Object) {
|
|||
|
||||
// HeadByAddress handles head requests using simple cid/oid format.
|
||||
func (d *Downloader) HeadByAddress(c *fasthttp.RequestCtx) {
|
||||
d.byAddress(c, request.headObject)
|
||||
d.byAddress(c, headObject)
|
||||
}
|
||||
|
||||
// HeadByAttribute handles attribute-based head requests.
|
||||
func (d *Downloader) HeadByAttribute(c *fasthttp.RequestCtx) {
|
||||
d.byAttribute(c, request.headObject)
|
||||
d.byAttribute(c, headObject)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue