Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/opencensus-beam/opencensus_absinthe
Opencensus integration with Absinthe
https://github.com/opencensus-beam/opencensus_absinthe
absinthe elixir opencensus tracing
Last synced: 3 days ago
JSON representation
Opencensus integration with Absinthe
- Host: GitHub
- URL: https://github.com/opencensus-beam/opencensus_absinthe
- Owner: opencensus-beam
- License: apache-2.0
- Created: 2019-05-04T00:50:51.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2020-07-30T13:38:05.000Z (over 4 years ago)
- Last Synced: 2024-03-14T16:24:06.816Z (8 months ago)
- Topics: absinthe, elixir, opencensus, tracing
- Language: Elixir
- Size: 38.1 KB
- Stars: 21
- Watchers: 5
- Forks: 5
- Open Issues: 12
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-beam-monitoring - Absinthe
README
# Opencensus.Absinthe
[![CircleCI](https://circleci.com/gh/opencensus-beam/opencensus_absinthe.svg?style=svg)](https://circleci.com/gh/opencensus-beam/opencensus_absinthe)
[![Hex version badge](https://img.shields.io/hexpm/v/opencensus_absinthe.svg)](https://hex.pm/packages/opencensus_absinthe)Extends [Absinthe] to automatically create [OpenCensus] spans. Designed to
work with whatever is producing spans upstream, e.g. [Opencensus.Plug].[Absinthe]: http://absinthe-graphql.org
[Opencensus.Plug]: https://github.com/opencensus-beam/opencensus_plug
[OpenCensus]: http://opencensus.io## Installation
* Take the dependency
* Set up the pipeline
* Set up the middleware
* Adjust your schema
* Check it's all working### Dependency
If you're using `Absinthe.Plug`, add `opencensus_absinthe` to your `deps`
in `mix.exs` using a tighter version constraint than:```elixir
{:absinthe_plug, ">= 0.0.0"},
{:opencensus_absinthe, ">= 0.0.0"},
```### Pipeline
Add a `:pipeline` to your `t:Absinthe.Plug.opts/0` to have it call
`Opencensus.Absinthe.Plug.traced_pipeline/2`. If you're using
`Phoenix.Router.forward/4`, for example:```elixir
forward(
path,
Absinthe.Plug,
# ... existing config ...
pipeline: {Opencensus.Absinthe.Plug, :traced_pipeline}
)
```If you already have a `pipeline`, you can define your own and call both to
insert their phases. To work with `ApolloTracing`, for example:```elixir
def your_custom_pipeline(config, pipeline_opts \\ []) do
config
|> Absinthe.Plug.default_pipeline(pipeline_opts)
|> ApolloTracing.Pipeline.add_phases()
|> Opencensus.Absinthe.add_phases()
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.### Middleware
Your [middleware callback][c:middleware/3] needs to run its output through
the matching function in `Opencensus.Absinthe.Middleware` to add the
middleware to only the fields that need it:```elixir
def middleware(middleware, field, object) do
Opencensus.Absinthe.middleware(middleware, field, object)
end
```If you've already got some middleware, like above, you might need to copy
some code around to get the job done:```elixir
def middleware(middleware, field, object) do
([ApolloTracing.Middleware.Tracing, ApolloTracing.Middleware.Caching] ++ middleware)
|> Opencensus.Absinthe.middleware(field, object)
end
```[c:middleware/3]: https://hexdocs.pm/absinthe/Absinthe.Schema.html#c:middleware/3
### Schema
Until Absinthe merge and publish their telemetry support (see below) _and_
you upgrade, you'll also need to set `:trace` in the metadata for any
`field` for which you want tracing to happen:```elixir
query do
@desc "List all the things"
field :things, list_of(:thing), meta: [trace: true] do
resolve(&Resolvers.Account.all_things/2)
end
```Once you're on a telemetry-capable Absinthe, you'll get tracing for every
`field` containing a `resolve`.### Verification
Check your installation with `iex -S mix phx.server`, assuming Phoenix, and:
iex> :oc_reporter.register(:oc_reporter_stdout)
:okFire off a few requests and check the `{span, <` lines on standard
output.* If you see names matching your GraphQL route, e.g. `<>`, you set up
`opencensus_plug` properly.* If you see `<<"Absinthe.Blueprint">>`, the pipeline is working.
* If you see `<<"YourProject.Schema:thefield">>`, the middleware is working
and you've either:* Added `meta: [trace: true]` to your `field :thefield` as above, or
* Upgraded to a telemetry-capable Absinthe.
## Behaviour
Each Absinthe query runs in the process of its caller. If you hook up
[`opencensus_plug`][opencensus_plug], or something else that'll take trace
details off the wire, the process dictionary will have an `:oc_span_ctx_key`
key used by [`opencensus`][opencensus] to keep track of spans in flight.This package adds new [phases] to your [Absinthe Pipeline][pipeline]
to start new spans for each [resolution] and call, using both methods
available:> `opencensus` provides two methods for tracking \[trace and span] context,
> the process dictionary and a variable holding a ctx record.Specifically, this package:
* Starts a new span registered in the process dictionary for each query, and
* _Without any use of the process dictionary_, starts a new span for each
field, using the query span as the parent.The latter is necessary because the fields don't necessarily start and stop
without overlap. Naïve use of `:ocp.with_child_span` and `:ocp.finish_span`
will yield incorrect traces.[pipeline]: https://hexdocs.pm/absinthe/Absinthe.Pipeline.html
[phases]: https://hexdocs.pm/absinthe/Absinthe.Phase.html
[resolution]: https://hexdocs.pm/absinthe/Absinthe.Resolution.html
[opencensus]: https://hex.pm/packages/opencensus
[opencensus_plug]: https://hex.pm/packages/opencensus_plug## Development
Dependency management:
* `mix deps.get` to get your dependencies
* `mix deps.compile` to compile them
* `mix licenses` to check their license declarations, recursivelyFinding problems:
* `mix compile` to compile your code
* `mix credo` to suggest more idiomatic style for it
* `mix dialyzer` to find problems static typing might spot... *slowly*
* `mix test` to run unit tests
* `mix test.watch` to run the tests again whenever you change something
* `mix coveralls` to check test coverageDocumentation:
* `mix docs` to generate documentation for this project
* `mix help` to find out what else you can do with `mix`### Next Steps
Obvious next steps include stronger tests and many minor tweaks:
* Rename the outer span according to the schema
* Set some attributes on the outer span
* Trim the path from references so it starts with the closest `lib`
* Set the span status on completion
* Retire `lib/opencensus/absinthe/logger.ex` when possibleThe biggest looming change would be telemetry integration:
[`absinthe-graphql/absinthe#663`][PR663] to add [`telemetry`][telemetry] to
Absinthe could give us start and stop calls from within the calling process
suitable for calling `:ocp.with_child_span` and `:ocp.finish_span` to
maintain the main trace. In turn, that'd mean we didn't need the pipeline.`#663` won't help us generate spans for fields, because there's no way to
pass state back through `:telemetry.execute`. That said, it'll automatically
set `:absinthe_telemetry` in the field metadata if `query` is present.[PR663]: https://github.com/absinthe-graphql/absinthe/pull/663
[telemetry]: https://hex.pm/packages/telemetryRather than push back on the telemetry support to make it better support
tracing, we could integrate this capability directly with Absinthe if:* The community deploy a lot of `opencensus`
* It proves to be as lightweight and stable as `telemetry`
* Its impact when not hooked up is minimal or zeroWe could then retire this module except for users with older versions.