NLog Raygun - How to catch exception when calling SendInBackground - c#

I forked the NLog Raygun from Mindscape to provide more settings of Raygun in NLog.
A RaygunTarget is created and needs to override Write method as follows NLog document (https://github.com/NLog/NLog/wiki/How-to-write-a-custom-target).
To send an exception to Raygun, follows the below code
protected override void Write(LogEventInfo logEvent)
{
_raygunClient ??= (_raygunClient = CreateRaygunClient());
...
_raygunClient.SendInBackground(exception, tags, userCustomData);
}
SendInBackground returns a Task which we can not mark Write method as async void because it's not the case of using async void.
Everything works fine. We have a swagger to have Healthcheck. I want to check if NLog Raygun is sent successfully but I don't know how to catch the exception in SendInBackground in case API Key is invalid. I mean is there a better way to test whether this RaygunTarget can send a message successfully to Raygun?
If I provide a setting called ThrowOnError and in Write method updated like this
protected override void Write(LogEventInfo logEvent)
{
_raygunClient ??= (_raygunClient = CreateRaygunClient());
...
var task = _raygunClient.SendInBackground(exception, tags, userCustomData);
if (_setting.ThrowOnError) task.Wait();
}
It works but a question is: This is a good way to do that? Personally, I think it's not because it introduces a different behavior or side-effect based on a setting.

Instead of inheriting from TargetWithLayout then you can inherit from AsyncTaskTarget:
protected override Task WriteAsyncTask(LogEventInfo logEvent, CancellationToken token)
{
_raygunClient ??= (_raygunClient = CreateRaygunClient());
...
var userCustomData = base.GetAllProperties(logEvent);
return _raygunClient.SendInBackground(exception, tags, userCustomData);
}
See also: https://github.com/NLog/NLog/wiki/How-to-write-a-custom-async-target
Then you can hook into the NLog InternalLogger using InternalLogger.LogWriter, and forward to healthcheck-api.
There are plans to improve the API for NLog 5.0 so one can subscribe to an InternalLogger-Event and can also get more context details. Like Target-Name, Target-Type etc. See also: https://github.com/NLog/NLog/issues/3350

Related

MassTransit - Cannot override the Consume method from RoutingSlipResponseProxy

I'm trying to set up a RoutingSlipResponseProxy that will prevent a response from being sent if there is no RequestId. I am trying to do this by overriding the Consume method in my RoutingSlipResponseProxy, like so:
public class MigrateResponseProxy : RoutingSlipResponseProxy<IMigrationRequested, IMigrationComplete>
{
public new async Task Consume(ConsumeContext<RoutingSlipCompleted> context)
{
var isRequest = context.Message.Variables.ContainsKey("RequestId");
if (!isRequest)
return;
var request = context.Message.GetVariable<IMigrationRequested>("Request");
var requestId = context.Message.GetVariable<Guid>("RequestId");
Uri responseAddress = null;
if (context.Message.Variables.ContainsKey("ResponseAddress"))
responseAddress = context.Message.GetVariable<Uri>("ResponseAddress");
if (responseAddress == null)
throw new ArgumentException($"The response address could not be found for the faulted routing slip: {context.Message.TrackingNumber}");
var endpoint = await context.GetResponseEndpoint<IMigrationComplete>(responseAddress, requestId).ConfigureAwait(false);
var response = await CreateResponseMessage(context, request);
await endpoint.Send(response).ConfigureAwait(false);
}
... remaining code ...
}
This is basically the same code as the original method, except with a check for the RequestId at the beginning. However, when debugging through the code, it seems as though this overridden method is never getting called, and instead the parent method is getting called. Is there something I might be missing here? Any help would be appreciated.
The methods aren't virtual, so you won't be able to override them. In this case, you'd be better of copying the proxy code into your own project instead of using the implementation that's included with MassTransit.
You're welcome to submit a PR to make those methods virtual.

Roslyn Code Action: How to check if preview or real execution?

I am currently experimenting with Roslyn and Code Actions, more specific Code Refactorings.
It feels kind of easy, but I have a difficulty I cannot solve.
Code actions are executed once against a dummy workspace as a "preview" option, so that you can see the actual changes before you click the action and execute it against the real workspace.
Now I am dealing with some things Roslyn can't really do (yet), so I am doing some changes via EnvDTE. I know, it's bad, but I couldn't find another way.
So the issue here is:
When I hover over my code action, the code gets executed as preview, and it should NOT do the EnvDTE changes. Those should only be done when the real execute happens.
I have created a gist with a small example of my code. It doesn't really makes sense, but should show what I want to achieve. Do some modifications via roslyn, then do something via EnvDTE, like changing Cursor position. But of course only on the real execution.
The relevant part for those who can't click the gist:
public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(continueOnCapturedContext: false);
var node = root.FindNode(context.Span);
var dec = node as MethodDeclarationSyntax;
if (dec == null)
return;
context.RegisterRefactoring(CodeAction.Create("MyAction", c => DoMyAction(context.Document, dec, c)));
}
private static async Task<Solution> DoMyAction(Document document, MethodDeclarationSyntax method, CancellationToken cancellationToken)
{
var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken);
var root = await syntaxTree.GetRootAsync(cancellationToken);
// some - for the question irrelevant - roslyn changes, like:
document = document.WithSyntaxRoot(root.ReplaceNode(method, method.WithIdentifier(SyntaxFactory.ParseToken(method.Identifier.Text + "Suffix"))));
// now the DTE magic
var preview = false; // <--- TODO: How to check if I am in preview here?
if (!preview)
{
var requestedItem = DTE.Solution.FindProjectItem(document.FilePath);
var window = requestedItem.Open(Constants.vsViewKindCode);
window.Activate();
var position = method.Identifier.GetLocation().GetLineSpan().EndLinePosition;
var textSelection = (TextSelection) window.Document.Selection;
textSelection.MoveTo(position.Line, position.Character);
}
return document.Project.Solution;
}
You can choose to override ComputePreviewOperationsAsync to have different behavior for Previews from regular code.
I've found the solution to my problem by digging deeper and trial and error after Keven Pilch's answer. He bumped me in the right direction.
The solution was to override both the ComputePreviewOperationsAsync and the GetChangedSolutionAsync methods in my own CodeAction.
Here the relevant part of my CustomCodeAction, or full gist here.
private readonly Func<CancellationToken, bool, Task<Solution>> _createChangedSolution;
protected override async Task<IEnumerable<CodeActionOperation>> ComputePreviewOperationsAsync(CancellationToken cancellationToken)
{
const bool isPreview = true;
// Content copied from http://sourceroslyn.io/#Microsoft.CodeAnalysis.Workspaces/CodeActions/CodeAction.cs,81b0a0866b894b0e,references
var changedSolution = await GetChangedSolutionWithPreviewAsync(cancellationToken, isPreview).ConfigureAwait(false);
if (changedSolution == null)
return null;
return new CodeActionOperation[] { new ApplyChangesOperation(changedSolution) };
}
protected override Task<Solution> GetChangedSolutionAsync(CancellationToken cancellationToken)
{
const bool isPreview = false;
return GetChangedSolutionWithPreviewAsync(cancellationToken, isPreview);
}
protected virtual Task<Solution> GetChangedSolutionWithPreviewAsync(CancellationToken cancellationToken, bool isPreview)
{
return _createChangedSolution(cancellationToken, isPreview);
}
The code to create the action stays quite similar, except the bool is added and I can check against it then:
public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
{
// [...]
context.RegisterRefactoring(CustomCodeAction.Create("MyAction",
(c, isPreview) => DoMyAction(context.Document, dec, c, isPreview)));
}
private static async Task<Solution> DoMyAction(Document document, MethodDeclarationSyntax method, CancellationToken cancellationToken, bool isPreview)
{
// some - for the question irrelevant - roslyn changes, like:
// [...]
// now the DTE magic
if (!isPreview)
{
// [...]
}
return document.Project.Solution;
}
Why those two?
The ComputePreviewOperationsAsync calls the the normal ComputeOperationsAsync, which internally calls ComputeOperationsAsync. This computation executes GetChangedSolutionAsync. So both ways - preview and not - end up at GetChangedSolutionAsync. That's what I actually want, calling the same code, getting a very similar solution, but giving a bool flag if it is preview or not too.
So I've written my own GetChangedSolutionWithPreviewAsync which I use instead. I have overriden the default GetChangedSolutionAsync using my custom Get function, and then ComputePreviewOperationsAsync with a fully customized body. Instead of calling ComputeOperationsAsync, which the default one does, I've copied the code of that function, and modified it to use my GetChangedSolutionWithPreviewAsync instead.
Sounds rather complicated in written from, but I guess the code above should explain it quite well.
Hope this helps other people.

GetAnalyzerDiagnosticsAsync returns nothing if a DiagnosticAnalyzer has an empty Initialize

I am writing a method which gets all the Diagnostics for a Project for a set of DiagnosticAnalyzers:
private static async Task<ImmutableArray<Diagnostic>> GetDiagnosticsAsync(
Project project,
ImmutableArray<DiagnosticAnalyzer> analyzers)
{
var compilation = await project.GetCompilationAsync();
var withAnalyzers = compilation.WithAnalyzers(analyzers);
var diagnostics = await withAnalyzers.GetAnalyzerDiagnosticsAsync();
return diagnostics;
}
This works fine if all the DiagnosticAnalyzers in analyzers have their Initialize(AnalysisContext) method containing some register call:
public override void Initialize(AnalysisContext context)
{
context.Register...(...);
}
However if any of them have an empty implementation
public override void Initialize(AnalysisContext context)
{
// nothing here
}
then diagnostics.Count() == 0.
Have I misunderstood what the behavior for GetAnalyzerDiagnosticsAsync() and DiagnosticAnalyzers are and therefore this a correct thing for it to be doing? Or is this a bug in Roslyn? Or is there another method I should be using? Or something else?
I'm tempted to think that this is a error in Roslyn (as such I have opened an issue). Digging into the source code and debugging results that the difference occurs in CompilationWithAnalyzers._driver.DiagnosticQueue - when it works this has the desired Count but is 0 when the issue occurs.
The plot thickens...
Turns out this was a bug with Roslyn, which has now been fixed:
Closed issue
Pull request

Response.Redirect issue with Asp.net async

I'm new to asp.net 4.5 async and am running into the following with calling response.redirect within an async method. The issue is that the response just "hangs" Has anyone else experienced similar issues with attempting an redirect with async? This code will work in a brand new project, but, does not work with a new page in our existing code. I made sure to gut out everything I could out of our web.config and removed our master page. Hitting a brick wall...any ideas? Thanks!
protected void Page_Load(object sender, EventArgs e)
{
RegisterAsyncTask(new PageAsyncTask(PageLoadAsync));
}
private async Task PageLoadAsync()
{
var data = await GetData();
if (data == HttpStatusCode.OK)
Response.Redirect("http://www.google.com");
}
private async Task<HttpStatusCode> GetData()
{
using (var client = new HttpClient())
{
var response = await client.GetAsync("https://www.google.com");
return response.StatusCode;
}
}
This code will work in a brand new project, but, does not work with a new page in our existing code.
I assume your existing site has already been upgraded to .NET 4.5.
The first thing to check is that httpRuntime.targetFramework is set to 4.5. This is not set by default when you upgrade.
Edit from comments:
Another thing to check (just in case) is that Page.Async is set to true.
In this case, the solution was to call Response.Redirect("http://www.google.com", false), which explicitly passes false for the endResponse parameter. The default value of true is only for backwards-compatibility reasons as described here.
The hack I used is:
I used a static dictionary as var d= new Dictionary<string, bool>(); in the class where my API calling method is written.
I put the code line client.timeout = new System.TimeSpan(0,0,60); for API sending the request.
When API is timed out, it throws the TaskTimeoutException, in the TaskTimeoutExceptioncatch block write code as d.Add("timeout", true);
Now, I created the custom action filter and applied the following code:
public class MyCustomActionFilter : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if(MyApiClass.d.ContainsKey("timeout") && d["timeout"])
{
throw new Exception();
}
}
}
I applied the [MyCustomActionFilter ] on the action.
When action is executed and enter the custom filter it throws Exception by checking the dictionary entry.
If timeout would have occurred then dictionary entry will be true, so, on the basis of that, we check the entry and throws the exception. Now, we have Application_Error() in Global.asax.cs that catches the exception.
In the Application_Error() we have written the code for redirect to the required page.
NOTE: In step 4 you can create your custom exception to provide more precise detail for logging.

Separating Logging Code from C# Objects

Currently I have a custom built static logging class in C# that can be called with the following code:
EventLogger.Log(EventLogger.EventType.Application, string.Format("AddData request from {0}", ipAddress));
When this is called it simply writes to a defined log file specified in a configuration file.
However, being that I have to log many, many events, my code is starting to become hard to read because all of the logging messages.
Is there an established way to more or less separate logging code from objects and methods in a C# class so code doesn't become unruly?
Thank you all in advance for your help as this is something I have been struggling with lately.
I like the AOP Features, that PostSharp offers. In my opinion Loggin is an aspect of any kind of software. Logging isn't the main value an application should provide.
So in my case, PostSharp always was fine. Spring.NET has also an AOP module which could be used to achieve this.
The most commonly used technique I have seen employs AOP in one form or another.
PostSharp is one product that does IL weaving as a form of AOP, though not the only way to do AOP in .NET.
A solution to this is to use Aspect-oriented programming in which you can separate these concerns. This is a pretty complex/invasive change though, so I'm not sure if it's feasible in your situation.
I used to have a custom built logger but recently changed to TracerX. This provides a simple way to instrument the code with different levels of severity. Loggers can be created with names closely related to the class etc that you are working with
It has a separate Viewer with a lot of filtering capabilities including logger, severity and so on.
http://tracerx.codeplex.com/
There is an article on it here: http://www.codeproject.com/KB/dotnet/TracerX.aspx
If your primary goal is to log function entry/exit points and occasional information in between, I've had good results with an Disposable logging object where the constructor traces the function entry, and Dispose() traces the exit. This allows calling code to simply wrap each method's code inside a single using statement. Methods are also provided for arbitrary logs in between. Here is a complete C# ETW event tracing class along with a function entry/exit wrapper:
using System;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace MyExample
{
// This class traces function entry/exit
// Constructor is used to automatically log function entry.
// Dispose is used to automatically log function exit.
// use "using(FnTraceWrap x = new FnTraceWrap()){ function code }" pattern for function entry/exit tracing
public class FnTraceWrap : IDisposable
{
string methodName;
string className;
private bool _disposed = false;
public FnTraceWrap()
{
StackFrame frame;
MethodBase method;
frame = new StackFrame(1);
method = frame.GetMethod();
this.methodName = method.Name;
this.className = method.DeclaringType.Name;
MyEventSourceClass.Log.TraceEnter(this.className, this.methodName);
}
public void TraceMessage(string format, params object[] args)
{
string message = String.Format(format, args);
MyEventSourceClass.Log.TraceMessage(message);
}
public void Dispose()
{
if (!this._disposed)
{
this._disposed = true;
MyEventSourceClass.Log.TraceExit(this.className, this.methodName);
}
}
}
[EventSource(Name = "MyEventSource")]
sealed class MyEventSourceClass : EventSource
{
// Global singleton instance
public static MyEventSourceClass Log = new MyEventSourceClass();
private MyEventSourceClass()
{
}
[Event(1, Opcode = EventOpcode.Info, Level = EventLevel.Informational)]
public void TraceMessage(string message)
{
WriteEvent(1, message);
}
[Event(2, Message = "{0}({1}) - {2}: {3}", Opcode = EventOpcode.Info, Level = EventLevel.Informational)]
public void TraceCodeLine([CallerFilePath] string filePath = "",
[CallerLineNumber] int line = 0,
[CallerMemberName] string memberName = "", string message = "")
{
WriteEvent(2, filePath, line, memberName, message);
}
// Function-level entry and exit tracing
[Event(3, Message = "Entering {0}.{1}", Opcode = EventOpcode.Start, Level = EventLevel.Informational)]
public void TraceEnter(string className, string methodName)
{
WriteEvent(3, className, methodName);
}
[Event(4, Message = "Exiting {0}.{1}", Opcode = EventOpcode.Stop, Level = EventLevel.Informational)]
public void TraceExit(string className, string methodName)
{
WriteEvent(4, className, methodName);
}
}
}
Code that uses it will look something like this:
public void DoWork(string foo)
{
using (FnTraceWrap fnTrace = new FnTraceWrap())
{
fnTrace.TraceMessage("Doing work on {0}.", foo);
/*
code ...
*/
}
}
To make the code readable, only log what you really need to (info/warning/error). Log debug messages during development, but remove most when you are finished. For trace logging, use
AOP to log simple things like method entry/exit (if you feel you need that kind of granularity).
Example:
public int SomeMethod(int arg)
{
Log.Trace("SomeClass.SomeMethod({0}), entering",arg); // A
if (arg < 0)
{
arg = -arg;
Log.Warn("Negative arg {0} was corrected", arg); // B
}
Log.Trace("SomeClass.SomeMethod({0}), returning.",arg); // C
return 2*arg;
}
In this example, the only necessary log statement is B. The log statements A and C are boilerplate, logging that you can leave to PostSharp to insert for you instead.
Also: in your example you can see that there is some form of "Action X invoked by Y", which suggests that a lot of your code could in fact be moved up to a higher level (e.g. Command/Filter).
Your proliferation of logging statements could be telling you something: that some form of design pattern could be used, which could also centralize a lot of the logging.
void DoSomething(Command command, User user)
{
Log.Info("Command {0} invoked by {1}", command, user);
command.Process(user);
}
I think it is a good option to implement something similar to filters in ASP.NET MVC. This is implement with the help of attributes and reflection. You mark every method you want to log in a certain way and enjoy. I suppose there might be a better way to do it, may be with the help of Observer pattern or something but as long as I thought about it I couldn't think of something better.
Basically such problems are called cross-cutting concerns and can be tackled with the help of AOP.
I also think that some interesting inheritance schema can be applied with log entities at the base but I would go for filters

Categories