Skip to content
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

Add document provider integration #20

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,25 @@ end
Worst case, you'll need to copy the code from the current `pipeline` target
and add a call to `Opencensus.Absinthe.add_phases/1` as above.

If you are using `DocumentProvider` modules, you will need to integrate into
their `pipeline/1` callback as well. If your `DocumentProvider` modules do not
yet override this callback, then this is fairly straightforward:

```elixir
def pipeline(%{pipeline: as_configured}) do
as_configured
|> Absinthe.Pipeline.from(__absinthe_plug_doc__(:remaining_pipeline))
|> Opencensus.Absinthe.add_schema_phases()
end
```

If you already override the `pipeline/1` callback, just append this to the end:

```elixir
# ... result
|> Opencensus.Absinthe.add_schema_phases()
```

### Middleware

Your [middleware callback][c:middleware/3] needs to run its output through
Expand Down
41 changes: 41 additions & 0 deletions lib/opencensus/absinthe.ex
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,25 @@ defmodule Opencensus.Absinthe do

Worst case, you'll need to copy the code from the current `pipeline` target and add a call to
`Opencensus.Absinthe.add_phases/1` as above.

If you are using `DocumentProvider` modules, you will need to integrate into
their `pipeline/1` callback as well. If your `DocumentProvider` modules do not
yet override this callback, then this is fairly straightforward:

```elixir
def pipeline(%{pipeline: as_configured}) do
as_configured
|> Absinthe.Pipeline.from(__absinthe_plug_doc__(:remaining_pipeline))
|> Opencensus.Absinthe.add_schema_phases()
end
```

If you already override the `pipeline/1` callback, just append this to the end:

```elixir
# ... result
|> Opencensus.Absinthe.add_schema_phases()
```
"""

alias Absinthe.Middleware
Expand Down Expand Up @@ -68,6 +87,28 @@ defmodule Opencensus.Absinthe do
)
end

@doc """
Add tracing phases to an existing pipeline for schema.

```elixir
pipeline =
Absinthe.Pipeline.for_document(schema, pipeline_opts)
|> Opencensus.Absinthe.add_schema_phases()
```
"""
@spec add_schema_phases(Absinthe.Pipeline.t()) :: Absinthe.Pipeline.t()
def add_schema_phases(pipeline) do
pipeline
|> Absinthe.Pipeline.insert_after(
Absinthe.Phase.Schema,
Opencensus.Absinthe.Phase.SchemaPush
)
|> Absinthe.Pipeline.insert_after(
Absinthe.Phase.Document.Result,
Opencensus.Absinthe.Phase.Pop
)
end

@doc """
Add tracing middleware for field resolution.

Expand Down
19 changes: 12 additions & 7 deletions lib/opencensus/absinthe/middleware.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,20 @@ defmodule Opencensus.Absinthe.Middleware do
@impl true
@spec call(Resolution.t(), term()) :: Resolution.t()
def call(%Resolution{state: :unresolved} = resolution, field: field) do
acc = Acc.get(resolution)
case Acc.get(resolution) do
# nil ->
# Logger.error("Handling a field resolution with no span metadata: #{inspect(field, pretty: true)}")
# resolution

span_options = %{
attributes: field |> extract_metadata() |> Enum.into(%{}, &stringify_keys/1)
}
acc ->
span_options = %{
attributes: field |> extract_metadata() |> Enum.into(%{}, &stringify_keys/1)
}

span_ctx = :oc_trace.start_span(field |> repr(), acc.span_ctx, span_options)
middleware = resolution.middleware ++ [{{__MODULE__, :on_complete}, span_ctx: span_ctx}]
%{resolution | middleware: middleware}
span_ctx = :oc_trace.start_span(field |> repr(), acc.span_ctx, span_options)
middleware = resolution.middleware ++ [{{__MODULE__, :on_complete}, span_ctx: span_ctx}]
%{resolution | middleware: middleware}
end
end

@doc false
Expand Down
5 changes: 3 additions & 2 deletions lib/opencensus/absinthe/phase/push.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ defmodule Opencensus.Absinthe.Phase.Push do

@impl true
@spec run(Blueprint.t(), keyword()) :: Phase.result_t()
def run(blueprint, _opts \\ []) do
parent_span_ctx = :ocp.with_child_span("Blueprint")
def run(blueprint, opts \\ []) do
child_span = Keyword.get(opts, :child_span, "Blueprint")
parent_span_ctx = :ocp.with_child_span(child_span)
span_ctx = :ocp.current_span_ctx()

acc = %Acc{
Expand Down
15 changes: 15 additions & 0 deletions lib/opencensus/absinthe/phase/schema_push.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
defmodule Opencensus.Absinthe.Phase.SchemaPush do
@moduledoc false

use Absinthe.Phase

alias Absinthe.Blueprint
alias Absinthe.Phase

@impl true
@spec run(Blueprint.t(), keyword()) :: Phase.result_t()
def run(blueprint, opts \\ []) do
opts = Keyword.put_new(opts, :child_span, "Blueprint")
Opencensus.Absinthe.Phase.Push.run(blueprint, opts)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe instead of calling this span "Blueprint" it might make sense to name it something else. "Schema" might make sense since that's the phase we're starting at, but is a fairly specific term with a generally understood usage.

end
end