getsentry / sentry-elixir

The official Elixir SDK for Sentry (sentry.io)
https://sentry.io
MIT License
625 stars 185 forks source link

set_context is private, but the docs advise not using set_extra_context #465

Closed hexpunk closed 1 year ago

hexpunk commented 3 years ago

Environment

How do you use Sentry? Sentry SaaS (sentry.io)

Which SDK and version? Elixir 7.x (but this applies to the 8.x versions as well)

Steps to Reproduce

Try using Sentry.Context.set_context instead of Sentry.Context.set_extra_context because of a note in the documentation:

Additional Data is deprecated in favor of structured contexts and should be avoided when possible.

Expected Result

I thought it would let me use that function similar to the Sentry libraries for other languages.

Actual Result

I received an error because Sentry.Context.set_context is a private function.

hexpunk commented 3 years ago

Perhaps this should be a documentation update? https://github.com/getsentry/sentry-docs/issues/3213

mitchellhenke commented 3 years ago

Thanks for opening an issue! There are some upstream changes to Sentry that require changes in this package, and that is definitely one of them. The number of contexts used to fit well enough in set_user_context, etc. but I'm not sure if it's a sustainable pattern going forward.

There would need to be some minor work to figure out how to handle the merging of different contexts without ruining what's already been stored.

eprothro commented 2 years ago

+1 for adding support. There's not a good way for us to get job args reported that I see with the current version of sentry-elixir.

eprothro commented 2 years ago

For anyone else trying the same you can hijack the request params:

defmodule Exq.Middleware.AddSentryMetadata do
  require Logger

  @behaviour Exq.Middleware.Behaviour

  def before_work(pipeline) do
    data = build_sentry_metadata(pipeline)
    Sentry.Context.set_tags_context(data.tags)
    Sentry.Context.set_request_context(data.request)
    pipeline
  rescue
    exception ->
      # if we don't return the pipeline, the job will not be re-enqueued
      Logger.error(inspect(exception))
      pipeline
  end

  def after_processed_work(pipeline), do: pipeline

  def after_failed_work(pipeline), do: pipeline

  defp build_sentry_metadata(%Exq.Middleware.Pipeline{assigns: %{job_serialized: job_serialized}}) do
    {:ok, job} = Jason.decode(job_serialized)

    %{
      tags: %{
        "job.module": job["class"],
        "job.queue": job["queue"],
        "job.id": job["jid"],
        "job.try": job["retry_count"] || 1
      },
      request: %{
        method: "Job",
        data: %{
          module: job["class"],
          args: job["args"],
          try: job["retry_count"] || 1,
          max_tries: job["retry"],
          queue: job["queue"],
          id: job["jid"]
        }
      }
    }
  end

  defp build_sentry_metadata(_), do: %{}
end
whatyouhide commented 1 year ago

This is now supported via Sentry.Context, with the functions