|
| 1 | +--- |
| 2 | +title: Schema — Instrumentation |
| 3 | +--- |
| 4 | + |
| 5 | +Instrumentation provides hooks for inserting custom code around field resolution and query execution. |
| 6 | + |
| 7 | +## Field Instrumentation |
| 8 | + |
| 9 | +Field instrumentation can be attached during schema definition: |
| 10 | + |
| 11 | +```ruby |
| 12 | +MySchema = GraphQL::Schema.define do |
| 13 | + instrument(:field, MyFieldInstrumentation.new) |
| 14 | +end |
| 15 | +``` |
| 16 | + |
| 17 | +The instrumenter is an object which responds to `#instrument(type, field)`. `#instrument` should return a `GraphQL::Field` instance which will be used during query execution. `#instrument` is called with each type-field pair for _all_ Object types and Interface types in your schema. |
| 18 | + |
| 19 | +Here's an example field instrumenter: |
| 20 | + |
| 21 | +```ruby |
| 22 | +class MyFieldInstrumentation |
| 23 | + # If a field was flagged to be timed, |
| 24 | + # wrap its resolve proc with a timer. |
| 25 | + def instrument(type, field) |
| 26 | + if field.metadata[:timed] |
| 27 | + old_resolve_proc = field.resolve_proc |
| 28 | + new_resolve_proc = ->(obj, args, ctx) { |
| 29 | + Rails.logger.info("#{type.name}.#{field.name} START: #{Time.now.to_i}") |
| 30 | + old_resolve_proc.call(obj, args, ctx) |
| 31 | + Rails.logger.info("#{type.name}.#{field.name} END: #{Time.now.to_i}") |
| 32 | + } |
| 33 | + end |
| 34 | + end |
| 35 | +end |
| 36 | +``` |
| 37 | + |
| 38 | +It can be attached as shown above. This implementation will _modify_ the underlying `GraphQL::Field` instance... be warned! |
| 39 | + |
| 40 | +## Query Instrumetation |
| 41 | + |
| 42 | + |
| 43 | +Query instrumentation can be attached during schema definition: |
| 44 | + |
| 45 | +```ruby |
| 46 | +MySchema = GraphQL::Schema.define do |
| 47 | + instrument(:query, MyQueryInstrumentation.new) |
| 48 | +end |
| 49 | +``` |
| 50 | + |
| 51 | +The instrumenter must implement `#before_query(query)` and `#after_query(query)`. The return value of these methods are not used. They receive the `GraphQL::Query` instance. |
| 52 | + |
| 53 | +```ruby |
| 54 | +class MyQueryInstrumentation |
| 55 | + # Log the time of the query |
| 56 | + def before_query(query) |
| 57 | + Rails.logger.info("Query begin: #{Time.now.to_i}") |
| 58 | + end |
| 59 | + |
| 60 | + def after_query(query) |
| 61 | + Rails.logger.info("Query end: #{Time.now.to_i}") |
| 62 | + end |
| 63 | +end |
| 64 | +``` |
0 commit comments