Open Nuklon opened 7 months ago
Are you submitting any custom data? When does this happen in the logs? We are just using JSON.NET via source import.
I do have some custom data, but it's not WinRT stuff. It's thrown when an exception is logged/submitted by Exceptionless related to WinRT (i.e., thrown by WinRT, typically a COMException).
at Exceptionless.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
at Exceptionless.Serializer.DefaultJsonSerializer.Serialize(Object model, String[] exclusions, Int32 maxDepth, Boolean continueOnSerializationError)
at Exceptionless.Submission.DefaultSubmissionClient.PostEventsAsync(IEnumerable`1 events, ExceptionlessConfiguration config, IJsonSerializer serializer)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
at Exceptionless.Submission.DefaultSubmissionClient.PostEventsAsync(IEnumerable`1 events, ExceptionlessConfiguration config, IJsonSerializer serializer)
at Exceptionless.Queue.DefaultEventQueue.ProcessAsync()
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
at Exceptionless.Queue.DefaultEventQueue.ProcessAsync()
at Exceptionless.Queue.DefaultEventQueue.OnProcessQueueAsync(Object state)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
at Exceptionless.Queue.DefaultEventQueue.OnProcessQueueAsync(Object state)
Any chance you could put together a small sample project in a pr (in our samples folder) that can reproduce this. I can then debug this and make sure it's not broken going forward.
Maybe, the trick is getting a WinRT method to throw.
Were you able to find a method that throws?
Were you able to find a method that throws?
Maybe, need a bit more time.
Were you able to come up with an easy repo sample?
Took some time, but here it is. Create a WPF project in VS and target net8.0-windows10.0.22000.0 (necessary to get UWP types). Some of the code in ExceptionlessService is probably not necessary.
internal class ExceptionlessService(ExceptionlessClient exceptionlessClient)
{
private bool _isDisposed;
private long _queuedFirstChanceExceptions;
public void Initialize()
{
try
{
ExceptionlessConfiguration configuration = exceptionlessClient.Configuration;
configuration.ServerUrl = "YOUR_URL";
configuration.ApiKey = "YOUR_API_KEY";
configuration.Enabled = true;
configuration.IncludePrivateInformation = true;
configuration.IncludeIpAddress = false;
configuration.UseSessions();
AppDomain.CurrentDomain.UnhandledException += (_, args) => OnUnhandledException(args.ExceptionObject as Exception, "AppDomainUnhandledException");
TaskScheduler.UnobservedTaskException += (_, args) => OnUnhandledException(args.Exception, "TaskSchedulerUnobservedTaskException");
App.Current.DispatcherUnhandledException += (_, args) => OnUnhandledException(args.Exception, "ApplicationDispatcherUnhandledException");
AppDomain.CurrentDomain.FirstChanceException += OnFirstChanceException;
if (configuration.SessionsEnabled)
exceptionlessClient.SubmitSessionStart();
exceptionlessClient.SubmittingEvent += OnSubmittingEvent;
}
catch
{ }
}
public void Dispose()
{
if (exceptionlessClient == null || _isDisposed)
return;
_isDisposed = true;
// Wait until all first chance exceptions have been submitted.
while (Interlocked.Read(ref _queuedFirstChanceExceptions) > 0)
Thread.Sleep(1);
exceptionlessClient.ProcessQueueAsync().GetAwaiter().GetResult();
if (exceptionlessClient.Configuration.SessionsEnabled)
exceptionlessClient.SubmitSessionEndAsync().GetAwaiter().GetResult();
}
private static void OnSubmittingEvent(object sender, EventSubmittingEventArgs eventArgs)
{
try
{
if (eventArgs is { Event: not null, IsUnhandledError: true })
eventArgs.Event.Tags.Add("Unhandled");
}
catch
{ }
}
private static void OnUnhandledException(Exception exception, string submissionMethod)
{
if (exception == null)
return;
var contextData = new ContextData();
contextData.MarkAsUnhandledError();
contextData.SetSubmissionMethod(submissionMethod);
EventBuilder eventBuilder = exception.ToExceptionless(contextData);
eventBuilder.AddTags("Unhandled");
eventBuilder.Submit();
}
private void OnFirstChanceException(object sender, FirstChanceExceptionEventArgs eventArgs)
{
Exception exception = eventArgs.Exception;
string stackTrace = new StackTrace(true).ToString();
Interlocked.Increment(ref _queuedFirstChanceExceptions);
Task.Run(() => SubmitFirstChanceException(exception, stackTrace));
}
private void SubmitFirstChanceException(Exception exception, string stackTrace)
{
try
{
EventBuilder eventBuilder = exception.ToExceptionless();
eventBuilder.AddTags("First Chance");
eventBuilder.AddObject(stackTrace, "Stack Trace");
eventBuilder.Submit();
}
finally
{
Interlocked.Decrement(ref _queuedFirstChanceExceptions);
}
}
}
public partial class MainWindow : Window
{
public WiFiDirectAdvertisementPublisher a;
public MainWindow()
{
ExceptionlessService aa = new ExceptionlessService(ExceptionlessClient.Default);
aa.Initialize();
InitializeComponent();
try
{
a = new WiFiDirectAdvertisementPublisher();
a.Advertisement.LegacySettings.Ssid = "test";
a.Advertisement.LegacySettings.Passphrase = new PasswordCredential("a", null, null); // Throws!
a.Start();
}
catch (Exception e)
{
e.ToExceptionless().Submit();
aa.Dispose();
}
}
}
Now, within Exceptionless, you'll see two exceptions logged. One is "The parameter is incorrect. Cannot create credential". This is the correct one. But you'll also get a second exception: "Error getting value from 'GetReference_1' on 'ABI.WinRT.Interop.IRestrictedErrorInfo+Vftbl'." which obviously doesn't make sense.
If the other exception doesn't show up on first start, run it a couple of times, it'll get there eventually. I've had better success by letting it run a few seconds.
On a side note, you might also see this (only rarely here, but it happens):
InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.Collections.NodeKeyValueCollection.NodeKeyValueEnumerator.MoveNext() at offset 29
at Exceptionless.ToErrorModelExtensions.ToErrorModelInternal(System.Exception exception, Exceptionless.ExceptionlessClient client, System.Boolean isInner) at offset 397
Thanks for the sample! I'll try and take a look into this hopefully today or tomorrow.
Sorry for the delay. This is expected as you are wiring up FirstChanceExceptions which catch everything that's already handled. I do think that maybe we should update the default error exclusions to filter out any error data property prefixed with __Restricted
or Restricted
(cc @ejsmith )
Looking at your sample I see a few things that I wanted to call out.
ExceptionlessClient.Default.Register()
(register also wires up to RegisterApplicationDispatcherUnhandledExceptionHandler
) to wire up to all the wpf handlers and cover WinRT scenarios. If that doesn't work which it did for me I'd still call ExceptionlessClient.Default.Startup()
which handles session management for you. which will wire up to
client.RegisterAppDomainUnhandledExceptionHandler();
// make sure that queued events are sent when the app exits client.RegisterOnProcessExitHandler(); client.RegisterTaskSchedulerUnobservedTaskExceptionHandler();
2.Instead of your dispose method call ExceptionlessClient.Default.ShutdownAsync() which does everything and more safely.
3. Be very careful of FirstChanceExceptions it can be misleading as it catches things that are already safely handled.
I'll leave this open until we get a response on ` __Restricted`... Or if you have any follow up
It's been some time since I've written this around Exceptionless, perhaps I'll give the more default code another try someday ☺️
@Nuklon would you mind submitting a pr to update the default exclusions to filter out any error data property prefixed with __Restricted or Restricted (cc @ejsmith )
@Nuklon would you mind submitting a pr to update the default exclusions to filter out any error data property prefixed with __Restricted or Restricted (cc @ejsmith )
I have no idea where this is located, so you can probably make this change yourself faster :)
This keeps getting logged, it's a problem with Exceptionless client when using WinRT (in .net core apps):
Another one: