README.md in graphql-metrics-5.0.8 vs README.md in graphql-metrics-6.0.0

- old
+ new

@@ -5,13 +5,10 @@ Extract as much detail as you want from GraphQL queries, served up from your Ruby app and the [`graphql` gem](https://github.com/rmosolgo/graphql-ruby). Compatible with the [`graphql-batch` gem](https://github.com/Shopify/graphql-batch), to extract batch-loaded fields resolution timings. Be sure to read the [CHANGELOG](CHANGELOG.md) to stay updated on feature additions, breaking changes made to this gem. -**NOTE**: Not tested with graphql-ruby's multiplexing feature. Metrics may not -be accurate if you execute multiple operations at once. - ## Installation Add this line to your application's Gemfile: ```ruby @@ -40,19 +37,19 @@ Get started by defining your own Analyzer, inheriting from `GraphQL::Metrics::Analyzer`. The following analyzer demonstrates a simple way to capture commonly used metrics sourced from key parts of your schema definition, the query document being served, as well as runtime query and resolver timings. In this toy example, all of -this data is simply stored on the GraphQL::Query context, under a namespace to avoid collisions with other analyzers +this data is simply stored on the `GraphQL::Query` context, under a namespace to avoid collisions with other analyzers etc. What you do with these captured metrics is up to you! **NOTE**: If any non-`graphql-ruby` gem-related exceptions occur in your application during query document -parsing and validation, **runtime metrics** for queries (like `query_duration`, `parsing_start_time_offset` etc.) as well as field +parsing and validation, **runtime metrics** for queries (like `query_duration`, etc.) as well as field resolver timings (like `resolver_timings`, `lazy_resolver_timings`) **may not be present** in the extracted `metrics` hash, -even if you opt to collect them by using `GraphQL::Metrics::Analyzer` and `GraphQL::Metrics::Tracer`. +even if you opt to collect them. ### Define your own analyzer subclass ```ruby class SimpleAnalyzer < GraphQL::Metrics::Analyzer @@ -73,19 +70,14 @@ # { # operation_type: "query", # operation_name: "PostDetails", # query_start_time: 1573833076.027327, # query_duration: 2.0207119999686256, - # lexing_start_time_offset: 0.0010339999571442604, # lexing_duration: 0.0008190000080503523, - # parsing_start_time_offset: 0.0010339999571442604, # parsing_duration: 0.0008190000080503523, - # validation_start_time_offset: 0.0030819999519735575, # validation_duration: 0.01704599999357015, - # analysis_start_time_offset: 0.0010339999571442604, # analysis_duration: 0.0008190000080503523, - # multiplex_start_time: 0.0008190000080503523, # } # # You can use these metrics to track high-level query performance, along with any other details you wish to # manually capture from `query` and/or `query.context`. def query_extracted(metrics) @@ -127,16 +119,14 @@ # return_type_name: "ID", # parent_type_name: "Post", # deprecated: false, # path: ["post", "id"], # resolver_timings: [ - # start_time_offset: 0.011901999998372048, - # duration: 5.999987479299307e-06 + # 5.999987479299307e-06, # ], # lazy_resolver_timings: [ - # start_time_offset: 0.031901999998372048, - # duration: 5.999987479299307e-06 + # 5.999987479299307e-06, # ], # } def field_extracted(metrics) store_metrics(:fields, metrics) end @@ -176,16 +166,16 @@ ns[:simple_extractor_results][context_key] << metrics end end ``` -Once defined, you can opt into capturing all metrics seen above by simply including GraphQL::Metrics as a plugin on your +Once defined, you can opt into capturing all metrics seen above by simply including `GraphQL::Metrics` as a plugin on your schema. + #### Metrics that are captured for arguments for fields and directives -Let's have a query example - +Example query: ```graphql query PostDetails($postId: ID!, $commentsTags: [String!] = null, $val: Int!) @customDirective(val: $val) { post(id: $postId) { title @skip(if: true) comments(ids: [1, 2], tags: $commentsTags) { @@ -240,79 +230,72 @@ } ``` ### Make use of your analyzer -Ensure that your schema is using the graphql-ruby 1.9+ `GraphQL::Execution::Interpreter` and `GraphQL::Analysis::AST` -engine, and then simply add the below `GraphQL::Metrics` plugins. +Add the `GraphQL::Metrics` plugin to your schema. This opts you in to capturing all static and runtime metrics seen above. -This opts you in to capturing all static and runtime metrics seen above. - ```ruby class Schema < GraphQL::Schema query QueryRoot mutation MutationRoot - query_analyzer SimpleAnalyzer - - instrument :query, GraphQL::Metrics::Instrumentation.new # Both of these are required if either is used. - tracer GraphQL::Metrics::Tracer.new # <-- Note! - - use GraphQL::Batch # Optional, but highly recommended. See https://github.com/Shopify/graphql-batch/. + use GraphQL::Metrics, analyzer: SimpleAnalyzer end ``` ### Optionally, only gather static metrics -If you don't care to capture runtime metrics like query and resolver timings, you can use your analyzer a standalone -analyzer without `GraphQL::Metrics::Instrumentation` and `tracer GraphQL::Metrics::Tracer`, like so: +If you don't care to capture field timings metrics, they can be disabled with the `capture_field_timings` option: ```ruby class Schema < GraphQL::Schema query QueryRoot mutation MutationRoot - query_analyzer SimpleAnalyzer + use GraphQL::Metrics, analyzer: SimpleAnalyzer, capture_field_timings: false end ``` Your analyzer will still be called with `query_extracted`, `field_extracted`, but with timings metrics omitted. -`argument_extracted` will work exactly the same, whether instrumentation and tracing are used or not. +`argument_extracted` will work exactly the same. +And if you want to disable tracing metrics entirely, use the `capture_timings` option: + +```ruby +class Schema < GraphQL::Schema + query QueryRoot + mutation MutationRoot + + use GraphQL::Metrics, analyzer: SimpleAnalyzer, capture_timings: false +end +``` + ## Order of execution Because of the structure of graphql-ruby's plugin architecture, it may be difficult to build an intuition around the -order in which methods defined on `GraphQL::Metrics::Instrumentation`, `GraphQL::Metrics::Tracer` and subclasses of +order in which methods defined on `GraphQL::Metrics::Instrumentation`, `GraphQL::Metrics::Trace` and subclasses of `GraphQL::Metrics::Analyzer` run. Although you ideally will not need to care about these details if you are simply using this gem to gather metrics in your application as intended, here's a breakdown of the order of execution of the methods involved: When used as instrumentation, an analyzer and tracing, the order of execution is usually: -* Tracer.capture_multiplex_start_time -* Tracer.capture_lexing_time -* Tracer.capture_parsing_time -* Instrumentation.before_query (context setup) -* Tracer.capture_validation_time -* Tracer.capture_analysis_time +* Instrumentation.execute_multiplex (context setup) +* Trace.capture_lexing_time +* Trace.capture_parsing_time +* Trace.capture_validation_time +* Trace.capture_analysis_time * Analyzer#initialize (bit more context setup, instance vars setup) * Analyzer#result -* Tracer.capture_query_start_time -* Tracer.trace_field (n times) -* Instrumentation.after_query (call query and field callbacks, now that we have all static and runtime metrics - gathered) +* Trace.capture_query_start_time +* Trace.trace_field (n times) +* Instrumentation.execute_multiplex (call query and field callbacks, now that we have all static and runtime metrics gathered) * Analyzer#extract_query * Analyzer#query_extracted * Analyzer#extract_fields_with_runtime_metrics * calls Analyzer#field_extracted n times - -When used as a simple analyzer, which doesn't gather or emit any runtime metrics (timings, arg values): -* Analyzer#initialize -* Analyzer#field_extracted n times -* Analyzer#result -* Analyzer#extract_query -* Analyzer#query_extracted ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.