I am currently adding some logging to our application to aid debugging in the future. To achieve this I have written a DLL with a static class which basically acts as a layer between our application and writes to the chosen log source, this is normally application insights.
One of the things I want to achieve is to log a trace to application insights with the method name and parameters, now this is achievable with code like this:
var methodName = MethodBase.GetCurrentMethod().Name;
var methodParameters = new Dictionary<string, string> { { "Parameter1", "Parameter1 Value" }, { "Parameter2", "Parameter2 Value" } };
appInsightsClient.TrackTrace(methodName, methodParameters);
and this works fine.
I am wondering if there is a better / cleaner way to achieve this? For methods with lots of parameters this will easily become difficult to read. I know that MethodBase.GetCurrentMethod() has a method for GetParameters() but these do not return the value. This is also relies on the developer setting the methodParameters / methodName variables back to null so they are picked up by garbage collection and with lots of methods being hit, I don't want to consume too much memory.
I appreciate this question is partly subjective and the opinion of the individual developer, but I can't seem to find any alternatives or examples out there, and can't be the only person who does this.
One way to solve it is using an AOP framework. I know at least a couple of them. One is PostSharp, which is really feature rich but isn't free. The other one I've experience with is MrAdvice.
Basically what you can do with those framework is create method interception points. You can apply custom logic when a method is entered and exited. What you could do is inspect the method info and use that in the logging. You can decorate the methods you are interested in so you have control over which methods are logged or not logged.
For example, using MrAdvice you can do something like:
public sealed class AppInsightsRequestAttribute : Attribute, IMethodAsyncAdvice
{
private static readonly TelemetryClient TelemetryClient = new TelemetryClient(TelemetryConfiguration.Active);
public async Task Advise(MethodAsyncAdviceContext context)
{
var parameters = context.TargetMethod.GetParameters();
var parameterDescription = string.Join(", ",
parameters.Select(p => $"{p.ParameterType.Name} {p.Name}"));
var signature = $"{context.Target ?? context.TargetType}.{context.TargetName}({parameterDescription})";
using (var operation = TelemetryClient.StartOperation<RequestTelemetry>(signature))
{
try
{
await context.ProceedAsync();
}
catch (Exception)
{
operation.Telemetry.Success = false;
throw;
}
finally
{
EnrichRequestTelemetry(operation.Telemetry, context, parameters);
}
}
}
private static void EnrichRequestTelemetry(ISupportProperties telemetry, MethodAsyncAdviceContext context, IReadOnlyList<ParameterInfo> parameters)
{
telemetry.Properties.Add(
new KeyValuePair<string, string>("Accessibility",
context.TargetMethod.Attributes.ToVisibilityScope().ToString()));
for (var i = 0; i < context.Arguments.Count; i++)
{
telemetry.Properties.Add($"ARG {parameters[i].Name}", context.Arguments[i].ToString());
}
}
}
This code will create a RequestTelemetry item and send it to application insights. The EnrichRequestTelemetry method will add the method arguments and values as custom properties to the item.
You can then decorate your methods like this: (there are more options, but this is to demonstrate a possibility)
public class SomeClass
{
[AppInsightsRequest]
public async Task<string> SayHello(string to)
{
var telemetryClient = new TelemetryClient(TelemetryConfiguration.Active);
string response = null;
try
{
var greeting = $"Hello {to}";
telemetryClient.TrackTrace($"Sending {greeting}");
response = await SomeService.SendAsync(greeting);
}
catch (Exception exception)
{
telemetryClient.TrackException(exception);
}
return response;
}
}
A complete sample using a console application to send telemetry to application insights can be found in this repository which I created.
Related
I have a already written (was written years ago) C# function, I have been asked to cover this method with Unit Tests.
public string PlaceOrder(int requestId, string orderedby)
{
try
{
using (DatabaseContext dbContext = new DatabaseContext("myConnectionStringHere"))
{
var req = dbContext.Orders.Where(row => row.id == requestId).FirstOrDefault();
if (req == null)
return "not found";
req.status="A";
dbContext.SaveChanges();
return "found";
}
}
catch (Exception ex)
{
return "error";
}
}
Now while Unit testing I need to make sure that it does not write anything to database, so I have to MOQ it.
How can I MOQ, it contains Using block.
I know architecture could have been better and design patterns should have been followed but I am not allowed to change the structure of the application as it is a legacy application.
The general guidance here is to prefer Integration Test with in memory (w/o sqlite) database over unit testing.
Let me suggest you four helper libraries which can make your testing easier:
EntityFrameworkCoreMock
Github link
The prerequisite here is to mark your DbSet as virtual like this:
public virtual DbSet<Order> Orders { get; set; }
Then you can create a mock where you can populate your Orders collection with some dummy data:
var initialOrders = new[]
{
new Order { ... },
new Order { ... },
};
var dbContextMock = new DbContextMock<DatabaseContext>(new DbContextOptionsBuilder<DatabaseContext>().Options);
var ordersDbSetMock = dbContextMock.CreateDbSetMock(db => db.Orders, initialOrders);
You have to rewrite your containing class of the PlaceOrder method in a way to receive a DatabaseContext parameter in the constructor to be able inject dbContextMock.Object during testing.
In the assertion phase you can query your data and make assertion against it. Since you do not call Add, Remove or any other CRUD method, you can only Verify the SaveChanges call.
public void GivenAnExistingOrder_WhenICallPlaceOrder_ThenSaveChangesIsCalledOnce()
{
...
//Assert
dbMock.Verify(db => db.SaveChanges(), Times.Once);
}
public void GivenANonExistingOrder_WhenICallPlaceOrder_ThenSaveChangesIsCalledNever()
{
...
//Assert
dbMock.Verify(db => db.SaveChanges(), Times.Never);
}
EntityFrameworkCore.Testing
Github link
It is working more or less in the way as the previous library.
var dbContextMock = Create.MockedDbContextFor<DatabaseContext>();
dbContextMock.Set<Order>().AddRange(initialOrders);
dbContextMock.SaveChanges();
The assertions work in the same way.
A 3rd (less mature) library is called Moq.EntityFrameworkCore.
If you really keen to perform unit testing by avoiding in memory database then you should give a try to the MockQueryable library.
const int requestId = 1;
var orders = new List<Order>();
var ordersMock = orders.AsQueryable().BuildMockDbSet();
ordersMock.Setup(table => table.Where(row => row.Id == requestId)).Returns(...)
Here you are basically mocking what should be the result of your Where filter. In order to be able to use this the containing class of the PlaceOrder should receive a DbSet<Order> parameter via its constructor.
Or if you have an IDatabaseContext interface then you can use that one as well like this:
Mock<IQueryable<Order>> ordersMock = orders.AsQueryable().Build();
Mock<IDatabaseContext> dbContextMock = ...
dbContextMock.Setup(m => m.ReadSet<Order>()).Returns(ordersMock.Object));
Many things should be changed here:
1:
Do not implement your connection string this way, directly in the code base.
Instead, DI your database into your classes.
so this pseudo code should help out with the general idea.
public void ConfigureService(IServiceCollection serviceCollection)
{
...
string connectionString = //secure storage;
serviceCollection.AddDbContext<DatabaseContext>(options => {
options.UseSqlServer(connectionString);
});
...
}
And then
public class OrderRepository
{
private IServiceScopeFactory _serviceScopeFactory ;
public OrderRepository(IServiceScopeFactory serviceScopeFactory ){
_serviceScopeFactory = serviceScopeFactory ;
}
...
public string PlaceOrder(int requestId, string orderedby)
{
try
{
using (var context = serviceScopeFactory.CreateScope())
{
var req = context.Orders.Where(row => row.id == requestId).FirstOrDefault();
if (req == null)
return "not found";
req.status="A";
context.SaveChanges();
return "found";
}
}
catch (Exception ex)
{
return "error";
}
}
...
}
if you want to make an integration test, you can then use an InMemory db to emulate whatever you want.
Or you can connect to a "real" db, and do it that way.
If you want to make it a unit test, you can see at this link:
How to setup a DbContext Mock
2:
returning a string saying found/not found for a order being placed, seems extremely counter productive.
if your aim is to log this information, provider a DI logger, that can log this. (Try importing the ILogger interface, it's a microsoft extension on logging, can't remember the nuget package name)
should enable you to log with DI very efficiently.
If your aim is to let a possible UI display this message, there is no way the message content should originate from back-end or domain logic.
At least not like this.
Then you should make an interface for a response, and return an implementation of said interface, that exists somewhere else as a minimum but even that is a bit like peeing your pants.
(And contains a UI friendly message, can contain a possible stacktrace/exception), and other possible relevant information, like what Id you were trying to place an order on etc.)
You should make it something that happens at the interface between your UI and domain logic, provided that is what the string is intended for. Where you would expect to see error handling.
3:
WTF is up with the catch? you just return error? Well ? What error? you lose the stack-trace this way?
Someone should be punished for that.
Having an issue with akka.net. I need to access an actor which I have already created with a specific name. I can retrieve the actor from IActorContext but I am struggling to access it from the ActorSystem.
I have created a method called GetOrCreateActor which attempts to get the actor using ActorSelection. If it doesn't exist, the catch creates a new actor with the name. If it does exist, I want it to return the reference. However, it never returns from '.Result'. Assuming this could be some sort of deadlocking issue.
public static IActorRef GetOrCreateActor<T>(this ActorSystem actorSystem, string actorPath, string name = null) where T : ActorBase
{
try
{
return actorSystem.ActorSelection(actorPath).ResolveOne(TimeSpan.FromSeconds(1)).Result;
}
catch
{
return actorSystem.ActorOf(actorSystem.DI().Props<T>(), name);
}
}
Edit
I've tried to include a simplified version of the calling code below.
The actor system is created in an IOC container using AutoFac (ExampleActor is the ReceiveActor I am trying to access):
containerBuilder.RegisterAssemblyTypes(typeof(ExampleActor).Assembly).Where(x => x.Name.EndsWith("Actor"));
var lazyContainer = new Lazy<IContainer>(() => containerBuilder.Build());
containerBuilder.Register(c =>
{
var system = ActorSystem.Create("ExampleActorSystem");
new AutoFacDependencyResolver(lazyContainer.Value, system);
return system;
}).As<ActorSystem>().SingleInstance();
return lazyContainer.Value;
ActorSystem is then injected into another class, where I call the GetOrCreateActor method (via the Execute method):
public class ExampleCommand : IExampleCommand
{
private readonly ActorSystem _actorSystem;
public ExampleCommand(ActorSystem actorSystem)
{
_actorSystem = actorSystem;
}
public void Execute()
{
SendMessage();
}
private void SendMessage()
{
string message = new Message();
_actorSystem.GetOrCreateActor<ExampleActor>("akka://ExampleActorSystem/user/ExampleActor", "ExampleActor").Tell(message);
}
}
The above command would be called from a RESTful endpoint
public ExampleGetModule(IExampleCommand exampleCommand)
{
Get["/api/createExample"] = parameters =>
{
exampleCommand.Execute();
};
}
Your deadlocking issue looks more like it has to do with how you're using your container than it does Akka.NET:
var lazyContainer = new Lazy<IContainer>(() => containerBuilder.Build());
containerBuilder.Register(c =>
{
var system = ActorSystem.Create("ExampleActorSystem");
new AutoFacDependencyResolver(lazyContainer.Value, system);
return system;
}).As<ActorSystem>().SingleInstance();
In terms of what can go wrong here, self-referential Lazy<T> types are an infamous source of race-conditions. You should not be calling lazyContainer.Value inside of this registration method if the output of containerBuilder.Build depends on the input of containerBuilder.Register.
Last thing is to use step-through debugging to make sure that your application actually calls into the ResolveOne method here - if you're not getting a timeout exception back then it means that your application is deadlocking on producing the actor system (because of how DI is configured).
Lately I am working on exception logging module of a WCF service. Unfortunately the service hasn't been introduced with unit tests, therefore there are many unexpected exceptions occurring. And so far I have accomplished to get the exceptions with interceptor aproach, by implementing IErrorHandler interface and tying it to the service interface with IServiceBehaviour. I liked this functionality very much actually. But it brought me into a next step of desire of getting the details of exception. Like on which line did the exception occurred?
I can satisfy this desire by 2 ways in my mind:
By having a variable for keeping track of the lines I've passed through successfully, and including it in the exception thrown.
By catching exceptions from all lines seperately.
But both approaches seem very lousy to me. I am wondering is there a known design pattern or a tool to achive this goal?
In my opinion you might try using logging, such as log4net. Then you can find out where is and what happened. Exception object not always contains the stack info, because of "inlining", that occur during optimization etc.
include the PDB files for your service and the line numbers will be included in exception.ToString()
The way we have solved this problem is twofold:
Our services are dumb wrappers around commands. So when a service method is entered it delegates its work to a command.
We wrap every command call in a logging proxy that is responsible for logging input, output and errors and executing the command.
For example:
public FooServiceModel GetFoo(int fooId)
{
return new ILogged<GetFooCommand>().Target.Execute(fooId);
}
This delegates execution of the command to ILogged which:
Logs the command name
Logs the command parameters
Logs the execution result
Logs any exceptions
It also does some other stuff to link up the client request with the server call using custom message headers so that a call can be completely debugged from client to server and back. This is incredibly useful and allows us to diagnose even complex problems off site.
We use the Castle.Core dynamic proxy to implement ILogged with an interceptor that looks something like this (ILog is a log4net logger):
public class LoggingInterceptor : IInterceptor
{
public LoggingInterceptor([NotNull] object target, [NotNull] ILog logger)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
if (logger == null)
{
throw new ArgumentNullException("logger");
}
this.Target = target;
this.Logger = logger;
}
public object Target { get; set; }
public ILog Logger { get; set; }
public void Intercept(IInvocation invocation)
{
try
{
this.Logger.Debug(invocation);
invocation.ReturnValue = invocation.Method.Invoke(
this.Target, invocation.Arguments);
this.Logger.Debug("Invocation return value:");
this.Logger.Debug(invocation.ReturnValue);
}
catch (TargetInvocationException ex)
{
this.Logger.Error("Unable to execute invocation", ex);
if (ex.InnerException != null)
{
throw ex.InnerException;
}
throw;
}
}
}
The invocation itself is rendered by a custom log4net object renderer:
public class InvocationRenderer : IObjectRenderer
{
public void RenderObject(RendererMap rendererMap, object obj, TextWriter writer)
{
var invocation = (IInvocation)obj;
var builder = new StringBuilder();
builder.AppendFormat(
"Invoking Method: {0} --> '{1}' with parameters (",
invocation.Method.DeclaringType != null
? invocation.Method.DeclaringType.FullName : "{Unknown Type}",
invocation.Method);
var parameters = invocation.Method
.GetParameters()
.Zip(invocation.Arguments, (p, a) => new { Parameter = p, Argument = a })
.ToArray();
var index = 0;
foreach (var parameter in parameters)
{
builder.AppendFormat(
"{0}: {1}",
parameter.Parameter.Name,
rendererMap.FindAndRender(parameter.Argument));
if (++index < parameters.Length)
{
builder.Append(", ");
}
}
builder.Append(")");
writer.Write(builder.ToString());
}
}
Hopefully that will give you some ideas on how to tackle this problem.
Currently in code i have used an object factory to return me a processor based of a string tag, which has severed its purpose up until now.
using Core;
using Data;
public static class TagProcessorFactory
{
public static ITagProcessor GetProcessor(string tag)
{
switch (tag)
{
case "gps0":
return new GpsTagProcessor();
case "analog_manager":
return new AnalogManagerTagProcessor();
case "input_manager":
return new InputManagerTagProcessor();
case "j1939":
return new J1939TagProcessor(new MemcachedProvider(new[] { "localhost" }, "DigiGateway"), new PgnRepository());
default:
return new UnknownTagProcessor();
}
}
}
Calling Code
var processor = TagProcessorFactory.GetProcessor(tag.Name);
if (!(processor is UnknownTagProcessor))
{
var data = processor.Process(unitId, tag.Values);
Trace.WriteLine("Tag <{0}> processed. # of IO Items => {1}".FormatWith(tag.Name, data.Count()));
}
as you can see one of my items has dependencies and im trying to execute testing code and i want to pass in mock repositories and cache providers but i can seem to think of a way to do this.
Is this a bad design or anyone have any ideas to fix it to make my factory testable?
Thanks
Since you are using Autofac, you can take advantage of the lookup relationship type:
public class Foo
{
private readonly IIndex<string, ITagProcessor> _tagProcessorIndex;
public Foo(IIndex<string, ITagProvider> tagProcessorIndex)
{
_tagProcessorIndex = tagProcessorIndex;
}
public void Process(int unitId, Tag tag)
{
ITagProcessor processor;
if(_tagProcessorIndex.TryGetValue(tag.Name, out processor))
{
var data = processor.Process(unitId, tag.Values);
Trace.WriteLine("Tag <{0}> processed. # of IO Items => {1}".FormatWith(tag.Name, data.Count()));
}
}
}
See the TypedNamedAndKeysServices wiki article for more information. To register the various processors, you would associate each with its key:
builder.RegisterType<GpsTagProcessor>().Keyed<ITagProcessor>("gps0");
builder.RegisterType<AnalogManagerTagProcessor>().Keyed<ITagProcessor>("analog_manager");
builder.RegisterType<InputManagerTagProcessor>().Keyed<ITagProcessor>("input_manager");
builder
.Register(c => new J1939TagProcessor(new MemcachedProvider(new[] { "localhost" }, new PgnRepository()))
.Keyed<ITagProcessor>("j1939");
Notice we don't register UnknownTagProcessor. That was a signal to the caller of the factory that no processor was found for the tag, which we express using TryGetValue instead.
Using something like StructureMap you could use the ObjectFactory which, when configured would return you a named concrete instance.
http://structuremap.net/structuremap/index.html
I suggest you look through another SO post. It solves several problems at once, including how to replace contructor values - without a mess. Specifically, the parameters to the constructor simply become static fields of a "Context" class, which are read by the constructor of the interior class.
Does anyone have a good example for common error handling for service calls? I just started a new project and I see a lot of duplicate code that I don't like and would like to get rid of. I manage to do so in several other layers but in the proxy layer making the calls to services it is a little bit harder. The code is basically structured as follows:
ResponseType MyProxyFunc(different, parameters)
{
var client = MyServiceClient();
using (Tracer functionTracer = new Tracer(Constants.TraceLog))
{
try
{
var response = client.MyRequest(different, parameters);
if (response.ErrorCode != Constants.OK)
{
ProxyCommon.ThrowError(besvarelseDS.Status[0].ErrorCode);
}
}
finally
{
ProxyCommon.CloseWcfClient(client);
}
return response;
}
}
The code above is just a sample, the ProxyCommon object is a static class with various methods (should probably not be abstract instead of static but that is another discussion). So does anyone have a good suggestion how to abstract this piece of code? I want to have the using, the try/catch and the if-statment in somekind of abstract method, but it's hard since MyServiceClient differs, the numbers of parameters differs and the request is not the same.
EDIT: A pattern I've used before is to use a generic Execute function like public T Execute<T>(Func<T> func). But I can't get that type of pattern to work in this case.
EDIT #2: I've updated the code but I'm not 100 % satisfied, more like 60-75 %. The problem with the code below is that it uses the service objects and they will not be the same for all services, but this will work for service calls against the service in the example that has a wrapped request and response object which it's ok. But I still don't think this is the solution to the problem:
public IList<PGSA.Data.Cargo.PGSAReportCargo> GetPGSAReport(DateTime dateFrom, DateTime? dateTo)
{
var reportService = new ReportServiceClient();
var request = new GetPGSAReportRequest()
{
SystemCode = Settings.SystemID,
FromDate = dateFrom,
ToDate = dateTo
};
var response = Execute(reportService, reportService.GetPGSAReport, request);
return response.PGSAReport.ToList();
}
public L Execute<T, K, L>(T client, Func<K, L> serviceFunc, K request)
where T : ICommunicationObject
where K : RequestBase
where L : ResponseBase
{
using (Tracer functionTracer = new Tracer(Constants.TraceLog))
{
try
{
L response = serviceFunc(request);
if (response.ErrorCode != Constants.OK)
{
ProxyCommon.ThrowError(response.ErrorCode);
}
return response;
}
finally
{
ProxyCommon.CloseWcfClient(client);
}
}
}
EDIT #3: The ResponseBase and RequestBase in EDIT #2 are base classes defined by the service.
Your last approach looks fine to me - I would simplify it slightly as follows:
public R Execute<T, R>(this T client, Func<R> serviceFunc)
where T : ICommunicationObject
where L : ResponseBase
{
using (Tracer functionTracer = new Tracer(Constants.TraceLog))
{
try
{
R response = serviceFunc();
if (response.ErrorCode != Constants.OK)
{
ProxyCommon.ThrowError(response.ErrorCode);
}
return response;
}
finally
{
ProxyCommon.CloseWcfClient(client);
}
}
}
And use it
reportService.Execute(() => reportService.GetPGSAReport(request));
Idea here is to eliminate dependency on not needed request object.