Skip to content

otelriver: add extra attributes #8

@krhubert

Description

@krhubert

Hey,

I saw some job attributes in otelriver source code and I want to share my implemenatation as a starting point for discussion about extra attributes.

    spanOpts := []trace.SpanStartOption{
        trace.WithAttributes(
            attribute.Int64("river.job.id", job.ID),
            attribute.Int("river.job.attempt", job.Attempt),
            attribute.Int64("river.job.created_at", job.CreatedAt.Unix()),
            attribute.String("river.job.kind", job.Kind),
            attribute.String("river.job.queue", job.Queue),
            attribute.Int64("river.job.scheduled_at", job.ScheduledAt.Unix()),
            attribute.Int("river.job.priority", job.Priority),
            attribute.StringSlice("river.job.tags", job.Tags),
        ),
        trace.WithSpanKind(trace.SpanKindConsumer),
    }

    ctx, span := wm.cfg.Tracer.Start(ctx, job.Kind, spanOpts...)
    defer span.End()

    err := doInner(ctx)
    if err != nil {
        if ok := errors.Is(err, &river.JobSnoozeError{}); ok {
            // Snooze errors are expected and should not be recorded as errors.
            // but rather as informational events.
            //
            // do not set the set status to error, but keep the unset.
            // This way the success/error ratio is not affected by snoozed jobs.
            span.SetAttributes(attribute.Bool("river.job.snoozed", true))
        } else {
            // otherwise, record the error as an error event.
            cancelErr := &river.JobCancelError{}
            if ok := errors.As(err, &cancelErr); ok {
                // try to unwrap the error to get the original error.
                //
                // TODO: think how we want to treat cancelled jobs.
                // On one hand, they are expected and should not be recorded as errors,
                // but on the other hand, they are not successful jobs.
                // For now, we just record them as error.
                span.SetAttributes(attribute.Bool("river.job.cancelled", true))
                err = cancelErr.Unwrap()
            }

            span.SetStatus(codes.Error, err.Error())
            span.RecordError(err)
        }
    } else {
        span.SetStatus(codes.Ok, "")
    }

Things that are different

  1. add SpanKindConsumer

  2. Extra span attributes:

  • "river.job.id"
  • "river.job.created_at"
  • "river.job.scheduled_at"
  • "river.job.priority"
  • "river.job.tags"

I think all of them might be helpful for logging, debugging and the dashboard. Maybe the attributes list can be configurable? I know this is not a common pattern in otel (configurable list of attrs), but why not give it a shot?

  1. special case for handling cancelled and snoozed jobs, which you can find more in the implementation I shared.

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions