Repository: mirumee/ariadne
Pull request #1125 (2023-10-23 08:04:53)

Enable Subscription Functionality for GraphiQL-Explorer
The way GraphiQL-Explorer is currently initialized by Ariadne, subscriptions do not work.

This pull request allows to set the subscription endpoint (to be used by GraphiQL) manually via a `subscription_url`-parameter, which defaults to a websocket connection at the location of the graphiql-explorer (e.g., `ws://localhost:8000/graphql/`, if the explorer is reached via `http://localhost:8000/graphql/`).

rafalp: Tests are failing. Can you fix them?
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/mirumee/ariadne/pull/1125?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mirumee) Report
> Merging [#1125](https://app.codecov.io/gh/mirumee/ariadne/pull/1125?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mirumee) (94f65b5) into [master](https://app.codecov.io/gh/mirumee/ariadne/commit/48fd7c7752a7d27e3ba45533f390617a5937ce8b?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mirumee) (48fd7c7) will **not change** coverage.
> The diff coverage is `n/a`.

```diff
@@           Coverage Diff           @@
##           master    #1125   +/-   ##
=======================================
  Coverage   97.82%   97.82%           
=======================================
  Files         115      115           
  Lines        7763     7763           
=======================================
  Hits         7594     7594           
  Misses        169      169           
```


| [Files](https://app.codecov.io/gh/mirumee/ariadne/pull/1125?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mirumee) | Coverage Δ | |
|---|---|---|
| [ariadne/explorer/graphiql.py](https://app.codecov.io/gh/mirumee/ariadne/pull/1125?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mirumee#diff-YXJpYWRuZS9leHBsb3Jlci9ncmFwaGlxbC5weQ==) | `100.00% <ø> (ø)` | |
| [tests/asgi/snapshots/snap\_test\_explorer.py](https://app.codecov.io/gh/mirumee/ariadne/pull/1125?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mirumee#diff-dGVzdHMvYXNnaS9zbmFwc2hvdHMvc25hcF90ZXN0X2V4cGxvcmVyLnB5) | `100.00% <ø> (ø)` | |
| [tests/explorers/snapshots/snap\_test\_explorers.py](https://app.codecov.io/gh/mirumee/ariadne/pull/1125?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mirumee#diff-dGVzdHMvZXhwbG9yZXJzL3NuYXBzaG90cy9zbmFwX3Rlc3RfZXhwbG9yZXJzLnB5) | `100.00% <ø> (ø)` | |
| [tests/wsgi/snapshots/snap\_test\_explorer.py](https://app.codecov.io/gh/mirumee/ariadne/pull/1125?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mirumee#diff-dGVzdHMvd3NnaS9zbmFwc2hvdHMvc25hcF90ZXN0X2V4cGxvcmVyLnB5) | `100.00% <ø> (ø)` | |

:mega: We’re building smart automated test selection to slash your CI/CD build times. [Learn more](https://about.codecov.io/iterative-testing/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mirumee)

fabiangfd: OK, I have fixed the tests: Added the new expected html from graphiql-explorer to the test snapshots.
rafalp: There's also a test for passing options to graphiQL explorer. Can you add one more for custom subscription url?

https://github.com/mirumee/ariadne/blob/master/tests/explorers/test_explorers.py#L19

Patch:
diff --git a/ariadne/explorer/graphiql.py b/ariadne/explorer/graphiql.py
index 8d8915a..c177d0c 100644
--- a/ariadne/explorer/graphiql.py
+++ b/ariadne/explorer/graphiql.py
@@ -43,6 +43,7 @@ class ExplorerGraphiQL(Explorer):
         title: str = "Ariadne GraphQL",
         explorer_plugin: bool = False,
         default_query: str = DEFAULT_QUERY,
+        subscription_url: str = "",
     ) -> None:
         self.parsed_html = render_template(
             GRAPHIQL_HTML,
@@ -50,6 +51,7 @@ class ExplorerGraphiQL(Explorer):
                 "title": title,
                 "enable_explorer_plugin": explorer_plugin,
                 "default_query": escape_default_query(default_query),
+                "subscription_url": subscription_url,
             },
         )
 
diff --git a/ariadne/explorer/templates/graphiql.html b/ariadne/explorer/templates/graphiql.html
index b52fbdb..62b5923 100644
--- a/ariadne/explorer/templates/graphiql.html
+++ b/ariadne/explorer/templates/graphiql.html
@@ -70,6 +70,11 @@
     <script>
       var fetcher = GraphiQL.createFetcher({
         url: window.location.href,
+        {% if subscription_url %}
+        subscriptionUrl: "{{ subscription_url }}",
+        {% else %}
+        subscriptionUrl: (window.location.protocol === "https:" ? "wss" : "ws") + "://" + window.location.host + window.location.pathname,
+        {% endif %}
       });
 
       function AriadneGraphiQL() {
diff --git a/benchmark/results/Linux-CPython-3.10-64bit/0022_73ce096d9b567ead19faf6554c1c5018ef773787_20231024_132531.json b/benchmark/results/Linux-CPython-3.10-64bit/0022_73ce096d9b567ead19faf6554c1c5018ef773787_20231024_132531.json
new file mode 100644
index 0000000..a6b5b7f
--- /dev/null
+++ b/benchmark/results/Linux-CPython-3.10-64bit/0022_73ce096d9b567ead19faf6554c1c5018ef773787_20231024_132531.json
@@ -0,0 +1,284 @@
+{
+    "machine_info": {
+        "node": "fv-az1250-266",
+        "processor": "x86_64",
+        "machine": "x86_64",
+        "python_compiler": "GCC 11.4.0",
+        "python_implementation": "CPython",
+        "python_implementation_version": "3.10.13",
+        "python_version": "3.10.13",
+        "python_build": [
+            "main",
+            "Aug 28 2023 08:28:42"
+        ],
+        "release": "6.2.0-1014-azure",
+        "system": "Linux",
+        "cpu": {
+            "python_version": "3.10.13.final.0 (64 bit)",
+            "cpuinfo_version": [
+                9,
+                0,
+                0
+            ],
+            "cpuinfo_version_string": "9.0.0",
+            "arch": "X86_64",
+            "bits": 64,
+            "count": 2,
+            "arch_string_raw": "x86_64",
+            "vendor_id_raw": "GenuineIntel",
+            "brand_raw": "Intel(R) Xeon(R) Platinum 8171M CPU @ 2.60GHz",
+            "hz_advertised_friendly": "2.6000 GHz",
+            "hz_actual_friendly": "2.0951 GHz",
+            "hz_advertised": [
+                2600000000,
+                0
+            ],
+            "hz_actual": [
+                2095077000,
+                0
+            ],
+            "stepping": 4,
+            "model": 85,
+            "family": 6,
+            "flags": [
+                "3dnowprefetch",
+                "abm",
+                "adx",
+                "aes",
+                "apic",
+                "avx",
+                "avx2",
+                "avx512bw",
+                "avx512cd",
+                "avx512dq",
+                "avx512f",
+                "avx512vl",
+                "bmi1",
+                "bmi2",
+                "clflush",
+                "clflushopt",
+                "cmov",
+                "constant_tsc",
+                "cpuid",
+                "cx16",
+                "cx8",
+                "de",
+                "erms",
+                "f16c",
+                "fma",
+                "fpu",
+                "fsgsbase",
+                "fxsr",
+                "hle",
+                "ht",
+                "hypervisor",
+                "invpcid",
+                "invpcid_single",
+                "lahf_lm",
+                "lm",
+                "mca",
+                "mce",
+                "md_clear",
+                "mmx",
+                "movbe",
+                "msr",
+                "mtrr",
+                "nopl",
+                "nx",
+                "osxsave",
+                "pae",
+                "pat",
+                "pcid",
+                "pclmulqdq",
+                "pdpe1gb",
+                "pge",
+                "pni",
+                "popcnt",
+                "pse",
+                "pse36",
+                "pti",
+                "rdrand",
+                "rdrnd",
+                "rdseed",
+                "rdtscp",
+                "rep_good",
+                "rtm",
+                "sep",
+                "smap",
+                "smep",
+                "ss",
+                "sse",
+                "sse2",
+                "sse4_1",
+                "sse4_2",
+                "ssse3",
+                "syscall",
+                "tsc",
+                "vme",
+                "xsave",
+                "xsavec",
+                "xsaveopt",
+                "xsaves",
+                "xtopology"
+            ],
+            "l3_cache_size": 37486592,
+            "l2_cache_size": 2097152,
+            "l1_data_cache_size": 65536,
+            "l1_instruction_cache_size": 65536,
+            "l2_cache_line_size": 256,
+            "l2_cache_associativity": 6
+        }
+    },
+    "commit_info": {
+        "id": "73ce096d9b567ead19faf6554c1c5018ef773787",
+        "time": "2023-10-24T13:24:53+00:00",
+        "author_time": "2023-10-24T13:24:53+00:00",
+        "dirty": false,
+        "project": "ariadne",
+        "branch": "master"
+    },
+    "benchmarks": [
+        {
+            "group": null,
+            "name": "test_query_without_extensions",
+            "fullname": "benchmark/test_extensions.py::test_query_without_extensions",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.6618058119999972,
+                "max": 1.7346449559999968,
+                "mean": 1.6955735507999976,
+                "stddev": 0.031798397439802464,
+                "rounds": 5,
+                "median": 1.7008382500000039,
+                "iqr": 0.05636636599999889,
+                "q1": 1.664090188999996,
+                "q3": 1.7204565549999948,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.6618058119999972,
+                "hd15iqr": 1.7346449559999968,
+                "ops": 0.5897709359338524,
+                "total": 8.477867753999988,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_noop_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_noop_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.671564552999996,
+                "max": 1.7630059709999983,
+                "mean": 1.718160531999996,
+                "stddev": 0.0413684094332238,
+                "rounds": 5,
+                "median": 1.724863451999994,
+                "iqr": 0.07700485250001066,
+                "q1": 1.6775821457499909,
+                "q3": 1.7545869982500015,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.671564552999996,
+                "hd15iqr": 1.7630059709999983,
+                "ops": 0.5820177925027569,
+                "total": 8.59080265999998,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_open_telemetry_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_open_telemetry_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 2.0004514440000207,
+                "max": 2.102721115999998,
+                "mean": 2.051136749,
+                "stddev": 0.03878771006323934,
+                "rounds": 5,
+                "median": 2.051837250999995,
+                "iqr": 0.05530808599999659,
+                "q1": 2.0229952522499985,
+                "q3": 2.078303338249995,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 2.0004514440000207,
+                "hd15iqr": 2.102721115999998,
+                "ops": 0.48753453444171124,
+                "total": 10.255683744999999,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_open_tracing_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_open_tracing_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.8273924780000073,
+                "max": 1.9061192089999963,
+                "mean": 1.8702541318000043,
+                "stddev": 0.0379858529240782,
+                "rounds": 5,
+                "median": 1.8883763050000084,
+                "iqr": 0.07008226699998943,
+                "q1": 1.8301663275000095,
+                "q3": 1.900248594499999,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.8273924780000073,
+                "hd15iqr": 1.9061192089999963,
+                "ops": 0.5346866947100721,
+                "total": 9.351270659000022,
+                "iterations": 1
+            }
+        }
+    ],
+    "datetime": "2023-10-24T13:26:26.299630",
+    "version": "4.0.0"
+}
\ No newline at end of file
diff --git a/benchmark/results/Linux-CPython-3.10-64bit/0023_bb320f5ab78d0c9d2560fe8bbe8a84b05cecad67_20231024_133853.json b/benchmark/results/Linux-CPython-3.10-64bit/0023_bb320f5ab78d0c9d2560fe8bbe8a84b05cecad67_20231024_133853.json
new file mode 100644
index 0000000..813e1c6
--- /dev/null
+++ b/benchmark/results/Linux-CPython-3.10-64bit/0023_bb320f5ab78d0c9d2560fe8bbe8a84b05cecad67_20231024_133853.json
@@ -0,0 +1,284 @@
+{
+    "machine_info": {
+        "node": "fv-az810-537",
+        "processor": "x86_64",
+        "machine": "x86_64",
+        "python_compiler": "GCC 11.4.0",
+        "python_implementation": "CPython",
+        "python_implementation_version": "3.10.13",
+        "python_version": "3.10.13",
+        "python_build": [
+            "main",
+            "Aug 28 2023 08:28:42"
+        ],
+        "release": "6.2.0-1014-azure",
+        "system": "Linux",
+        "cpu": {
+            "python_version": "3.10.13.final.0 (64 bit)",
+            "cpuinfo_version": [
+                9,
+                0,
+                0
+            ],
+            "cpuinfo_version_string": "9.0.0",
+            "arch": "X86_64",
+            "bits": 64,
+            "count": 2,
+            "arch_string_raw": "x86_64",
+            "vendor_id_raw": "GenuineIntel",
+            "brand_raw": "Intel(R) Xeon(R) Platinum 8171M CPU @ 2.60GHz",
+            "hz_advertised_friendly": "2.6000 GHz",
+            "hz_actual_friendly": "2.0952 GHz",
+            "hz_advertised": [
+                2600000000,
+                0
+            ],
+            "hz_actual": [
+                2095193000,
+                0
+            ],
+            "stepping": 4,
+            "model": 85,
+            "family": 6,
+            "flags": [
+                "3dnowprefetch",
+                "abm",
+                "adx",
+                "aes",
+                "apic",
+                "avx",
+                "avx2",
+                "avx512bw",
+                "avx512cd",
+                "avx512dq",
+                "avx512f",
+                "avx512vl",
+                "bmi1",
+                "bmi2",
+                "clflush",
+                "clflushopt",
+                "cmov",
+                "constant_tsc",
+                "cpuid",
+                "cx16",
+                "cx8",
+                "de",
+                "erms",
+                "f16c",
+                "fma",
+                "fpu",
+                "fsgsbase",
+                "fxsr",
+                "hle",
+                "ht",
+                "hypervisor",
+                "invpcid",
+                "invpcid_single",
+                "lahf_lm",
+                "lm",
+                "mca",
+                "mce",
+                "md_clear",
+                "mmx",
+                "movbe",
+                "msr",
+                "mtrr",
+                "nopl",
+                "nx",
+                "osxsave",
+                "pae",
+                "pat",
+                "pcid",
+                "pclmulqdq",
+                "pdpe1gb",
+                "pge",
+                "pni",
+                "popcnt",
+                "pse",
+                "pse36",
+                "pti",
+                "rdrand",
+                "rdrnd",
+                "rdseed",
+                "rdtscp",
+                "rep_good",
+                "rtm",
+                "sep",
+                "smap",
+                "smep",
+                "ss",
+                "sse",
+                "sse2",
+                "sse4_1",
+                "sse4_2",
+                "ssse3",
+                "syscall",
+                "tsc",
+                "vme",
+                "xsave",
+                "xsavec",
+                "xsaveopt",
+                "xsaves",
+                "xtopology"
+            ],
+            "l3_cache_size": 37486592,
+            "l2_cache_size": 2097152,
+            "l1_data_cache_size": 65536,
+            "l1_instruction_cache_size": 65536,
+            "l2_cache_line_size": 256,
+            "l2_cache_associativity": 6
+        }
+    },
+    "commit_info": {
+        "id": "bb320f5ab78d0c9d2560fe8bbe8a84b05cecad67",
+        "time": "2023-10-24T13:38:24+00:00",
+        "author_time": "2023-10-24T13:38:24+00:00",
+        "dirty": false,
+        "project": "ariadne",
+        "branch": "master"
+    },
+    "benchmarks": [
+        {
+            "group": null,
+            "name": "test_query_without_extensions",
+            "fullname": "benchmark/test_extensions.py::test_query_without_extensions",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.2798617919999913,
+                "max": 1.3721145699999937,
+                "mean": 1.3065499213999943,
+                "stddev": 0.0371607267455812,
+                "rounds": 5,
+                "median": 1.292831256999989,
+                "iqr": 0.02607039899999819,
+                "q1": 1.288940091249998,
+                "q3": 1.3150104902499962,
+                "iqr_outliers": 1,
+                "stddev_outliers": 1,
+                "outliers": "1;1",
+                "ld15iqr": 1.2798617919999913,
+                "hd15iqr": 1.3721145699999937,
+                "ops": 0.7653745054980219,
+                "total": 6.532749606999971,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_noop_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_noop_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.2894333640000042,
+                "max": 1.3726681779999979,
+                "mean": 1.3210469184000004,
+                "stddev": 0.03803818547689372,
+                "rounds": 5,
+                "median": 1.2979946089999999,
+                "iqr": 0.06306771524999633,
+                "q1": 1.2931557505000022,
+                "q3": 1.3562234657499985,
+                "iqr_outliers": 0,
+                "stddev_outliers": 1,
+                "outliers": "1;0",
+                "ld15iqr": 1.2894333640000042,
+                "hd15iqr": 1.3726681779999979,
+                "ops": 0.7569753852582013,
+                "total": 6.605234592000002,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_open_telemetry_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_open_telemetry_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.5637812899999943,
+                "max": 1.6038031140000015,
+                "mean": 1.5818072924000006,
+                "stddev": 0.016393369260543203,
+                "rounds": 5,
+                "median": 1.5813642400000134,
+                "iqr": 0.02710157250000833,
+                "q1": 1.567430195999993,
+                "q3": 1.5945317685000013,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.5637812899999943,
+                "hd15iqr": 1.6038031140000015,
+                "ops": 0.6321882601026246,
+                "total": 7.909036462000003,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_open_tracing_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_open_tracing_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.407740055000005,
+                "max": 1.4536487040000026,
+                "mean": 1.424520719999998,
+                "stddev": 0.018094367059304995,
+                "rounds": 5,
+                "median": 1.4187835820000032,
+                "iqr": 0.023327746500001467,
+                "q1": 1.4119214437499927,
+                "q3": 1.4352491902499942,
+                "iqr_outliers": 0,
+                "stddev_outliers": 1,
+                "outliers": "1;0",
+                "ld15iqr": 1.407740055000005,
+                "hd15iqr": 1.4536487040000026,
+                "ops": 0.7019904912299214,
+                "total": 7.122603599999991,
+                "iterations": 1
+            }
+        }
+    ],
+    "datetime": "2023-10-24T13:39:36.502373",
+    "version": "4.0.0"
+}
\ No newline at end of file
diff --git a/benchmark/results/Linux-CPython-3.11-64bit/0023_c44d706444e8d23e13fb72292a01b8603deb1b58_20231024_134007.json b/benchmark/results/Linux-CPython-3.11-64bit/0023_c44d706444e8d23e13fb72292a01b8603deb1b58_20231024_134007.json
new file mode 100644
index 0000000..96ed7dd
--- /dev/null
+++ b/benchmark/results/Linux-CPython-3.11-64bit/0023_c44d706444e8d23e13fb72292a01b8603deb1b58_20231024_134007.json
@@ -0,0 +1,284 @@
+{
+    "machine_info": {
+        "node": "fv-az477-186",
+        "processor": "x86_64",
+        "machine": "x86_64",
+        "python_compiler": "GCC 11.4.0",
+        "python_implementation": "CPython",
+        "python_implementation_version": "3.11.6",
+        "python_version": "3.11.6",
+        "python_build": [
+            "main",
+            "Oct  3 2023 04:42:57"
+        ],
+        "release": "6.2.0-1014-azure",
+        "system": "Linux",
+        "cpu": {
+            "python_version": "3.11.6.final.0 (64 bit)",
+            "cpuinfo_version": [
+                9,
+                0,
+                0
+            ],
+            "cpuinfo_version_string": "9.0.0",
+            "arch": "X86_64",
+            "bits": 64,
+            "count": 2,
+            "arch_string_raw": "x86_64",
+            "vendor_id_raw": "GenuineIntel",
+            "brand_raw": "Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz",
+            "hz_advertised_friendly": "2.8000 GHz",
+            "hz_actual_friendly": "2.7934 GHz",
+            "hz_advertised": [
+                2800000000,
+                0
+            ],
+            "hz_actual": [
+                2793437000,
+                0
+            ],
+            "stepping": 6,
+            "model": 106,
+            "family": 6,
+            "flags": [
+                "3dnowprefetch",
+                "abm",
+                "adx",
+                "aes",
+                "apic",
+                "avx",
+                "avx2",
+                "avx512bw",
+                "avx512cd",
+                "avx512dq",
+                "avx512f",
+                "avx512vl",
+                "bmi1",
+                "bmi2",
+                "clflush",
+                "clflushopt",
+                "cmov",
+                "constant_tsc",
+                "cpuid",
+                "cx16",
+                "cx8",
+                "de",
+                "erms",
+                "f16c",
+                "fma",
+                "fpu",
+                "fsgsbase",
+                "fxsr",
+                "hle",
+                "ht",
+                "hypervisor",
+                "invpcid",
+                "invpcid_single",
+                "lahf_lm",
+                "lm",
+                "mca",
+                "mce",
+                "md_clear",
+                "mmx",
+                "movbe",
+                "msr",
+                "mtrr",
+                "nopl",
+                "nx",
+                "osxsave",
+                "pae",
+                "pat",
+                "pcid",
+                "pclmulqdq",
+                "pdpe1gb",
+                "pge",
+                "pni",
+                "popcnt",
+                "pse",
+                "pse36",
+                "pti",
+                "rdrand",
+                "rdrnd",
+                "rdseed",
+                "rdtscp",
+                "rep_good",
+                "rtm",
+                "sep",
+                "smap",
+                "smep",
+                "ss",
+                "sse",
+                "sse2",
+                "sse4_1",
+                "sse4_2",
+                "ssse3",
+                "syscall",
+                "tsc",
+                "vme",
+                "xsave",
+                "xsavec",
+                "xsaveopt",
+                "xsaves",
+                "xtopology"
+            ],
+            "l3_cache_size": 50331648,
+            "l2_cache_size": "2.5 MiB",
+            "l1_data_cache_size": 98304,
+            "l1_instruction_cache_size": 65536,
+            "l2_cache_line_size": 256,
+            "l2_cache_associativity": 6
+        }
+    },
+    "commit_info": {
+        "id": "c44d706444e8d23e13fb72292a01b8603deb1b58",
+        "time": "2023-10-24T13:39:36+00:00",
+        "author_time": "2023-10-24T13:39:36+00:00",
+        "dirty": false,
+        "project": "ariadne",
+        "branch": "master"
+    },
+    "benchmarks": [
+        {
+            "group": null,
+            "name": "test_query_without_extensions",
+            "fullname": "benchmark/test_extensions.py::test_query_without_extensions",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.0247406389999867,
+                "max": 1.0733194379999986,
+                "mean": 1.041529148399991,
+                "stddev": 0.01877968676529115,
+                "rounds": 5,
+                "median": 1.0354694059999758,
+                "iqr": 0.01897995149999332,
+                "q1": 1.030561130999999,
+                "q3": 1.0495410824999922,
+                "iqr_outliers": 0,
+                "stddev_outliers": 1,
+                "outliers": "1;0",
+                "ld15iqr": 1.0247406389999867,
+                "hd15iqr": 1.0733194379999986,
+                "ops": 0.9601267535682622,
+                "total": 5.207645741999954,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_noop_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_noop_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.0341329629999905,
+                "max": 1.0874000549999892,
+                "mean": 1.071857707800001,
+                "stddev": 0.02195030691004965,
+                "rounds": 5,
+                "median": 1.082494195999999,
+                "iqr": 0.022965520750005908,
+                "q1": 1.0619318637500044,
+                "q3": 1.0848973845000103,
+                "iqr_outliers": 0,
+                "stddev_outliers": 1,
+                "outliers": "1;0",
+                "ld15iqr": 1.0341329629999905,
+                "hd15iqr": 1.0874000549999892,
+                "ops": 0.9329596575393485,
+                "total": 5.359288539000005,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_open_telemetry_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_open_telemetry_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.2644616430000042,
+                "max": 1.2989596930000005,
+                "mean": 1.2849725428000056,
+                "stddev": 0.013041603250701368,
+                "rounds": 5,
+                "median": 1.2865678550000155,
+                "iqr": 0.016072319249992972,
+                "q1": 1.277969078500007,
+                "q3": 1.29404139775,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.2644616430000042,
+                "hd15iqr": 1.2989596930000005,
+                "ops": 0.778226745468787,
+                "total": 6.424862714000028,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_open_tracing_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_open_tracing_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.1686460880000027,
+                "max": 1.1859206020000101,
+                "mean": 1.1769496561999973,
+                "stddev": 0.006485035949478855,
+                "rounds": 5,
+                "median": 1.1767772359999924,
+                "iqr": 0.0088983512500036,
+                "q1": 1.1723982937499926,
+                "q3": 1.1812966449999962,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.1686460880000027,
+                "hd15iqr": 1.1859206020000101,
+                "ops": 0.849654014283574,
+                "total": 5.884748280999986,
+                "iterations": 1
+            }
+        }
+    ],
+    "datetime": "2023-10-24T13:40:42.633375",
+    "version": "4.0.0"
+}
\ No newline at end of file
diff --git a/benchmark/results/Linux-CPython-3.8-64bit/0022_94f65b5cbe55253c84af30166f5ccddf61fe88cd_20231024_132259.json b/benchmark/results/Linux-CPython-3.8-64bit/0022_94f65b5cbe55253c84af30166f5ccddf61fe88cd_20231024_132259.json
new file mode 100644
index 0000000..af0050c
--- /dev/null
+++ b/benchmark/results/Linux-CPython-3.8-64bit/0022_94f65b5cbe55253c84af30166f5ccddf61fe88cd_20231024_132259.json
@@ -0,0 +1,284 @@
+{
+    "machine_info": {
+        "node": "fv-az189-75",
+        "processor": "x86_64",
+        "machine": "x86_64",
+        "python_compiler": "GCC 11.4.0",
+        "python_implementation": "CPython",
+        "python_implementation_version": "3.8.18",
+        "python_version": "3.8.18",
+        "python_build": [
+            "default",
+            "Aug 28 2023 08:27:22"
+        ],
+        "release": "6.2.0-1015-azure",
+        "system": "Linux",
+        "cpu": {
+            "python_version": "3.8.18.final.0 (64 bit)",
+            "cpuinfo_version": [
+                9,
+                0,
+                0
+            ],
+            "cpuinfo_version_string": "9.0.0",
+            "arch": "X86_64",
+            "bits": 64,
+            "count": 2,
+            "arch_string_raw": "x86_64",
+            "vendor_id_raw": "GenuineIntel",
+            "brand_raw": "Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz",
+            "hz_advertised_friendly": "2.8000 GHz",
+            "hz_actual_friendly": "2.7934 GHz",
+            "hz_advertised": [
+                2800000000,
+                0
+            ],
+            "hz_actual": [
+                2793438000,
+                0
+            ],
+            "stepping": 6,
+            "model": 106,
+            "family": 6,
+            "flags": [
+                "3dnowprefetch",
+                "abm",
+                "adx",
+                "aes",
+                "apic",
+                "avx",
+                "avx2",
+                "avx512bw",
+                "avx512cd",
+                "avx512dq",
+                "avx512f",
+                "avx512vl",
+                "bmi1",
+                "bmi2",
+                "clflush",
+                "clflushopt",
+                "cmov",
+                "constant_tsc",
+                "cpuid",
+                "cx16",
+                "cx8",
+                "de",
+                "erms",
+                "f16c",
+                "fma",
+                "fpu",
+                "fsgsbase",
+                "fxsr",
+                "hle",
+                "ht",
+                "hypervisor",
+                "invpcid",
+                "invpcid_single",
+                "lahf_lm",
+                "lm",
+                "mca",
+                "mce",
+                "md_clear",
+                "mmx",
+                "movbe",
+                "msr",
+                "mtrr",
+                "nopl",
+                "nx",
+                "osxsave",
+                "pae",
+                "pat",
+                "pcid",
+                "pclmulqdq",
+                "pdpe1gb",
+                "pge",
+                "pni",
+                "popcnt",
+                "pse",
+                "pse36",
+                "pti",
+                "rdrand",
+                "rdrnd",
+                "rdseed",
+                "rdtscp",
+                "rep_good",
+                "rtm",
+                "sep",
+                "smap",
+                "smep",
+                "ss",
+                "sse",
+                "sse2",
+                "sse4_1",
+                "sse4_2",
+                "ssse3",
+                "syscall",
+                "tsc",
+                "vme",
+                "xsave",
+                "xsavec",
+                "xsaveopt",
+                "xsaves",
+                "xtopology"
+            ],
+            "l3_cache_size": 50331648,
+            "l2_cache_size": "2.5 MiB",
+            "l1_data_cache_size": 98304,
+            "l1_instruction_cache_size": 65536,
+            "l2_cache_line_size": 256,
+            "l2_cache_associativity": 6
+        }
+    },
+    "commit_info": {
+        "id": "94f65b5cbe55253c84af30166f5ccddf61fe88cd",
+        "time": "2023-10-24T13:19:39+00:00",
+        "author_time": "2023-10-24T13:19:39+00:00",
+        "dirty": false,
+        "project": "ariadne",
+        "branch": "master"
+    },
+    "benchmarks": [
+        {
+            "group": null,
+            "name": "test_query_without_extensions",
+            "fullname": "benchmark/test_extensions.py::test_query_without_extensions",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.2899942550000105,
+                "max": 1.3277879410000253,
+                "mean": 1.3100436158000093,
+                "stddev": 0.01560528763426289,
+                "rounds": 5,
+                "median": 1.3128034130000117,
+                "iqr": 0.026203568499973073,
+                "q1": 1.2964831665000176,
+                "q3": 1.3226867349999907,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.2899942550000105,
+                "hd15iqr": 1.3277879410000253,
+                "ops": 0.7633333638203535,
+                "total": 6.550218079000047,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_noop_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_noop_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.314720685000026,
+                "max": 1.3630854460000137,
+                "mean": 1.3416965982000022,
+                "stddev": 0.020747847161725484,
+                "rounds": 5,
+                "median": 1.337854300999993,
+                "iqr": 0.03526825950000756,
+                "q1": 1.326900096249993,
+                "q3": 1.3621683557500006,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.314720685000026,
+                "hd15iqr": 1.3630854460000137,
+                "ops": 0.7453249872896625,
+                "total": 6.708482991000011,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_open_telemetry_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_open_telemetry_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.5828401910000025,
+                "max": 1.6383390439999914,
+                "mean": 1.6132441914000026,
+                "stddev": 0.020644591557031727,
+                "rounds": 5,
+                "median": 1.616985136000011,
+                "iqr": 0.02621751124998184,
+                "q1": 1.6000598685000114,
+                "q3": 1.6262773797499932,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.5828401910000025,
+                "hd15iqr": 1.6383390439999914,
+                "ops": 0.6198689605274089,
+                "total": 8.066220957000013,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_open_tracing_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_open_tracing_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.439749656999993,
+                "max": 1.481423253999992,
+                "mean": 1.458130711199999,
+                "stddev": 0.015693430768269494,
+                "rounds": 5,
+                "median": 1.4586846830000013,
+                "iqr": 0.020451978750003263,
+                "q1": 1.4464691102499998,
+                "q3": 1.466921089000003,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.439749656999993,
+                "hd15iqr": 1.481423253999992,
+                "ops": 0.6858095727076684,
+                "total": 7.290653555999995,
+                "iterations": 1
+            }
+        }
+    ],
+    "datetime": "2023-10-24T13:23:42.215019",
+    "version": "4.0.0"
+}
\ No newline at end of file
diff --git a/benchmark/results/Linux-CPython-3.8-64bit/0023_e386d276a88766ba2658837c757040484688dfef_20231024_133437.json b/benchmark/results/Linux-CPython-3.8-64bit/0023_e386d276a88766ba2658837c757040484688dfef_20231024_133437.json
new file mode 100644
index 0000000..f2b2d92
--- /dev/null
+++ b/benchmark/results/Linux-CPython-3.8-64bit/0023_e386d276a88766ba2658837c757040484688dfef_20231024_133437.json
@@ -0,0 +1,284 @@
+{
+    "machine_info": {
+        "node": "fv-az1233-325",
+        "processor": "x86_64",
+        "machine": "x86_64",
+        "python_compiler": "GCC 11.4.0",
+        "python_implementation": "CPython",
+        "python_implementation_version": "3.8.18",
+        "python_version": "3.8.18",
+        "python_build": [
+            "default",
+            "Aug 28 2023 08:27:22"
+        ],
+        "release": "6.2.0-1014-azure",
+        "system": "Linux",
+        "cpu": {
+            "python_version": "3.8.18.final.0 (64 bit)",
+            "cpuinfo_version": [
+                9,
+                0,
+                0
+            ],
+            "cpuinfo_version_string": "9.0.0",
+            "arch": "X86_64",
+            "bits": 64,
+            "count": 2,
+            "arch_string_raw": "x86_64",
+            "vendor_id_raw": "GenuineIntel",
+            "brand_raw": "Intel(R) Xeon(R) Platinum 8171M CPU @ 2.60GHz",
+            "hz_advertised_friendly": "2.6000 GHz",
+            "hz_actual_friendly": "2.0952 GHz",
+            "hz_advertised": [
+                2600000000,
+                0
+            ],
+            "hz_actual": [
+                2095175000,
+                0
+            ],
+            "stepping": 4,
+            "model": 85,
+            "family": 6,
+            "flags": [
+                "3dnowprefetch",
+                "abm",
+                "adx",
+                "aes",
+                "apic",
+                "avx",
+                "avx2",
+                "avx512bw",
+                "avx512cd",
+                "avx512dq",
+                "avx512f",
+                "avx512vl",
+                "bmi1",
+                "bmi2",
+                "clflush",
+                "clflushopt",
+                "cmov",
+                "constant_tsc",
+                "cpuid",
+                "cx16",
+                "cx8",
+                "de",
+                "erms",
+                "f16c",
+                "fma",
+                "fpu",
+                "fsgsbase",
+                "fxsr",
+                "hle",
+                "ht",
+                "hypervisor",
+                "invpcid",
+                "invpcid_single",
+                "lahf_lm",
+                "lm",
+                "mca",
+                "mce",
+                "md_clear",
+                "mmx",
+                "movbe",
+                "msr",
+                "mtrr",
+                "nopl",
+                "nx",
+                "osxsave",
+                "pae",
+                "pat",
+                "pcid",
+                "pclmulqdq",
+                "pdpe1gb",
+                "pge",
+                "pni",
+                "popcnt",
+                "pse",
+                "pse36",
+                "pti",
+                "rdrand",
+                "rdrnd",
+                "rdseed",
+                "rdtscp",
+                "rep_good",
+                "rtm",
+                "sep",
+                "smap",
+                "smep",
+                "ss",
+                "sse",
+                "sse2",
+                "sse4_1",
+                "sse4_2",
+                "ssse3",
+                "syscall",
+                "tsc",
+                "vme",
+                "xsave",
+                "xsavec",
+                "xsaveopt",
+                "xsaves",
+                "xtopology"
+            ],
+            "l3_cache_size": 37486592,
+            "l2_cache_size": 2097152,
+            "l1_data_cache_size": 65536,
+            "l1_instruction_cache_size": 65536,
+            "l2_cache_line_size": 256,
+            "l2_cache_associativity": 6
+        }
+    },
+    "commit_info": {
+        "id": "e386d276a88766ba2658837c757040484688dfef",
+        "time": "2023-10-24T13:33:24+00:00",
+        "author_time": "2023-10-24T13:33:24+00:00",
+        "dirty": false,
+        "project": "ariadne",
+        "branch": "master"
+    },
+    "benchmarks": [
+        {
+            "group": null,
+            "name": "test_query_without_extensions",
+            "fullname": "benchmark/test_extensions.py::test_query_without_extensions",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.649046853999991,
+                "max": 1.7105205749999897,
+                "mean": 1.6799394391999982,
+                "stddev": 0.025252664048172738,
+                "rounds": 5,
+                "median": 1.6896483870000054,
+                "iqr": 0.03962047375000921,
+                "q1": 1.6565662092499949,
+                "q3": 1.696186683000004,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.649046853999991,
+                "hd15iqr": 1.7105205749999897,
+                "ops": 0.5952595532111614,
+                "total": 8.399697195999991,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_noop_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_noop_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.6902170630000057,
+                "max": 1.7566916379999782,
+                "mean": 1.7250421537999898,
+                "stddev": 0.02895260797993321,
+                "rounds": 5,
+                "median": 1.737171303999986,
+                "iqr": 0.049333399250002685,
+                "q1": 1.6966209244999888,
+                "q3": 1.7459543237499915,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.6902170630000057,
+                "hd15iqr": 1.7566916379999782,
+                "ops": 0.5796959789053046,
+                "total": 8.625210768999949,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_open_telemetry_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_open_telemetry_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 2.0274989099999914,
+                "max": 2.092992367999983,
+                "mean": 2.0618874440000012,
+                "stddev": 0.024249136540887707,
+                "rounds": 5,
+                "median": 2.0606699020000008,
+                "iqr": 0.031008258500001773,
+                "q1": 2.0476607955000077,
+                "q3": 2.0786690540000095,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 2.0274989099999914,
+                "hd15iqr": 2.092992367999983,
+                "ops": 0.48499252610027505,
+                "total": 10.309437220000007,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_open_tracing_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_open_tracing_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.8420245300000033,
+                "max": 1.9163032870000052,
+                "mean": 1.8765972739999994,
+                "stddev": 0.02773438581002328,
+                "rounds": 5,
+                "median": 1.8696777379999787,
+                "iqr": 0.03552258199998448,
+                "q1": 1.8601474917500127,
+                "q3": 1.8956700737499972,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.8420245300000033,
+                "hd15iqr": 1.9163032870000052,
+                "ops": 0.5328793843276148,
+                "total": 9.382986369999998,
+                "iterations": 1
+            }
+        }
+    ],
+    "datetime": "2023-10-24T13:35:33.569077",
+    "version": "4.0.0"
+}
\ No newline at end of file
diff --git a/benchmark/results/Linux-CPython-3.9-64bit/0022_b3013f29cdf8259b3fabb9fcc8ea116bacc4870e_20231024_132410.json b/benchmark/results/Linux-CPython-3.9-64bit/0022_b3013f29cdf8259b3fabb9fcc8ea116bacc4870e_20231024_132410.json
new file mode 100644
index 0000000..a78a33d
--- /dev/null
+++ b/benchmark/results/Linux-CPython-3.9-64bit/0022_b3013f29cdf8259b3fabb9fcc8ea116bacc4870e_20231024_132410.json
@@ -0,0 +1,285 @@
+{
+    "machine_info": {
+        "node": "fv-az309-3",
+        "processor": "x86_64",
+        "machine": "x86_64",
+        "python_compiler": "GCC 11.4.0",
+        "python_implementation": "CPython",
+        "python_implementation_version": "3.9.18",
+        "python_version": "3.9.18",
+        "python_build": [
+            "main",
+            "Aug 28 2023 08:38:32"
+        ],
+        "release": "6.2.0-1014-azure",
+        "system": "Linux",
+        "cpu": {
+            "python_version": "3.9.18.final.0 (64 bit)",
+            "cpuinfo_version": [
+                9,
+                0,
+                0
+            ],
+            "cpuinfo_version_string": "9.0.0",
+            "arch": "X86_64",
+            "bits": 64,
+            "count": 2,
+            "arch_string_raw": "x86_64",
+            "vendor_id_raw": "GenuineIntel",
+            "brand_raw": "Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz",
+            "hz_advertised_friendly": "2.6000 GHz",
+            "hz_actual_friendly": "2.5939 GHz",
+            "hz_advertised": [
+                2600000000,
+                0
+            ],
+            "hz_actual": [
+                2593907000,
+                0
+            ],
+            "stepping": 7,
+            "model": 85,
+            "family": 6,
+            "flags": [
+                "3dnowprefetch",
+                "abm",
+                "adx",
+                "aes",
+                "apic",
+                "avx",
+                "avx2",
+                "avx512bw",
+                "avx512cd",
+                "avx512dq",
+                "avx512f",
+                "avx512vl",
+                "bmi1",
+                "bmi2",
+                "clflush",
+                "clflushopt",
+                "cmov",
+                "constant_tsc",
+                "cpuid",
+                "cx16",
+                "cx8",
+                "de",
+                "erms",
+                "f16c",
+                "fma",
+                "fpu",
+                "fsgsbase",
+                "fxsr",
+                "hle",
+                "ht",
+                "hypervisor",
+                "invpcid",
+                "invpcid_single",
+                "lahf_lm",
+                "lm",
+                "mca",
+                "mce",
+                "md_clear",
+                "mmx",
+                "movbe",
+                "mpx",
+                "msr",
+                "mtrr",
+                "nopl",
+                "nx",
+                "osxsave",
+                "pae",
+                "pat",
+                "pcid",
+                "pclmulqdq",
+                "pdpe1gb",
+                "pge",
+                "pni",
+                "popcnt",
+                "pse",
+                "pse36",
+                "pti",
+                "rdrand",
+                "rdrnd",
+                "rdseed",
+                "rdtscp",
+                "rep_good",
+                "rtm",
+                "sep",
+                "smap",
+                "smep",
+                "ss",
+                "sse",
+                "sse2",
+                "sse4_1",
+                "sse4_2",
+                "ssse3",
+                "syscall",
+                "tsc",
+                "vme",
+                "xsave",
+                "xsavec",
+                "xsaveopt",
+                "xsaves",
+                "xtopology"
+            ],
+            "l3_cache_size": 37486592,
+            "l2_cache_size": 2097152,
+            "l1_data_cache_size": 65536,
+            "l1_instruction_cache_size": 65536,
+            "l2_cache_line_size": 256,
+            "l2_cache_associativity": 6
+        }
+    },
+    "commit_info": {
+        "id": "b3013f29cdf8259b3fabb9fcc8ea116bacc4870e",
+        "time": "2023-10-24T13:23:42+00:00",
+        "author_time": "2023-10-24T13:23:42+00:00",
+        "dirty": false,
+        "project": "ariadne",
+        "branch": "master"
+    },
+    "benchmarks": [
+        {
+            "group": null,
+            "name": "test_query_without_extensions",
+            "fullname": "benchmark/test_extensions.py::test_query_without_extensions",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.2190204460000018,
+                "max": 1.2781704970000192,
+                "mean": 1.2486290896000072,
+                "stddev": 0.02530449985729843,
+                "rounds": 5,
+                "median": 1.2451803220000102,
+                "iqr": 0.04467158599998555,
+                "q1": 1.2276033935000115,
+                "q3": 1.272274979499997,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.2190204460000018,
+                "hd15iqr": 1.2781704970000192,
+                "ops": 0.8008783459628878,
+                "total": 6.2431454480000355,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_noop_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_noop_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.229186819000006,
+                "max": 1.2966992769999877,
+                "mean": 1.2652028427999995,
+                "stddev": 0.02615784544165,
+                "rounds": 5,
+                "median": 1.2711415010000167,
+                "iqr": 0.038393512250003425,
+                "q1": 1.2449089872499925,
+                "q3": 1.283302499499996,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.229186819000006,
+                "hd15iqr": 1.2966992769999877,
+                "ops": 0.7903870953901089,
+                "total": 6.326014213999997,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_open_telemetry_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_open_telemetry_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.4881390129999943,
+                "max": 1.5450591709999912,
+                "mean": 1.5206631891999962,
+                "stddev": 0.022918073518628845,
+                "rounds": 5,
+                "median": 1.5200150389999862,
+                "iqr": 0.035681460750005556,
+                "q1": 1.5050975637499988,
+                "q3": 1.5407790245000044,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.4881390129999943,
+                "hd15iqr": 1.5450591709999912,
+                "ops": 0.6576078168408146,
+                "total": 7.603315945999981,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_open_tracing_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_open_tracing_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.55532424499998,
+                "max": 1.608330833999986,
+                "mean": 1.5776711581999905,
+                "stddev": 0.022640084429923813,
+                "rounds": 5,
+                "median": 1.5789388899999892,
+                "iqr": 0.03842738025001324,
+                "q1": 1.555903877999988,
+                "q3": 1.5943312582500013,
+                "iqr_outliers": 0,
+                "stddev_outliers": 1,
+                "outliers": "1;0",
+                "ld15iqr": 1.55532424499998,
+                "hd15iqr": 1.608330833999986,
+                "ops": 0.6338456495211132,
+                "total": 7.888355790999952,
+                "iterations": 1
+            }
+        }
+    ],
+    "datetime": "2023-10-24T13:24:52.958984",
+    "version": "4.0.0"
+}
\ No newline at end of file
diff --git a/benchmark/results/Linux-CPython-3.9-64bit/0023_8a0b2b50e0bc5c5ce8ac6afa564fc223824faea6_20231024_133729.json b/benchmark/results/Linux-CPython-3.9-64bit/0023_8a0b2b50e0bc5c5ce8ac6afa564fc223824faea6_20231024_133729.json
new file mode 100644
index 0000000..1fd45e9
--- /dev/null
+++ b/benchmark/results/Linux-CPython-3.9-64bit/0023_8a0b2b50e0bc5c5ce8ac6afa564fc223824faea6_20231024_133729.json
@@ -0,0 +1,270 @@
+{
+    "machine_info": {
+        "node": "fv-az422-305",
+        "processor": "x86_64",
+        "machine": "x86_64",
+        "python_compiler": "GCC 11.4.0",
+        "python_implementation": "CPython",
+        "python_implementation_version": "3.9.18",
+        "python_version": "3.9.18",
+        "python_build": [
+            "main",
+            "Aug 28 2023 08:38:32"
+        ],
+        "release": "6.2.0-1014-azure",
+        "system": "Linux",
+        "cpu": {
+            "python_version": "3.9.18.final.0 (64 bit)",
+            "cpuinfo_version": [
+                9,
+                0,
+                0
+            ],
+            "cpuinfo_version_string": "9.0.0",
+            "arch": "X86_64",
+            "bits": 64,
+            "count": 2,
+            "arch_string_raw": "x86_64",
+            "vendor_id_raw": "GenuineIntel",
+            "brand_raw": "Intel(R) Xeon(R) CPU E5-2673 v3 @ 2.40GHz",
+            "hz_advertised_friendly": "2.4000 GHz",
+            "hz_actual_friendly": "2.3945 GHz",
+            "hz_advertised": [
+                2400000000,
+                0
+            ],
+            "hz_actual": [
+                2394455000,
+                0
+            ],
+            "stepping": 2,
+            "model": 63,
+            "family": 6,
+            "flags": [
+                "abm",
+                "aes",
+                "apic",
+                "avx",
+                "avx2",
+                "bmi1",
+                "bmi2",
+                "clflush",
+                "cmov",
+                "constant_tsc",
+                "cpuid",
+                "cx16",
+                "cx8",
+                "de",
+                "erms",
+                "f16c",
+                "fma",
+                "fpu",
+                "fsgsbase",
+                "fxsr",
+                "ht",
+                "hypervisor",
+                "invpcid",
+                "invpcid_single",
+                "lahf_lm",
+                "lm",
+                "mca",
+                "mce",
+                "md_clear",
+                "mmx",
+                "movbe",
+                "msr",
+                "mtrr",
+                "nopl",
+                "nx",
+                "osxsave",
+                "pae",
+                "pat",
+                "pcid",
+                "pclmulqdq",
+                "pdpe1gb",
+                "pge",
+                "pni",
+                "popcnt",
+                "pse",
+                "pse36",
+                "pti",
+                "rdrand",
+                "rdrnd",
+                "rdtscp",
+                "rep_good",
+                "sep",
+                "smep",
+                "ss",
+                "sse",
+                "sse2",
+                "sse4_1",
+                "sse4_2",
+                "ssse3",
+                "syscall",
+                "tsc",
+                "vme",
+                "xsave",
+                "xsaveopt",
+                "xtopology"
+            ],
+            "l3_cache_size": 31457280,
+            "l2_cache_size": 524288,
+            "l1_data_cache_size": 65536,
+            "l1_instruction_cache_size": 65536,
+            "l2_cache_line_size": 256,
+            "l2_cache_associativity": 6
+        }
+    },
+    "commit_info": {
+        "id": "8a0b2b50e0bc5c5ce8ac6afa564fc223824faea6",
+        "time": "2023-10-24T13:35:33+00:00",
+        "author_time": "2023-10-24T13:35:33+00:00",
+        "dirty": false,
+        "project": "ariadne",
+        "branch": "master"
+    },
+    "benchmarks": [
+        {
+            "group": null,
+            "name": "test_query_without_extensions",
+            "fullname": "benchmark/test_extensions.py::test_query_without_extensions",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.5634898570000075,
+                "max": 1.7616455790000032,
+                "mean": 1.6515733028,
+                "stddev": 0.07217861261116912,
+                "rounds": 5,
+                "median": 1.6557776539999907,
+                "iqr": 0.07559948500000502,
+                "q1": 1.6066997209999982,
+                "q3": 1.6822992060000033,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.5634898570000075,
+                "hd15iqr": 1.7616455790000032,
+                "ops": 0.6054832675635086,
+                "total": 8.257866514,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_noop_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_noop_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.6248173120000047,
+                "max": 1.7134689709999975,
+                "mean": 1.670496831600002,
+                "stddev": 0.03218809678811772,
+                "rounds": 5,
+                "median": 1.6706544500000007,
+                "iqr": 0.03745245300000022,
+                "q1": 1.6523883432500028,
+                "q3": 1.689840796250003,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.6248173120000047,
+                "hd15iqr": 1.7134689709999975,
+                "ops": 0.5986243021138806,
+                "total": 8.35248415800001,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_open_telemetry_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_open_telemetry_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.9711156229999744,
+                "max": 2.203345313,
+                "mean": 2.0627896427999928,
+                "stddev": 0.09856278100195176,
+                "rounds": 5,
+                "median": 2.0549051319999876,
+                "iqr": 0.1630355449999925,
+                "q1": 1.9720081492500015,
+                "q3": 2.135043694249994,
+                "iqr_outliers": 0,
+                "stddev_outliers": 1,
+                "outliers": "1;0",
+                "ld15iqr": 1.9711156229999744,
+                "hd15iqr": 2.203345313,
+                "ops": 0.4847804057434661,
+                "total": 10.313948213999964,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_open_tracing_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_open_tracing_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.9024634130000209,
+                "max": 1.9747007759999917,
+                "mean": 1.9340883157999997,
+                "stddev": 0.029509844346884445,
+                "rounds": 5,
+                "median": 1.938693440999998,
+                "iqr": 0.04652437649998831,
+                "q1": 1.9068523162500028,
+                "q3": 1.9533766927499912,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.9024634130000209,
+                "hd15iqr": 1.9747007759999917,
+                "ops": 0.5170394711713919,
+                "total": 9.670441578999998,
+                "iterations": 1
+            }
+        }
+    ],
+    "datetime": "2023-10-24T13:38:24.354320",
+    "version": "4.0.0"
+}
\ No newline at end of file


Test patch:
diff --git a/benchmark/results/Linux-CPython-3.11-64bit/0022_42074f0e3615fba4f8cec46d1ffae2e91a713c9c_20231024_132701.json b/benchmark/results/Linux-CPython-3.11-64bit/0022_42074f0e3615fba4f8cec46d1ffae2e91a713c9c_20231024_132701.json
new file mode 100644
index 0000000..9cbe4ed
--- /dev/null
+++ b/benchmark/results/Linux-CPython-3.11-64bit/0022_42074f0e3615fba4f8cec46d1ffae2e91a713c9c_20231024_132701.json
@@ -0,0 +1,284 @@
+{
+    "machine_info": {
+        "node": "fv-az395-589",
+        "processor": "x86_64",
+        "machine": "x86_64",
+        "python_compiler": "GCC 11.4.0",
+        "python_implementation": "CPython",
+        "python_implementation_version": "3.11.6",
+        "python_version": "3.11.6",
+        "python_build": [
+            "main",
+            "Oct  3 2023 04:42:57"
+        ],
+        "release": "6.2.0-1014-azure",
+        "system": "Linux",
+        "cpu": {
+            "python_version": "3.11.6.final.0 (64 bit)",
+            "cpuinfo_version": [
+                9,
+                0,
+                0
+            ],
+            "cpuinfo_version_string": "9.0.0",
+            "arch": "X86_64",
+            "bits": 64,
+            "count": 2,
+            "arch_string_raw": "x86_64",
+            "vendor_id_raw": "GenuineIntel",
+            "brand_raw": "Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz",
+            "hz_advertised_friendly": "2.8000 GHz",
+            "hz_actual_friendly": "2.7934 GHz",
+            "hz_advertised": [
+                2800000000,
+                0
+            ],
+            "hz_actual": [
+                2793437000,
+                0
+            ],
+            "stepping": 6,
+            "model": 106,
+            "family": 6,
+            "flags": [
+                "3dnowprefetch",
+                "abm",
+                "adx",
+                "aes",
+                "apic",
+                "avx",
+                "avx2",
+                "avx512bw",
+                "avx512cd",
+                "avx512dq",
+                "avx512f",
+                "avx512vl",
+                "bmi1",
+                "bmi2",
+                "clflush",
+                "clflushopt",
+                "cmov",
+                "constant_tsc",
+                "cpuid",
+                "cx16",
+                "cx8",
+                "de",
+                "erms",
+                "f16c",
+                "fma",
+                "fpu",
+                "fsgsbase",
+                "fxsr",
+                "hle",
+                "ht",
+                "hypervisor",
+                "invpcid",
+                "invpcid_single",
+                "lahf_lm",
+                "lm",
+                "mca",
+                "mce",
+                "md_clear",
+                "mmx",
+                "movbe",
+                "msr",
+                "mtrr",
+                "nopl",
+                "nx",
+                "osxsave",
+                "pae",
+                "pat",
+                "pcid",
+                "pclmulqdq",
+                "pdpe1gb",
+                "pge",
+                "pni",
+                "popcnt",
+                "pse",
+                "pse36",
+                "pti",
+                "rdrand",
+                "rdrnd",
+                "rdseed",
+                "rdtscp",
+                "rep_good",
+                "rtm",
+                "sep",
+                "smap",
+                "smep",
+                "ss",
+                "sse",
+                "sse2",
+                "sse4_1",
+                "sse4_2",
+                "ssse3",
+                "syscall",
+                "tsc",
+                "vme",
+                "xsave",
+                "xsavec",
+                "xsaveopt",
+                "xsaves",
+                "xtopology"
+            ],
+            "l3_cache_size": 50331648,
+            "l2_cache_size": "2.5 MiB",
+            "l1_data_cache_size": 98304,
+            "l1_instruction_cache_size": 65536,
+            "l2_cache_line_size": 256,
+            "l2_cache_associativity": 6
+        }
+    },
+    "commit_info": {
+        "id": "42074f0e3615fba4f8cec46d1ffae2e91a713c9c",
+        "time": "2023-10-24T13:26:26+00:00",
+        "author_time": "2023-10-24T13:26:26+00:00",
+        "dirty": false,
+        "project": "ariadne",
+        "branch": "master"
+    },
+    "benchmarks": [
+        {
+            "group": null,
+            "name": "test_query_without_extensions",
+            "fullname": "benchmark/test_extensions.py::test_query_without_extensions",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.0454940950000093,
+                "max": 1.1036979910000184,
+                "mean": 1.071212337600008,
+                "stddev": 0.022626564087262716,
+                "rounds": 5,
+                "median": 1.0638262260000033,
+                "iqr": 0.03218327750000327,
+                "q1": 1.056198638000005,
+                "q3": 1.0883819155000083,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.0454940950000093,
+                "hd15iqr": 1.1036979910000184,
+                "ops": 0.9335217350468954,
+                "total": 5.35606168800004,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_noop_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_noop_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.0531387300000006,
+                "max": 1.1221798300000216,
+                "mean": 1.1005271586000105,
+                "stddev": 0.028236539272916417,
+                "rounds": 5,
+                "median": 1.1026557010000033,
+                "iqr": 0.031939071000017805,
+                "q1": 1.0901933590000041,
+                "q3": 1.122132430000022,
+                "iqr_outliers": 0,
+                "stddev_outliers": 1,
+                "outliers": "1;0",
+                "ld15iqr": 1.0531387300000006,
+                "hd15iqr": 1.1221798300000216,
+                "ops": 0.9086554495139475,
+                "total": 5.502635793000053,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_open_telemetry_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_open_telemetry_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.2843037929999923,
+                "max": 1.3108633270000212,
+                "mean": 1.3009426740000039,
+                "stddev": 0.010993825996397394,
+                "rounds": 5,
+                "median": 1.3043286179999996,
+                "iqr": 0.01676729699999413,
+                "q1": 1.2929688535000068,
+                "q3": 1.309736150500001,
+                "iqr_outliers": 0,
+                "stddev_outliers": 1,
+                "outliers": "1;0",
+                "ld15iqr": 1.2843037929999923,
+                "hd15iqr": 1.3108633270000212,
+                "ops": 0.7686733781476347,
+                "total": 6.504713370000019,
+                "iterations": 1
+            }
+        },
+        {
+            "group": null,
+            "name": "test_query_with_open_tracing_extension",
+            "fullname": "benchmark/test_extensions.py::test_query_with_open_tracing_extension",
+            "params": null,
+            "param": null,
+            "extra_info": {},
+            "options": {
+                "disable_gc": false,
+                "timer": "perf_counter",
+                "min_rounds": 5,
+                "max_time": 1.0,
+                "min_time": 5e-06,
+                "warmup": false
+            },
+            "stats": {
+                "min": 1.1754369140000165,
+                "max": 1.207919406000002,
+                "mean": 1.1888751612000021,
+                "stddev": 0.012841606999628762,
+                "rounds": 5,
+                "median": 1.1863044269999818,
+                "iqr": 0.0189965357499986,
+                "q1": 1.178939419250007,
+                "q3": 1.1979359550000055,
+                "iqr_outliers": 0,
+                "stddev_outliers": 2,
+                "outliers": "2;0",
+                "ld15iqr": 1.1754369140000165,
+                "hd15iqr": 1.207919406000002,
+                "ops": 0.8411312075782967,
+                "total": 5.944375806000011,
+                "iterations": 1
+            }
+        }
+    ],
+    "datetime": "2023-10-24T13:27:36.925230",
+    "version": "4.0.0"
+}
\ No newline at end of file
diff --git a/tests/asgi/snapshots/snap_test_explorer.py b/tests/asgi/snapshots/snap_test_explorer.py
index 7d39910..742da3d 100644
--- a/tests/asgi/snapshots/snap_test_explorer.py
+++ b/tests/asgi/snapshots/snap_test_explorer.py
@@ -108,6 +108,9 @@ snapshots['test_default_explorer_html_is_served_on_get_request 1'] = '''<!--
     <script>
       var fetcher = GraphiQL.createFetcher({
         url: window.location.href,
+        
+        subscriptionUrl: (window.location.protocol === "https:" ? "wss" : "ws") + "://" + window.location.host + window.location.pathname,
+        
       });
 
       function AriadneGraphiQL() {
@@ -198,6 +201,9 @@ snapshots['test_graphiql_html_is_served_on_get_request 1'] = '''<!--
     <script>
       var fetcher = GraphiQL.createFetcher({
         url: window.location.href,
+        
+        subscriptionUrl: (window.location.protocol === "https:" ? "wss" : "ws") + "://" + window.location.host + window.location.pathname,
+        
       });
 
       function AriadneGraphiQL() {
diff --git a/tests/explorers/snapshots/snap_test_explorers.py b/tests/explorers/snapshots/snap_test_explorers.py
index 8457414..a5de6fc 100644
--- a/tests/explorers/snapshots/snap_test_explorers.py
+++ b/tests/explorers/snapshots/snap_test_explorers.py
@@ -113,6 +113,9 @@ snapshots['test_graphiql_explorer_includes_explorer_plugin 1'] = '''<!--
     <script>
       var fetcher = GraphiQL.createFetcher({
         url: window.location.href,
+        
+        subscriptionUrl: (window.location.protocol === "https:" ? "wss" : "ws") + "://" + window.location.host + window.location.pathname,
+        
       });
 
       function AriadneGraphiQL() {
@@ -145,6 +148,99 @@ snapshots['test_graphiql_explorer_includes_explorer_plugin 1'] = '''<!--
 </html>
 '''
 
+snapshots['test_graphiql_explorer_with_custom_subscription_url 1'] = '''<!--
+ *  Copyright (c) 2021 GraphQL Contributors
+ *  All rights reserved.
+ *
+ *  This source code is licensed under the license found in the
+ *  LICENSE file in the root directory of this source tree.
+-->
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
+    <title>Ariadne GraphQL</title>
+    <style>
+      body {
+        height: 100%;
+        margin: 0;
+        width: 100%;
+        overflow: hidden;
+      }
+
+      #graphiql {
+        height: 100vh;
+      }
+
+      #graphiql-loading {
+        height: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+
+        color: #545454;
+        font-size: 1.5em;
+        font-family: sans-serif;
+        font-weight: bold;
+      }
+    </style>
+    <link rel="stylesheet" href="https://unpkg.com/graphiql@3.0.0/graphiql.min.css" />
+    
+  </head>
+
+  <body>
+    <div id="graphiql">
+      <div id="graphiql-loading">Loading Ariadne GraphQL...</div>
+    </div>
+
+    <script
+      crossorigin
+      src="https://unpkg.com/react@17/umd/react.production.min.js"
+    ></script>
+    <script
+      crossorigin
+      src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"
+    ></script>
+
+    <script
+      crossorigin
+      src="https://unpkg.com/graphiql@3.0.0/graphiql.min.js"
+    ></script>
+
+    
+
+    <script>
+      var fetcher = GraphiQL.createFetcher({
+        url: window.location.href,
+        
+        subscriptionUrl: "ws://custom_url",
+        
+      });
+
+      function AriadneGraphiQL() {
+        var [query, setQuery] = React.useState(
+          \'#\\n# GraphiQL is an in -browser tool for writing, validating, and\\n# testing GraphQL queries.\\n#\\n# Type queries into this side of the screen, and you will see intelligent\\n# typeaheads aware of the current GraphQL type schema and live syntax and\\n# validation errors highlighted within the text.\\n#\\n# GraphQL queries typically start with a "{" character. Lines that start\\n# with a # are ignored.\\n#\\n# An example GraphQL query might look like:\\n#\\n#     {\\n#       field(arg: "value") {\\n#         subField\\n#\\n#       }\\n#\\n#     }\\n#\\n# Keyboard shortcuts:\\n#\\n#   Prettify query: Shift - Ctrl - P(or press the prettify button)\\n#\\n#  Merge fragments: Shift - Ctrl - M(or press the merge button)\\n#\\n#        Run Query: Ctrl - Enter(or press the play button)\\n#\\n#    Auto Complete: Ctrl - Space(or just start typing)\\n#\',
+        );
+        
+        return React.createElement(GraphiQL, {
+          fetcher: fetcher,
+          defaultEditorToolsVisibility: true,
+          
+          query: query,
+          onEditQuery: setQuery,
+        });
+      }
+
+      ReactDOM.render(
+        React.createElement(AriadneGraphiQL),
+        document.getElementById('graphiql'),
+      );
+    </script>
+  </body>
+</html>
+'''
+
 snapshots['test_graphiql_explorer_produces_html 1'] = '''<!--
  *  Copyright (c) 2021 GraphQL Contributors
  *  All rights reserved.
@@ -210,6 +306,9 @@ snapshots['test_graphiql_explorer_produces_html 1'] = '''<!--
     <script>
       var fetcher = GraphiQL.createFetcher({
         url: window.location.href,
+        
+        subscriptionUrl: (window.location.protocol === "https:" ? "wss" : "ws") + "://" + window.location.host + window.location.pathname,
+        
       });
 
       function AriadneGraphiQL() {
diff --git a/tests/explorers/test_explorers.py b/tests/explorers/test_explorers.py
index e0e0379..fbf35b4 100644
--- a/tests/explorers/test_explorers.py
+++ b/tests/explorers/test_explorers.py
@@ -21,6 +21,11 @@ def test_graphiql_explorer_includes_explorer_plugin(snapshot):
     snapshot.assert_match(explorer.html(None))
 
 
+def test_graphiql_explorer_with_custom_subscription_url(snapshot):
+    explorer = ExplorerGraphiQL(subscription_url="ws://custom_url")
+    snapshot.assert_match(explorer.html(None))
+
+
 def test_playground_explorer_produces_html(snapshot):
     explorer = ExplorerPlayground()
     snapshot.assert_match(explorer.html(None))
diff --git a/tests/wsgi/snapshots/snap_test_explorer.py b/tests/wsgi/snapshots/snap_test_explorer.py
index 2725e97..d2bddb1 100644
--- a/tests/wsgi/snapshots/snap_test_explorer.py
+++ b/tests/wsgi/snapshots/snap_test_explorer.py
@@ -15,11 +15,11 @@ snapshots['test_apollo_html_is_served_on_get_request 1'] = [
 ]
 
 snapshots['test_default_explorer_html_is_served_on_get_request 1'] = [
-    b'<!--\n *  Copyright (c) 2021 GraphQL Contributors\n *  All rights reserved.\n *\n *  This source code is licensed under the license found in the\n *  LICENSE file in the root directory of this source tree.\n-->\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset="utf-8" />\n    <meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">\n    <title>Ariadne GraphQL</title>\n    <style>\n      body {\n        height: 100%;\n        margin: 0;\n        width: 100%;\n        overflow: hidden;\n      }\n\n      #graphiql {\n        height: 100vh;\n      }\n\n      #graphiql-loading {\n        height: 100%;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n\n        color: #545454;\n        font-size: 1.5em;\n        font-family: sans-serif;\n        font-weight: bold;\n      }\n    </style>\n    <link rel="stylesheet" href="https://unpkg.com/graphiql@3.0.0/graphiql.min.css" />\n    \n  </head>\n\n  <body>\n    <div id="graphiql">\n      <div id="graphiql-loading">Loading Ariadne GraphQL...</div>\n    </div>\n\n    <script\n      crossorigin\n      src="https://unpkg.com/react@17/umd/react.production.min.js"\n    ></script>\n    <script\n      crossorigin\n      src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"\n    ></script>\n\n    <script\n      crossorigin\n      src="https://unpkg.com/graphiql@3.0.0/graphiql.min.js"\n    ></script>\n\n    \n\n    <script>\n      var fetcher = GraphiQL.createFetcher({\n        url: window.location.href,\n      });\n\n      function AriadneGraphiQL() {\n        var [query, setQuery] = React.useState(\n          \'#\\n# GraphiQL is an in -browser tool for writing, validating, and\\n# testing GraphQL queries.\\n#\\n# Type queries into this side of the screen, and you will see intelligent\\n# typeaheads aware of the current GraphQL type schema and live syntax and\\n# validation errors highlighted within the text.\\n#\\n# GraphQL queries typically start with a "{" character. Lines that start\\n# with a # are ignored.\\n#\\n# An example GraphQL query might look like:\\n#\\n#     {\\n#       field(arg: "value") {\\n#         subField\\n#\\n#       }\\n#\\n#     }\\n#\\n# Keyboard shortcuts:\\n#\\n#   Prettify query: Shift - Ctrl - P(or press the prettify button)\\n#\\n#  Merge fragments: Shift - Ctrl - M(or press the merge button)\\n#\\n#        Run Query: Ctrl - Enter(or press the play button)\\n#\\n#    Auto Complete: Ctrl - Space(or just start typing)\\n#\',\n        );\n        \n        return React.createElement(GraphiQL, {\n          fetcher: fetcher,\n          defaultEditorToolsVisibility: true,\n          \n          query: query,\n          onEditQuery: setQuery,\n        });\n      }\n\n      ReactDOM.render(\n        React.createElement(AriadneGraphiQL),\n        document.getElementById(\'graphiql\'),\n      );\n    </script>\n  </body>\n</html>\n'
+    b'<!--\n *  Copyright (c) 2021 GraphQL Contributors\n *  All rights reserved.\n *\n *  This source code is licensed under the license found in the\n *  LICENSE file in the root directory of this source tree.\n-->\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset="utf-8" />\n    <meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">\n    <title>Ariadne GraphQL</title>\n    <style>\n      body {\n        height: 100%;\n        margin: 0;\n        width: 100%;\n        overflow: hidden;\n      }\n\n      #graphiql {\n        height: 100vh;\n      }\n\n      #graphiql-loading {\n        height: 100%;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n\n        color: #545454;\n        font-size: 1.5em;\n        font-family: sans-serif;\n        font-weight: bold;\n      }\n    </style>\n    <link rel="stylesheet" href="https://unpkg.com/graphiql@3.0.0/graphiql.min.css" />\n    \n  </head>\n\n  <body>\n    <div id="graphiql">\n      <div id="graphiql-loading">Loading Ariadne GraphQL...</div>\n    </div>\n\n    <script\n      crossorigin\n      src="https://unpkg.com/react@17/umd/react.production.min.js"\n    ></script>\n    <script\n      crossorigin\n      src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"\n    ></script>\n\n    <script\n      crossorigin\n      src="https://unpkg.com/graphiql@3.0.0/graphiql.min.js"\n    ></script>\n\n    \n\n    <script>\n      var fetcher = GraphiQL.createFetcher({\n        url: window.location.href,\n        \n        subscriptionUrl: (window.location.protocol === "https:" ? "wss" : "ws") + "://" + window.location.host + window.location.pathname,\n        \n      });\n\n      function AriadneGraphiQL() {\n        var [query, setQuery] = React.useState(\n          \'#\\n# GraphiQL is an in -browser tool for writing, validating, and\\n# testing GraphQL queries.\\n#\\n# Type queries into this side of the screen, and you will see intelligent\\n# typeaheads aware of the current GraphQL type schema and live syntax and\\n# validation errors highlighted within the text.\\n#\\n# GraphQL queries typically start with a "{" character. Lines that start\\n# with a # are ignored.\\n#\\n# An example GraphQL query might look like:\\n#\\n#     {\\n#       field(arg: "value") {\\n#         subField\\n#\\n#       }\\n#\\n#     }\\n#\\n# Keyboard shortcuts:\\n#\\n#   Prettify query: Shift - Ctrl - P(or press the prettify button)\\n#\\n#  Merge fragments: Shift - Ctrl - M(or press the merge button)\\n#\\n#        Run Query: Ctrl - Enter(or press the play button)\\n#\\n#    Auto Complete: Ctrl - Space(or just start typing)\\n#\',\n        );\n        \n        return React.createElement(GraphiQL, {\n          fetcher: fetcher,\n          defaultEditorToolsVisibility: true,\n          \n          query: query,\n          onEditQuery: setQuery,\n        });\n      }\n\n      ReactDOM.render(\n        React.createElement(AriadneGraphiQL),\n        document.getElementById(\'graphiql\'),\n      );\n    </script>\n  </body>\n</html>\n'
 ]
 
 snapshots['test_graphiql_html_is_served_on_get_request 1'] = [
-    b'<!--\n *  Copyright (c) 2021 GraphQL Contributors\n *  All rights reserved.\n *\n *  This source code is licensed under the license found in the\n *  LICENSE file in the root directory of this source tree.\n-->\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset="utf-8" />\n    <meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">\n    <title>Ariadne GraphQL</title>\n    <style>\n      body {\n        height: 100%;\n        margin: 0;\n        width: 100%;\n        overflow: hidden;\n      }\n\n      #graphiql {\n        height: 100vh;\n      }\n\n      #graphiql-loading {\n        height: 100%;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n\n        color: #545454;\n        font-size: 1.5em;\n        font-family: sans-serif;\n        font-weight: bold;\n      }\n    </style>\n    <link rel="stylesheet" href="https://unpkg.com/graphiql@3.0.0/graphiql.min.css" />\n    \n  </head>\n\n  <body>\n    <div id="graphiql">\n      <div id="graphiql-loading">Loading Ariadne GraphQL...</div>\n    </div>\n\n    <script\n      crossorigin\n      src="https://unpkg.com/react@17/umd/react.production.min.js"\n    ></script>\n    <script\n      crossorigin\n      src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"\n    ></script>\n\n    <script\n      crossorigin\n      src="https://unpkg.com/graphiql@3.0.0/graphiql.min.js"\n    ></script>\n\n    \n\n    <script>\n      var fetcher = GraphiQL.createFetcher({\n        url: window.location.href,\n      });\n\n      function AriadneGraphiQL() {\n        var [query, setQuery] = React.useState(\n          \'#\\n# GraphiQL is an in -browser tool for writing, validating, and\\n# testing GraphQL queries.\\n#\\n# Type queries into this side of the screen, and you will see intelligent\\n# typeaheads aware of the current GraphQL type schema and live syntax and\\n# validation errors highlighted within the text.\\n#\\n# GraphQL queries typically start with a "{" character. Lines that start\\n# with a # are ignored.\\n#\\n# An example GraphQL query might look like:\\n#\\n#     {\\n#       field(arg: "value") {\\n#         subField\\n#\\n#       }\\n#\\n#     }\\n#\\n# Keyboard shortcuts:\\n#\\n#   Prettify query: Shift - Ctrl - P(or press the prettify button)\\n#\\n#  Merge fragments: Shift - Ctrl - M(or press the merge button)\\n#\\n#        Run Query: Ctrl - Enter(or press the play button)\\n#\\n#    Auto Complete: Ctrl - Space(or just start typing)\\n#\',\n        );\n        \n        return React.createElement(GraphiQL, {\n          fetcher: fetcher,\n          defaultEditorToolsVisibility: true,\n          \n          query: query,\n          onEditQuery: setQuery,\n        });\n      }\n\n      ReactDOM.render(\n        React.createElement(AriadneGraphiQL),\n        document.getElementById(\'graphiql\'),\n      );\n    </script>\n  </body>\n</html>\n'
+    b'<!--\n *  Copyright (c) 2021 GraphQL Contributors\n *  All rights reserved.\n *\n *  This source code is licensed under the license found in the\n *  LICENSE file in the root directory of this source tree.\n-->\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset="utf-8" />\n    <meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">\n    <title>Ariadne GraphQL</title>\n    <style>\n      body {\n        height: 100%;\n        margin: 0;\n        width: 100%;\n        overflow: hidden;\n      }\n\n      #graphiql {\n        height: 100vh;\n      }\n\n      #graphiql-loading {\n        height: 100%;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n\n        color: #545454;\n        font-size: 1.5em;\n        font-family: sans-serif;\n        font-weight: bold;\n      }\n    </style>\n    <link rel="stylesheet" href="https://unpkg.com/graphiql@3.0.0/graphiql.min.css" />\n    \n  </head>\n\n  <body>\n    <div id="graphiql">\n      <div id="graphiql-loading">Loading Ariadne GraphQL...</div>\n    </div>\n\n    <script\n      crossorigin\n      src="https://unpkg.com/react@17/umd/react.production.min.js"\n    ></script>\n    <script\n      crossorigin\n      src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"\n    ></script>\n\n    <script\n      crossorigin\n      src="https://unpkg.com/graphiql@3.0.0/graphiql.min.js"\n    ></script>\n\n    \n\n    <script>\n      var fetcher = GraphiQL.createFetcher({\n        url: window.location.href,\n        \n        subscriptionUrl: (window.location.protocol === "https:" ? "wss" : "ws") + "://" + window.location.host + window.location.pathname,\n        \n      });\n\n      function AriadneGraphiQL() {\n        var [query, setQuery] = React.useState(\n          \'#\\n# GraphiQL is an in -browser tool for writing, validating, and\\n# testing GraphQL queries.\\n#\\n# Type queries into this side of the screen, and you will see intelligent\\n# typeaheads aware of the current GraphQL type schema and live syntax and\\n# validation errors highlighted within the text.\\n#\\n# GraphQL queries typically start with a "{" character. Lines that start\\n# with a # are ignored.\\n#\\n# An example GraphQL query might look like:\\n#\\n#     {\\n#       field(arg: "value") {\\n#         subField\\n#\\n#       }\\n#\\n#     }\\n#\\n# Keyboard shortcuts:\\n#\\n#   Prettify query: Shift - Ctrl - P(or press the prettify button)\\n#\\n#  Merge fragments: Shift - Ctrl - M(or press the merge button)\\n#\\n#        Run Query: Ctrl - Enter(or press the play button)\\n#\\n#    Auto Complete: Ctrl - Space(or just start typing)\\n#\',\n        );\n        \n        return React.createElement(GraphiQL, {\n          fetcher: fetcher,\n          defaultEditorToolsVisibility: true,\n          \n          query: query,\n          onEditQuery: setQuery,\n        });\n      }\n\n      ReactDOM.render(\n        React.createElement(AriadneGraphiQL),\n        document.getElementById(\'graphiql\'),\n      );\n    </script>\n  </body>\n</html>\n'
 ]
 
 snapshots['test_playground_html_is_served_on_get_request 1'] = [