Incompatible with GraphQL.Server Metrics/Instrumentation
AzureMarker opened this issue · 4 comments
When using GraphQL.Conventions with GraphQL.Server, the following error occurs during the first GraphQL request:
GraphQL Error: Unable to cast object of type 'GraphQL.Instrumentation.InstrumentFieldsMiddleware' to type 'GraphQL.Types.IGraphType'.
at GraphQL.Conventions.Adapters.GraphTypeAdapter.DeriveTypeFromTypeInfo(Type type)
at GraphQL.FuncServiceProvider.GetService(Type type) in /_/src/GraphQL/DI/FuncServiceProvider.cs:line 27
at GraphQL.Types.Schema.System.IServiceProvider.GetService(Type serviceType) in /_/src/GraphQL/Types/Schema.cs:line 107
at GraphQL.Instrumentation.FieldMiddlewareBuilderExtensions.<>c__DisplayClass3_0.<Use>b__0(ISchema schema, FieldMiddlewareDelegate next) in /_/src/GraphQL/Instrumentation/FieldMiddlewareBuilderExtensions.cs:line 62
at GraphQL.Instrumentation.FieldMiddlewareBuilder.Build(FieldMiddlewareDelegate start, ISchema schema) in /_/src/GraphQL/Instrumentation/FieldMiddlewareBuilder.cs:line 57
at GraphQL.Instrumentation.FieldMiddlewareBuilder.ApplyTo(ISchema schema) in /_/src/GraphQL/Instrumentation/FieldMiddlewareBuilder.cs:line 77
at GraphQL.DocumentExecuter.ExecuteAsync(ExecutionOptions options) in /_/src/GraphQL/Execution/DocumentExecuter.cs:line 74
GraphQL.Server.GraphQLOptions.Metrics is enabled by default. This eventually results in a call to provider.GetService(middleware)
, where provider.GetService
is a reference to GraphTypeAdapter.DeriveTypeFromTypeInfo
. This function falls back to Activator.CreateInstance
, but casts to IGraphType
. This cast causes the above error.
I think I found a workaround by disabling GraphQL.Server's metrics and manually adding InstrumentFieldsMiddleware
to the GraphQLEngine via WithMiddleware
. I'm not sure this is a good/valid fix though. A proper fix might be to remove the cast since the function is only used as the implementation of GetService
, which only requires object?
as a return type.
Details: ConfigureServices
and Configure
methods
Here are my ConfigureServices
and Configure
methods in Startup
(link to file in git repo):
public void ConfigureServices(IServiceCollection services) {
// Infer the schema using GraphQL.Conventions
var engine = new GraphQLEngine()
.WithQuery<Query>()
.BuildSchema();
var schema = engine.GetSchema();
services.AddControllers();
services.AddSingleton(schema);
services.AddWebSockets(_ => { });
services
.AddGraphQL((options, provider) => {
var logger = provider.GetRequiredService<ILogger<Startup>>();
options.UnhandledExceptionDelegate = ctx =>
logger.LogError(
"GraphQL Error: {Error}\n{Stacktrace}",
ctx.OriginalException.Message,
ctx.OriginalException.StackTrace
);
})
.AddWebSockets()
.AddSystemTextJson();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
app.UseWebSockets();
app.UseGraphQLWebSockets<ISchema>();
app.UseGraphiQLServer(new GraphiQLOptions { Path = "/graphiql" });
app.UseGraphQL<ISchema>();
}
Hey @Mcat12 - apologies for my late response.
Thanks for the above report. It does indeed look like there's a mismatch in return types for DeriveTypeFromTypeInfo()
. I've attempted a fix on branch fix/issue-211
(#212). Could you please take it for a spin and see if the changed signature resolves the issue for you? The test suite seems unaffected.
That does seem to fix the error, although I've since changed to the GraphType approach instead of using this library (I think I ran into some issues with passing through GraphQL Server's context; I tested this fix on a previous revision).
No probs. Thanks for checking. 👍
If you recall any context around the other issues that you ran into, feel free to elaborate and I can have a look into it.