Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GraphQL over HTTP client integration #2538

Merged
merged 39 commits into from
Aug 18, 2023
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
44d9302
Created basic GraphQL server
jamescrosswell Jul 31, 2023
e29b658
Added Sentry
jamescrosswell Aug 1, 2023
ca8a1bb
Upgraded to latest GraphQL packages
jamescrosswell Aug 1, 2023
c6863e7
Added endpoint demonstrating use of GraphQL Client
jamescrosswell Aug 1, 2023
349f79e
Added OpenTelemetry instrumentation for GraphQL and Sentry
jamescrosswell Aug 1, 2023
cbc1aa1
Update CHANGELOG.md
jamescrosswell Aug 1, 2023
b9902b4
Merge branch 'main' into graphql
jamescrosswell Aug 1, 2023
2c610bd
Added GraphQL Client Sample
jamescrosswell Aug 2, 2023
229e6bf
Merge branch 'main' into graphql-v0.2
jamescrosswell Aug 9, 2023
da22fa8
Fixed Samples
jamescrosswell Aug 9, 2023
be5daf2
Implemented SentryGraphQlHttpMessageHandler
jamescrosswell Aug 10, 2023
31d39af
Update CHANGELOG.md
jamescrosswell Aug 10, 2023
6f6f05a
Removed DSN
jamescrosswell Aug 10, 2023
ab6984d
Merge branch 'graphql-client' of https://github.com/getsentry/sentry-…
jamescrosswell Aug 10, 2023
f7465ea
Rolled back unintentional changes to Sentry.csproj
jamescrosswell Aug 10, 2023
bd77a73
Update ApiApprovalTests.Run.Core3_1.verified.txt
jamescrosswell Aug 10, 2023
144faac
Update CHANGELOG.md
jamescrosswell Aug 10, 2023
7128c27
Merge branch 'main' into graphql-client
jamescrosswell Aug 10, 2023
f0e8e99
Fixed SentryGraphQlHttpFailedRequestHandlerTests
jamescrosswell Aug 11, 2023
be6fb2e
Added Request and Response contexts to failed requests
jamescrosswell Aug 11, 2023
b34d308
Updated verified files
jamescrosswell Aug 11, 2023
52f988c
Fixed unit tests
jamescrosswell Aug 11, 2023
740726d
Generate client errors in GraphQL Client
jamescrosswell Aug 13, 2023
c69a9cd
.
jamescrosswell Aug 13, 2023
2652a56
Fixed content not readable
jamescrosswell Aug 14, 2023
a53ebd0
Added mutation to GraphQL.Client sample
jamescrosswell Aug 14, 2023
ef28a1a
Merge branch 'main' into graphql-client
jamescrosswell Aug 14, 2023
347eef3
Renamed from Ql to QL
jamescrosswell Aug 15, 2023
4ee744a
Made GraphQLContentExtractor static
jamescrosswell Aug 15, 2023
5949aad
Merge branch 'graphql-client' of https://github.com/getsentry/sentry-…
jamescrosswell Aug 15, 2023
85eed5f
Removed redundant code
jamescrosswell Aug 15, 2023
7872c29
Integrated review feedback
jamescrosswell Aug 15, 2023
fff748f
Update GraphQLContentExtractor.cs
jamescrosswell Aug 15, 2023
7a956af
Rollback changes to breadcrumbs and defaults
jamescrosswell Aug 15, 2023
a0eeb30
Use defaults for StreamReader (except leaveopen, which must be true)
jamescrosswell Aug 15, 2023
42d1cd0
Moved GraphQL Client integration into core Sentry package
jamescrosswell Aug 16, 2023
365da70
Update ApiApprovalTests.Run.Core3_1.verified.txt
jamescrosswell Aug 17, 2023
5523f7e
Integrated final feedback
jamescrosswell Aug 17, 2023
6518ca2
Revert accidental changes to cocoa bindings
jamescrosswell Aug 17, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Features

- Graphql client ([#2538](https://github.com/getsentry/sentry-dotnet/pull/2538))

### Dependencies

- Bump CLI from v2.20.4 to v2.20.5 ([#2539](https://github.com/getsentry/sentry-dotnet/pull/2539))
Expand Down
28 changes: 28 additions & 0 deletions Sentry.sln
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sentry.Samples.OpenTelemetr
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sentry.Samples.OpenTelemetry.Console", "samples\Sentry.Samples.OpenTelemetry.Console\Sentry.Samples.OpenTelemetry.Console.csproj", "{D62E79F4-FC3C-4D75-ABFE-CDE76EF46DDE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sentry.Samples.GraphQL.Server", "samples\Sentry.Samples.GraphQL.Server\Sentry.Samples.GraphQL.Server.csproj", "{B3BFB7BA-1A5E-468F-8C47-F0841AA75848}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sentry.Samples.GraphQL.Client", "samples\Sentry.Samples.GraphQL.Client\Sentry.Samples.GraphQL.Client.csproj", "{B01C5D8F-62EE-4E63-AE96-745BA1D2E175}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sentry.GraphQl", "src\Sentry.GraphQl\Sentry.GraphQl.csproj", "{A976354F-8451-4A6B-8BAC-CF94C2FCC6A7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sentry.GraphQl.Tests", "test\Sentry.GraphQl.Tests\Sentry.GraphQl.Tests.csproj", "{1897129B-BA05-49C7-B37D-0328752C4A7C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -404,6 +412,22 @@ Global
{D62E79F4-FC3C-4D75-ABFE-CDE76EF46DDE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D62E79F4-FC3C-4D75-ABFE-CDE76EF46DDE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D62E79F4-FC3C-4D75-ABFE-CDE76EF46DDE}.Release|Any CPU.Build.0 = Release|Any CPU
{B3BFB7BA-1A5E-468F-8C47-F0841AA75848}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B3BFB7BA-1A5E-468F-8C47-F0841AA75848}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B3BFB7BA-1A5E-468F-8C47-F0841AA75848}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B3BFB7BA-1A5E-468F-8C47-F0841AA75848}.Release|Any CPU.Build.0 = Release|Any CPU
{B01C5D8F-62EE-4E63-AE96-745BA1D2E175}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B01C5D8F-62EE-4E63-AE96-745BA1D2E175}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B01C5D8F-62EE-4E63-AE96-745BA1D2E175}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B01C5D8F-62EE-4E63-AE96-745BA1D2E175}.Release|Any CPU.Build.0 = Release|Any CPU
{A976354F-8451-4A6B-8BAC-CF94C2FCC6A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A976354F-8451-4A6B-8BAC-CF94C2FCC6A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A976354F-8451-4A6B-8BAC-CF94C2FCC6A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A976354F-8451-4A6B-8BAC-CF94C2FCC6A7}.Release|Any CPU.Build.0 = Release|Any CPU
{1897129B-BA05-49C7-B37D-0328752C4A7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1897129B-BA05-49C7-B37D-0328752C4A7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1897129B-BA05-49C7-B37D-0328752C4A7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1897129B-BA05-49C7-B37D-0328752C4A7C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -469,6 +493,10 @@ Global
{A58DE854-6576-4E07-98BF-03B9DCCDBF9A} = {83263231-1A2A-4733-B759-EEFF14E8C5D5}
{6F791E40-49A8-4A67-81DB-6913E519310A} = {77454495-55EE-4B40-A089-71B9E8F82E89}
{D62E79F4-FC3C-4D75-ABFE-CDE76EF46DDE} = {77454495-55EE-4B40-A089-71B9E8F82E89}
{B3BFB7BA-1A5E-468F-8C47-F0841AA75848} = {77454495-55EE-4B40-A089-71B9E8F82E89}
{B01C5D8F-62EE-4E63-AE96-745BA1D2E175} = {77454495-55EE-4B40-A089-71B9E8F82E89}
{A976354F-8451-4A6B-8BAC-CF94C2FCC6A7} = {AF6AF4C7-8AA2-4D59-8064-2D79560904EB}
{1897129B-BA05-49C7-B37D-0328752C4A7C} = {83263231-1A2A-4733-B759-EEFF14E8C5D5}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0C652B1A-DF72-4EE5-A98B-194FE2C054F6}
Expand Down
120 changes: 120 additions & 0 deletions samples/Sentry.Samples.GraphQL.Client/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* This sample demonstrates using Sentry to capture traces and exceptions from a GraphQL client.
* It assumes the Sentry.Samples.GraphQL.Server is running on http://localhost:5051
* (see `/Samples/Sentry.Samples.GraphQL.Server/Properties/launchSettings.json`)
*/

using System.Text.Json;
using GraphQL;
using GraphQL.Client.Http;
using GraphQL.Client.Serializer.SystemTextJson;
using Sentry;
using Sentry.GraphQl;

SentrySdk.Init(options =>
{
// options.Dsn = "... Your DSN ...";
options.CaptureFailedRequests = true;
options.SendDefaultPii = true;
options.TracesSampleRate = 1.0;
options.EnableTracing = true;
});

var transaction = SentrySdk.StartTransaction("Program Main", "function");
SentrySdk.ConfigureScope(scope => scope.Transaction = transaction);

var graphClient = new GraphQLHttpClient(
options =>
{
options.EndPoint = new Uri("http://localhost:5051/graphql"); // Assumes Sentry.Samples.GraphQL.Server is running
options.HttpMessageHandler = new SentryGraphQlHttpMessageHandler(); // <-- Configure GraphQL use Sentry Message Handler
},
new SystemTextJsonSerializer()
);

char input = ' ';
do
{
Console.WriteLine("Select a query to send:");
Console.WriteLine("1. Add a note");
Console.WriteLine("2. Get all notes");
Console.WriteLine("3. Generate a GraphQL Error");
Console.WriteLine("0. Exit Note Master 3000");
input = Console.ReadKey().KeyChar;
Console.WriteLine();
switch (input)
{
case '0':
Console.WriteLine("Bye!");
break;
case '1':
await CreateNewNote();
break;
case '2':
await GetAllNotes();
break;
case '3':
await CreateError();
break;
default:
Console.WriteLine("Invalid selection.");
break;
}
} while (input != '0');
transaction.Finish(SpanStatus.Ok);

async Task CreateError()
{
var query = new GraphQLRequest(@"{ test { id } }");
var response = await graphClient!.SendQueryAsync<NotesResult>(query);
var result = JsonSerializer.Serialize(response);
Console.WriteLine(result);
}

async Task CreateNewNote()
{
Console.WriteLine("What do you want the note to say?");
var message = Console.ReadLine();
var mutation = new GraphQLRequest{
Query = @"mutation addANote($note:NoteInput!) { createNote(note: $note) {id message } }",
OperationName = "addANote",
Variables = new
{
note = new
{
message = message
}
}
};
var newNote = await graphClient!.SendQueryAsync<CreateNoteResult>(mutation);
Console.WriteLine("Note added:");
Console.WriteLine("{0,3} | {1}", newNote.Data.CreateNote.Id, newNote.Data.CreateNote.Message);
}

async Task GetAllNotes()
{
var query = new GraphQLRequest(@"query getAllNotes { notes { id, message } }");
var allNotesResponse = await graphClient.SendQueryAsync<NotesResult>(query);
Console.WriteLine();
foreach (var note in allNotesResponse.Data.Notes)
{
Console.WriteLine("{0,3} | {1}", note.Id, note.Message);
}
Console.WriteLine();
}

public class Note
{
public int Id { get; set; }
public string? Message { get; set; }
}

public class NotesResult
{
public List<Note> Notes { get; set; } = new();
}

public class CreateNoteResult
{
public Note CreateNote { get; set; } = new ();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="GraphQL" Version="7.6.0" />
<PackageReference Include="GraphQL.Client" Version="6.0.0" />
<PackageReference Include="GraphQL.Client.Serializer.SystemTextJson" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Sentry.GraphQl\Sentry.GraphQl.csproj" />
<ProjectReference Include="..\..\src\Sentry\Sentry.csproj" />
</ItemGroup>

</Project>
7 changes: 7 additions & 0 deletions samples/Sentry.Samples.GraphQL.Server/Notes/Note.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Sentry.Samples.GraphQL.Server.Notes;

public class Note
{
public int Id { get; set; }
public string? Message { get; set; }
}
14 changes: 14 additions & 0 deletions samples/Sentry.Samples.GraphQL.Server/Notes/NoteType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using GraphQL.Types;

namespace Sentry.Samples.GraphQL.Server.Notes;

public class NoteType : ObjectGraphType<Note>
{
public NoteType()
{
Name = "Note";
Description = "Note Type";
Field(d => d.Id, nullable: false).Description("Note Id");
Field(d => d.Message, nullable: true).Description("Note Message");
}
}
27 changes: 27 additions & 0 deletions samples/Sentry.Samples.GraphQL.Server/Notes/NotesData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Collections.Concurrent;

namespace Sentry.Samples.GraphQL.Server.Notes;

public class NotesData
{
private static int NextId = 0;
private readonly ICollection<Note> _notes = new List<Note> ()
{
new() { Id = NextId++, Message = "Hello World!" },
new() { Id = NextId++, Message = "Hello World! How are you?" }
};

public ICollection<Note> GetAll() => _notes;

public Task<Note?> GetNoteByIdAsync(int id)
{
return Task.FromResult(_notes.FirstOrDefault(n => n.Id == id));
}

public Note AddNote(Note note)
{
note.Id = NextId++;
_notes.Add(note);
return note;
}
}
27 changes: 27 additions & 0 deletions samples/Sentry.Samples.GraphQL.Server/Notes/NotesMutation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using GraphQL;
using GraphQL.Types;

namespace Sentry.Samples.GraphQL.Server.Notes;

public sealed class NotesMutation : ObjectGraphType
{
public NotesMutation(NotesData data)
{
Field<NoteType>("createNote")
.Argument<NonNullGraphType<NoteInputType>>("note")
.Resolve(context =>
{
var note = context.GetArgument<Note>("note");
return data.AddNote(note);
});
}
}

public class NoteInputType : InputObjectGraphType
{
public NoteInputType()
{
Name = "NoteInput";
Field<NonNullGraphType<StringGraphType>>("message");
}
}
11 changes: 11 additions & 0 deletions samples/Sentry.Samples.GraphQL.Server/Notes/NotesQuery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using GraphQL.Types;

namespace Sentry.Samples.GraphQL.Server.Notes;

public sealed class NotesQuery : ObjectGraphType
{
public NotesQuery(NotesData data)
{
Field<ListGraphType<NoteType>>("notes").Resolve(context => data.GetAll());
}
}
12 changes: 12 additions & 0 deletions samples/Sentry.Samples.GraphQL.Server/Notes/NotesSchema.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using GraphQL.Types;

namespace Sentry.Samples.GraphQL.Server.Notes;

public class NotesSchema : Schema
{
public NotesSchema(IServiceProvider serviceProvider) : base(serviceProvider)
{
Query = serviceProvider.GetRequiredService<NotesQuery>();
Mutation = serviceProvider.GetRequiredService<NotesMutation>();
}
}