I'm currently writing a custom logging method for my Web API where users can purchase items. This log method will log all the steps the users takes while following a purchase process so support can later track the steps. There are multiple steps like:
Creating a order
Updating a order
Purchasing a item
Receiving status
etc..
This method will return one 'Event' object where all the necessary log information is combined, for example the LogLevel, Message, UserId and more, and write this to a database.
Before i can reach this point, i have to create the very useful log message. The message is based on these two enums (explanation is a bit simplified):
ActionName - At which step in my process is this log event called
ActionOrigin - Is the recorded log event from my front end or backend system...
It is also based on a object where the necessary log values, like order id for example, are provided.
The log class where the log event method is defined is a scoped injected class so i can log events every where critical in my code.
The first thing that came into my mind was creating a switch statement and create the messages based on the correct case. But this would combine 2 switch statements and quickly started to look like a mess.
I did some research and found the strategy pattern. I'm not completely sure if this can help me? Are there any other ideas or examples?
Whenever you are working on an object model and find yourself writing a ton of switch statements, it usually means you've put the class-specific logic in the wrong place. You should put it with the class itself, not the class that consumes it.
To put it another way, your logger should not know how to log each and every type of event. That would be a maintenance nightmare. Instead, it should know how to log a common object (e.g. a string), and each event should itself know how to create that common object, via a common method that the logger knows about. That is the only thing it needs to know.
Here is a simple example. In this case, the logger accepts any type of LoggableEvent and calls its Serialize() method to figure out how it gets added to the common log. The event itself is responsible for knowing how to serialize itself.
abstract class LoggableEventBase
{
public string ActionName { get; }
public string ActionOrigin { get; }
public LoggableEventBase(string actionName, string actionOrigin)
{
ActionName = actionName;
ActionOrigin = actionOrigin;
}
public virtual string Serialize()
{
return string.Format("{0} {1}", ActionName, ActionOrigin);
}
}
class CreateOrderEvent : LoggableEventBase
{
protected readonly List<Item> _items;
protected readonly int _orderId;
public CreateOrderEvent(string origin, int orderID, List<Item> items) : base("CreateOrder", origin)
{
_orderId = orderID;
_items = items;
}
public override string Serialize()
{
return base.Serialize() + string.Format(" {0} {1}", _orderId, string.Join(",", _items.Select(item => item.SKU)));
}
}
Now the actual logging logic is rather simple-- no switch statements or anything else that needs to know what the event is:
class Logger : ILogger
{
public void Log(LoggableEventBase eventToLog)
{
Write(eventToLog.Serialize());
}
protected virtual void Write(string message)
{
//Write the message to a log file
}
}
To add additional event types, you just need to define the new class (and override Serialize()). You never have to go back and modify the Logger class. This is more consistent with the Open-Closed Principle than your existing solution.
This is a design pattern question. You might want to read on different patterns used for the language/framework you are using. It seems like you are trying to avoid writing your logs in line. One way of doing it would be to define the format for your different messages in a constant and use string interpolation (or simple concatenation) to build the message with a log() method.
Example (I'll do my best to write proper C#, please edit any mistakes or inadequacies):
class Logger {
// If you want personalized messages for different actions or origins, define their template constants and create different methods for building them.
public const string ORDER_PROGRESS_MSG_TMPL = "Action:{0}, Origin:{1}, OrderId:{3}";
void log_order_progress(string actionName, sting actionOrigin, string orderId){
Console.WriteLine(
ORDER_PROGRESS_MSG_TMPL, actionName, actionOrigin, orderId
);
}
}
Order
class Order {
...
void create(int orederId){
Logger.log_order_progress(ActionEnum.CREATING, OriginEnum.BACK_END, orderId)
// Do some stuff here to create order
Logger.log_order_progress(ActionEnum.UPDATING, OriginEnum.BACK_END, orderId)
// etc
}
}
This is a way of doing it, you could modularize it more by having templates in their own class. Also you could create (or better: use an existing logging framework) to differentiate level of logging (debug, info, error) as #Sandeep Sharma described.
You can create multiple methods in your Logger class, each for specific scenario.
The methods can be :
info() = for logging some information.
debug() = for debugging.
error() = for logging an error event.
Let's say you want to log an event of purchasing an item , and when user does buy action, you can pass information to the logger.info() method.
If you encounter an error, or a certain action or condition was not fulfilled , you can pass data to the method error() , which will log error in your case.
For messages :
1. Action Name - You can pass the method name or route path that was called by action of an user.
2. Action Origin - Provide details like user name , full path , action type etc.
You can also maintain fields like 'timestamp' and some 'unique-identifier' for better logging of events.
Related
I have a custom build log framework that logs to a database.
For example it can do
L.e("Error invalid password", userGuid);
This works fine for general use but the application is quite complex and there are a lot of different parts that are called from the main code. For example a login sequence could send an SMS for OTP which is handled by a completely other part of the system and it does not make sense to pass a lot of values thru just for logging purposes.
What I want to achieve is to tag the log with for example userGuid so that I can search for everything related to this specific user. I also want to tag any logging in the SMS module even though the SMS module does not know anything about the user concept.
So what I am thinking of is if it is possible to get the current threadid and store some things regarding the logging in a higher level. I wonder if this is at all possible.
Psuedo code:
void Login(UserName, Password) {
User user = UserManager.GetUser(UserName)
using(L.SetUser(user.ID)) { //Here I want to use user.ID later in code that dont know the context
SmsManager.SendOtp(user.Phonenumber)
}
}
public class SmsManager {
public static void SendOtp(string phonenumber) {
if (phonenumber == "") {
L.error("Phone number is empty"); //How can I use the value from L.SetUser above? Could I use a hash table of threadids in L or would that be a bad idea?
}
}
}
Kind regards
Jens
Can you show us some snippets from L? Is that a static class? Does SetUser set a static variable? You could use the using block the way you suggest. You'd want to implement IDisposable and clear the UserID value in the Dispose method. But if UserID is a static variable, then this solution will not work in a multi-threaded environment (without some other changes). And the design just seems odd to me.
Overall seems like you are using static a lot. That can get you into trouble.
There are lots of possible solutions. Tough to say what's best without seeing some more code. Here is one way using dependency injection to keep your modules separate, as you want.
Define an interface for your logger.
public interface ILogger
{
void Error(string message);
}
Implement with a class that adds the user information:
public class MessageWithUserLogger : ILogger
{
private readonly string _userId;
public MessageWithUserLogger(string userId)
{
_userId = userId;
}
public void Error(string message)
{
L.error(message, _userId);
}
}
Change SmsManager class to be non-static and depend on the ILogger abstraction rather than the L implementation:
public class SmsManager
{
private readonly ILogger _logger;
public SmsManager(ILogger logger)
{
_logger = logger;
}
public void SendOtp(string phonenumber)
{
if (phonenumber == "")
{
_logger.Error("Phone number is empty");
}
}
}
Inject the logger with userID when that information is available:
void Login(UserName, Password)
{
User user = UserManager.GetUser(UserName);
ILogger logger = new MessageWithUserLogger(user.ID);
SmsManager smsManager = new SmsManager(logger);
smsManager.SendOtp(user.Phonenumber);
}
The using statement is not intended to be used like this. The using statement was introduced to be able to define a limited scope, and at the same time make sure objects are disposed using the IDisposable interface (see also https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement).
The way you are using the using statement makes it seems as if the property is sent when you start the scope, and would somehow be "unset" afterwards, but this is not the case.
When working with loggers and starting from your pseudo code, I would say your logging framework should be extended to create a context specific logger when you go into the using, and then pass the logging context to the static function. it would look then as below:
void Login(UserName, Password) {
User user = UserManager.GetUser(UserName)
using(var logContext = L.CreateContext(user.ID)) { //Here I want to use user.ID later in code that dont know the context
SmsManager.SendOtp(logContext, user.Phonenumber)
}
}
public class SmsManager {
public static void SendOtp(LogContext logContext, string phonenumber) {
if (phonenumber == "") {
logContext.error("Phone number is empty"); //How can I use the value from L.SetUser above? Could I use a hash table of threadids in L or would that be a bad idea?
}
}
}
Instead of passing the log context, it is theoretically possible to store the context inside the L object and map it to a thread ID, and, later on in the functions check if there is a specific log context for that thread when you log something. In the IDisposable interface implementation of the LogContext object, you should then remove the context (which corresponds with the end of your using() scope). I would however not do this, because it "hides" a bunch of logic, but even more, it relies on the fact that every function will be executed in the same thread. This in combination with hiding this, makes it a possible source of errors (if the user of the code isn't aware that this is linked to the thread, and changes the thread, you might miss information, make wrong assumptions based on the logging, etc). I think it is not bad practice if you have functions like the SMS manager that has a number of helper functions, to pass in a context specific object.
Also, be aware that this is a concept that exists in most popular logging libraries such as Serilog, and, in almost all cases, writing your own logging libraries isn't the most profitable business (since most of these libraries also have extensions that allow you to write a custom sink, which for example would then write the log output to a database for your specific scenario (but you get all the rest for free).
I have a C# web api project, basically I need to log everytime a method is getting called (ie. method name, parameters passed, result, stacktrace (if error occured), etc).
Right now, I did this by adding few lines to every method and it seems bloated, is there more efficient way to achieve this?
Any help will be appreciated.
Thank you
Middleware is one approach, or you can also create a Filter that lets you perform 'before' and 'after' operations,
https://www.tutorialsteacher.com/webapi/web-api-filters
[Code from the above link]
public class LogDemoAttribute : Attribute, IActionFilter
{
public LogDemoAttribute()
{
}
public async Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
{
Trace.WriteLine(string.Format("Action Method {0} executing at {1}", actionContext.ActionDescriptor.ActionName, DateTime.Now.ToShortDateString()), "Web API Logs");
var result = await continuation();
Trace.WriteLine(string.Format("Action Method {0} executed at {1}", actionContext.ActionDescriptor.ActionName, DateTime.Now.ToShortDateString()), "Web API Logs");
return result;
}
public bool AllowMultiple
{
get { return true; }
}
}
This does let you add to the Global Filters (in which case, you might as well use a Middleware), or add it selectively to certain endpoints, e.g
[ApiController]
public class PeopleController : ControllerBase
{
[LogDemo]
[HttpGet("demo/endpoint")]
public IActionResult GetAll()
{
}
}
This has the advantage that you might want to pass in some parameters to the attribute, that let you perform certain context specific behaviours.
If you want to add logging to non-controller code, then you can take this approach further to an Aspect Orientated / Decorator pattern.
https://learn.microsoft.com/en-us/archive/msdn-magazine/2014/february/aspect-oriented-programming-aspect-oriented-programming-with-the-realproxy-class
I generally find logging parameters at the controller level is good enough, and something like Application Insights that generates telemetry that shows you what the request looks like is actually the useful bit of information.
When you're saying "method" I'm unsure if you mean literally every method or just whenever a controller is being hit. But middleware would probably be the way to go. The documentation on adding custom middleware is here: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/write?view=aspnetcore-3.1
And here is an example of error handling middleware, where you could place your logging: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/error-handling?view=aspnetcore-3.1
On an Azure Mobile App Services server side app using MVC 5, Web API 2.0, and EF Core 1.0, controllers can be decorated like so to implement token based authentication:
// Server-side EF Core 1.0 / Web API 2 REST API
[Authorize]
public class TodoItemController : TableController<TodoItem>
{
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
DomainManager = new EntityDomainManager<TodoItem>(context, Request);
}
// GET tables/TodoItem
public IQueryable<TodoItem> GetAllTodoItems()
{
return Query();
}
...
}
I want to be able to do something similar on the client side where I decorate a method with something like [Authorize] from above, perhaps with a, [Secured], decoration, below:
public class TodoItem
{
string id;
string name;
bool done;
[JsonProperty(PropertyName = "id")]
public string Id
{
get { return id; }
set { id = value;}
}
[JsonProperty(PropertyName = "text")]
public string Name
{
get { return name; }
set { name = value;}
}
[JsonProperty(PropertyName = "complete")]
public bool Done
{
get { return done; }
set { done = value;}
}
[Version]
public string Version { get; set; }
}
// Client side code calling GetAllTodoItems from above
[Secured]
public async Task<ObservableCollection<TodoItem>> GetTodoItemsAsync()
{
try
{
IEnumerable<TodoItem> items = await todoTable
.Where(todoItem => !todoItem.Done)
.ToEnumerableAsync();
return new ObservableCollection<TodoItem>(items);
}
catch (MobileServiceInvalidOperationException msioe)
{
Debug.WriteLine(#"Invalid sync operation: {0}", msioe.
}
catch (Exception e)
{
Debug.WriteLine(#"Sync error: {0}", e.Message);
}
return null;
}
Where [Secured] might be defined something like this:
public class SecuredFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Check if user is logged in, if not, redirect to the login page.
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
// Check some globally accessible member to see if user is logged out.
}
}
Unfortunately, the above code only works in Controllers in MVC 1.0 applications and above according to the Microsoft article on "Creating Custom Action Filters": https://msdn.microsoft.com/en-us/library/dd381609(v=vs.100).aspx
How do I implement something like a "Custom Action Filter" that allows me to use the "[Secured]" decoration in a Mobile App Service client instead of the server? The answer will help me create custom authentication from the client side and keep the code in one location without complicating the implementation, i.e., it is a cross-cutting concern like performance metrics, custom execution plans for repeated attempts, logging, etc.
Complicating the scenario, the client also implements Xamarin.Forms for iOS and has to be a functional Ahead of Time pattern due to iOS's requirement for native code, JIT is not yet possible.
The reason attributes work in the scenarios you describe is because other code is responsible for actually invoking the methods or reading the properties, and this other code will look for the attributes and modify behaviour accordingly. When you are just running C# code, you don't normally get that; there isn't a native way to, say, execute the code in an attribute before a method is executed.
From what you are describing, it sounds like you are after Aspect Oriented Programming. See What is the best implementation for AOP in .Net? for a list of frameworks.
In essence, using an appropriate AOP framework, you can add attributes or other markers and have code executed or inserted at compile time. There are many approaches to it, hence why I am not being very specific, sorry.
You do need to understand that the AOP approach is different from how things like ASP.Net MVC works as AOP will typically modify your runtime code (in my understanding anyway and I'm sure there are variations on that as well).
As to whether AOP is really the way to go will depend on your requirements, but I would proceed with caution - it's not for the faint of heart.
One completely alternative solution to this problem is to look at something like Mediatr or similar to break your logic into a set of commands, which you can call via a message bus. The reason that helps is that you can decorate your message bus (or pipeline) with various types of logic, including authorization logic. That solution is very different from what you are asking for - but may be preferable anyway.
Or just add a single-line authorisation call as the first line inside each method instead of doing it as an attribute...
What you are more generally describing in known by a few different names/terms. The first that comes to mind is "Aspect Oriented Programming" (or AOP for short). It deals with what are known as cross cutting concerns. Im willing to bet you want to do one of two things
Log exceptions/messages in a standardized meaningful way
Record times/performance of areas of your system
And in the generala sense, yes C# is able to do such things. There will be countless online tutorials on how to do so, it is much too broad to answer in this way.
However, the authors of asp.net MVC have very much thought of these things and supply you with many attributes just as you describe, which can be extended as you please, and provide easy access to the pipeline to provide the developer with all the information they need (such as the current route, any parameters, any exception, any authorization/authentication request etc etc)
This would be a good place to start: http://www.strathweb.com/2015/06/action-filters-service-filters-type-filters-asp-net-5-mvc-6/
This also looks good: http://www.dotnetcurry.com/aspnet-mvc/976/aspnet-mvc-custom-action-filter
I have a situation in a project I am currently working on at work that has left my mind restless the entire weekend. First, I need to explain my scenario, and the possible solutions I have considered.
I am writing a composite WCF service that will be aggregating a large amount of external API's . These API's are arbitrary and their existence is all that is needed for this explanation.
These services can be added and removed throughout the period of development. My WCF service should be able to consume the services using several methods (REST,SOAP,etc). For this example, I am focusing on communicating with the external APIS by manually creating the requests in code.
For example, we might have two API's ServiceX and ServiceY.
ServiceX is consumed by POST ing a web request with the data in the request body specifically.
ServiceY is consumed by POST ing a web request with the data appended to the URL(Yes...I know this should be a GET, but I didn't write the external API, so don't lecture me about it.)
In order to avoid redundant, duplicate code, I have wrapped the web requests using the command pattern, and am using a factory to build the requests.
For ServiceX, the data needs to be encoded and put into the request body, as oppose to ServiceY where the data needs to be iterated over and placed on the Post string.
I have a class structure like the following:
public abstract class PostCommandFactory
{
public ICommand CreateCommand();
}
public class UrlPostCommandFactory:PostCommandFactory
{
public ICommand CreateCommand()
{
//Initialize Command Object Here
}
}
public class BodyPostCommandFactory:PostCommandFactory
{
public ICommand CreateCommand()
{
//Initialize Command Object Here
}
}
public interface ICommand
{
string Invoke();
}
public class UrlPostCommand:ICommand
{
public string Invoke()
{
//Make URL Post Request
}
}
public class BodyPostCommand:ICommand
{
public string Invoke()
{
//Make Request Body Post Request
}
}
This allows me to cleanly separate the way that I am binding data to the request when they need to be send out, and essentially, I can also add additional classes to handle GET requests. I am not sure if this is a good use of these patterns. I am thinking an alternative might be using the Strategy pattern and specifying strategy objects for the different Request methods I might need to use. Such as the following:
public class RequestBodyPostStrategy:IPostStrategy
{
public string Invoke()
{
//Make Request Body POST here
}
}
public class UrlPostStrategy:IPostStrategy
{
public string Invoke()
{
//Make URL POST here
}
}
public interface IPostStrategy
{
string Invoke();
}
public class PostContext
{
pubic List<IPostStrategy> _strategies;
public IPostStrategy _strategy;
public PostContext()
{
_strategies = new List<IPostStrategy>();
}
public void AddStrategy(IPostStrategy strategy)
{
_strategies.Add(strategy);
}
public void SetStrategy(IPostStrategy strategy)
{
_strategy = strategy;
}
public void Execute()
{
_strategy.Invoke();
}
}
I am starting to think the Strategy pattern may be the cleaner solution.
Any thoughts?
I would use both.
Command is best practice for encapsulating requests and hiding implementation details. You should probably use it even if you only have one kind of request, as it promotes cleaner code. Essentially it's good practice to consider "what is the absolute minimum the rest of my code needs to know about how requests are executed and handled", which will lead you to the Command pattern.
Strategy is basically configuring your system at runtime with a general, consitent way to handle some ascpect of the operation, in this case generating the requests. This is also a good practice for testing, as you can substitute a test implementation of your strategy/request factory to fake actual connections etc.
Based on the examples for Command and Strategy that you have given, the Command pattern example looks exactly like a Strategy which I guess lead you to Strategy. I would also go with Strategy but would like to add that there's more to Command pattern than what you have included in the example. You should ask yourself questions like:
Do these Commands need to be stored and should be executed later point in time?
Is there a Invoker that needs to invoke these commands without caring about Command internals?
Would you want to have functionality of grouping different Commands together and executing them?
If this is the case then you should choose Command Pattern.
I am working on a website and we will need to send the user some email notifications when some actions happen on the website, such as if someone else sent the user a message or invite him to an event.
Is there a standard good way to attach a notification to any method without changing the method code?
For example I was thinking if I can put an attribute on the method this attribute will make this method to call the notification module with some parameters.
note: I am working on an ASP.Net MVC 3 website, using entity framework codefirst.
I do not believe there is a standard process.
Aspect Oriented approaches (such as attributes) can be handy only if there are used in conjunction with AOP frameworks (such as AspectSharp) or when used on the MVC Action itself: you can use action filters to achieve the requirement and send use the notification if the events are mapped to MVC actions.
Event Listeners. You do have to change the code, but you don't actually send the email within the code.
Basically, any code that does stuff that other code might be interested in has hooks so that listeners can attach to it and listen for events.
In Pseudo-java:
public class OrderProcessor {
protected final List<OrderProcessorListener> listeners = new ArrayList<OrderProcessorListener>();
public void addListener(OrderProcessorListener orderProcessorListener) {
listeners.add(orderProcessorListener);
}
public void notifyListeners(OrderProcessorEvent event) {
for(OrderProcessorListener listener : listeners) {
listener.handle(event);
}
}
public void randomMethod() {
// ... do stuff
notifyListeners(new SomeEvent(...)); // notify listeners
}
public interface OrderProcessorListener {
public void handle(OrderProcessorEvent event);
}
}
then, other interested code can do...
public class EmailSender implements OrderProcessorListener {
public void handleEvent(OrderProcessorEvent event) {
// do whatever...
}
}
When you construct your OrderProcessor and your EmailSender, you then add the EmailSender as a listener and voila. You can use this pattern everywhere you need to react to actions from a piece of code- and you don't need to put the actions in the same code...
Would be pretty hard without any change to the original code. How would you know an action succeeded? And what type of notification should be sent, to whom, etc.
If not changing the original code is a must, you could do it in a hacky way: add a global filter, inspect the controller name, action name, the action result, and maybe you could decide from those parameters if an email should be sent. But this would be extremely fragile, and a maintenance nightmare.
Unless your notifications are extremely simple, like always send e-mail to all event attendees, if any modification is done to the event. But that could cover only some of the basic use-cases...
IMO it would be better if you integrated sending notifications into your existing code. If you extend the meaning of a repository (and you use one) to "take database actions, and anything else related to creation/update/delete of an object".
No changes to controller actions, and your EventRepository.Create/Modify methods would know already have all the parameters to send the notifications...