func()

in module/apmazure/storage.go [74:135]


func (p *apmPipeline) Do(
	ctx context.Context,
	methodFactory pipeline.Factory,
	req pipeline.Request,
) (pipeline.Response, error) {
	rpc, err := newAzureRPC(req)
	if err != nil {
		return p.next.Do(ctx, methodFactory, req)
	}

	var span *apm.Span
	if rpc._type() == "messaging" && (req.Method == "GET" || req.Method == "") {
		// A new transaction is created when one or more messages are
		// received from a queue
		tx := p.tracer.StartTransaction(rpc.name(), rpc._type())
		ctx := apm.ContextWithTransaction(req.Context(), tx)
		r := req.Request.WithContext(ctx)
		req.Request = r
		defer tx.End()
		span = tx.StartExitSpan(rpc.name(), rpc._type(), apm.SpanFromContext(ctx))
	} else {
		span, ctx = apm.StartSpanOptions(ctx, rpc.name(), rpc._type(), apm.SpanOptions{
			ExitSpan: true,
		})
	}

	defer span.End()
	if !span.Dropped() {
		ctx = apm.ContextWithSpan(ctx, span)
		req.Request = apmhttp.RequestWithContext(ctx, req.Request)
		span.Context.SetHTTPRequest(req.Request)
	} else {
		return p.next.Do(ctx, methodFactory, req)
	}
	span.Action = rpc.operation()
	span.Subtype = rpc.subtype()

	resource := rpc.subtype() + "/" + rpc.storageAccountName()
	if rpc.subtype() == "azurequeue" {
		resource = rpc.subtype() + "/" + rpc.targetName()
	}
	span.Context.SetDestinationService(apm.DestinationServiceSpanContext{
		Resource: resource,
	})
	span.Context.SetServiceTarget(apm.ServiceTargetSpanContext{
		Type: rpc.subtype(),
		Name: rpc.targetName(),
	})

	resp, err := p.next.Do(ctx, methodFactory, req)
	if err != nil {
		apm.CaptureError(ctx, err).Send()
	}
	// We may still have a response even if err != nil
	// eg., the client library considers 4XX as an error but still returns
	// the response to us.
	if resp.Response() != nil {
		span.Context.SetHTTPStatusCode(resp.Response().StatusCode)
	}

	return resp, err
}