I am considering the architecture for an enterprise logging service. Its job would be to receive and store log messages and then allow开发者_运维问答 access to those log messages to users. Instead of building the logging functionality into our one existing Windows service that would use it for now, we need to separate it so that other services could use it in the near future. I like the fact that our various services could log their messages over net.tcp and then I could build a RESTful interface for delivering specific log messages to browsers or whatever.
Could anyone speak to the wisdom or lack of the following choices:
- Use WCF for the logging service
- Use net.tcp for the transport
- Host the service in a Windows Service project (using ServiceHost)
Also, how might I design it such that it takes advantage of some rather beefy servers that are going to be hosting it? Is it possible to open up multiple connections (or is that done automatically) or implement some automatic multi-threading?
The one service we currently have that would be utilizing this logging service is quite verbose and would be sending log messages very frequently (~40-100k/day). I have not yet built up a prototype and done any benchmarking and I know I'm not giving you enough details to make a definitive decision, but I'm just looking for some direction and considerations at this point. Thanks.
There are other alternatives to creating one more service just for logging. You could build the logging as an aspect and attach/detach this aspect (aka inject) as and when required by any ServiceContract
or OperationContract
. This way you decouple logging but it avoids the overhead of calling one more service on every call. Once you create these aspects, compile them away in separate binary and use them as and when needed in all of your future services, enabling and disabling specific logging scenarios are more maintainable IMO compared to having a dedicated service for just logging.
Have a look at following two posts and they provide simplistic approach of doing this, you'd have to fill in the flesh as you want for your project.
- Creating a logging Aspect
- WCF Extensibility: Parameter Inspectors
Important MSDN documentation you'd want to look at.
- IParameterInspector
- IOperationBehavior
- IServiceBehavior
Edit - Sample Code
With below code you add [OperationLogging]
above any of your operation contract, and you can intercept calls to this operation contract in LoggingInspector.BeforeCall
.
Use [ServiceLogging]
on any service contract and all the operations defined in that service calls could be intercepted and logged.
Set your_app_config_key
to anything other than TRUE
these additional behaviors are not added to your service pipeline. That is very cool as none of this code is executed based on this key in config.
public class LoggingInspector : IParameterInspector
{
private string service;
public LoggingInspector(string serviceName){ service = serviceName;}
public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState){}
public object BeforeCall(string operationName, object[] inputs)
{
// your logging logic
}
}
//Operation Logging attribute - applied to operationcontracts.
[AttributeUsage(AttributeTargets.Method)]
public class OperationLoggingAttribute : Attribute, IOperationBehavior
{
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters){}
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation){}
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
if (ConfigurationManager.AppSettings["your_app_config_key"] == "TRUE")
dispatchOperation.ParameterInspectors.Add(new LoggingInspector(dispatchOperation.Parent.Type.Name));
}
public void Validate(OperationDescription operationDescription){}
}
//Service Loggign attribute - applied to Service contract
[AttributeUsage(AttributeTargets.Class)]
public class ServiceLoggingAttribute : Attribute, IServiceBehavior
{
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters){}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
if (ConfigurationManager.AppSettings["your_app_config_key"] == "TRUE")
foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints)
foreach (OperationDescription operation in endpoint.Contract.Operations)
operation.Behaviors.Add(new OperationLoggingAttribute());
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase){}
}
In principal I think a single audit service makes sense, provided it falls within the bounded context of your application(s). IDesign have a sample implementation of a ES Logbook here (look for the "The Enterprise Services Logbook"). You could do some initial testing to see if it can handle the loads you are expecting. If you are worried about performance I would consider message queuing over tcp (the sample logging application also supports this). As for hosting, the service needs to be always running, so Windows Service makes sense. If you want to use IIS then I would suggest using Windows Server AppFabric and enable the AutoStart feature of the application.
HTH.
Reading the question i have some thoughts to share. Logging itself is not a terribly complex activity and using WCF to create a enterprise logging framework would be fine. But data logged just for logging is of no use. This data then needs to be consumed by some process\app and hence provide some value addition. Therefore the more important aspect of logging are
- What data is being logged.
- How data logged is being consumed\utilized
So my advice would be to spend more time thinking about what needs to be logged and what value this data adds.
精彩评论