2011-01-08 164 views
6

我有一套web服务,我想添加一个跟踪图层。 我不想修改每个Web服务,因为我有很多。 我想写入每一个输入到Web服务的日志:Web服务和参数的名称。webservices跟踪/日志

这样做的最佳方法是什么?

P.S.我正在使用asp.net和C#。

编辑: 我只想包裹Web服务作为每一个都会有开头日志(..)。

+0

“我不想修改每个Web服务,因为我有很多” - 估计你可以使用AOP,否则我认为你将不得不这样做。 ... – 2011-01-08 03:11:12

+2

您可以使用服务器访问日志 – 2011-01-08 03:14:07

+0

请参阅SoapExtension类上的MSDN文档。它有一个日志记录的例子。 – 2011-01-08 03:54:25

回答

6

实现此目的的常见方法是注入SOAP扩展。从那里你可以拦截原始SOAP中的每个请求/响应数据包。该示例展示了如何实现它,并解释了它如何工作以及如何配置它。

样品:

http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soapextension.aspx

说明:

http://msdn.microsoft.com/en-us/library/esw638yk(vs.71).aspx

配置:

http://msdn.microsoft.com/en-us/library/b5e8e7kk(v=vs.71).aspx

<configuration> 
<system.web> 
    <webServices> 
    <soapExtensionTypes> 
     <add type="{Type name}, {Assembly}" priority="1" group="0" /> 
    </soapExtensionTypes> 
    </webServices> 
</system.web> 
</configuration> 
0

我保持Open source web services framework,可以让你简单地通过使所有Web服务从基类继承,做你自己的日志实现这一目标。

这里是一个example of a base-class,我保持一个分布式滚动日志所有异常的redis - 非常快的NoSQL数据存储库:

public object Execute(TRequest request) 
{ 
    try 
    { 
     //Run the request in a managed scope serializing all 
     return Run(request); 
    } 
    catch (Exception ex) 
    { 
     return HandleException(request, ex); 
    } 
} 

protected object HandleException(TRequest request, Exception ex) 
{ 
    var responseStatus = ResponseStatusTranslator.Instance.Parse(ex); 

    if (EndpointHost.UserConfig.DebugMode) 
    { 
     // View stack trace in tests and on the client 
     responseStatus.StackTrace = GetRequestErrorBody() + ex; 
    } 

    Log.Error("ServiceBase<TRequest>::Service Exception", ex); 

    //If Redis is configured, maintain rolling service error logs in Redis (an in-memory datastore) 
    var redisManager = TryResolve<IRedisClientsManager>(); 
    if (redisManager != null) 
    { 
     try 
     { 
      //Get a thread-safe redis client from the client manager pool 
      using (var client = redisManager.GetClient()) 
      { 
       //Get a client with a native interface for storing 'ResponseStatus' objects 
       var redis = client.GetTypedClient<ResponseStatus>(); 

       //Store the errors in predictable Redis-named lists i.e. 
       //'urn:ServiceErrors:{ServiceName}' and 'urn:ServiceErrors:All' 
       var redisSeriviceErrorList = redis.Lists[UrnId.Create(UrnServiceErrorType, ServiceName)]; 
       var redisCombinedErrorList = redis.Lists[UrnId.Create(UrnServiceErrorType, CombinedServiceLogId)]; 

       //Append the error at the start of the service-specific and combined error logs. 
       redisSeriviceErrorList.Prepend(responseStatus); 
       redisCombinedErrorList.Prepend(responseStatus); 

       //Clip old error logs from the managed logs 
       const int rollingErrorCount = 1000; 
       redisSeriviceErrorList.Trim(0, rollingErrorCount); 
       redisCombinedErrorList.Trim(0, rollingErrorCount); 
      } 
     } 
     catch (Exception suppressRedisException) 
     { 
      Log.Error("Could not append exception to redis service error logs", suppressRedisException); 
     } 
    } 

    var responseDto = CreateResponseDto(request, responseStatus); 

    if (responseDto == null) 
    { 
     throw ex; 
    } 

    return new HttpResult(responseDto, null, HttpStatusCode.InternalServerError); 
} 

否则,对于普通的ASP.NET Web服务框架,我想看看全球.asax事件,特别是每当新请求进入时触发的'Application_BeginRequest'事件。

+3

@mythz:请透露您与ServiceStack的连接。尽管这是一个开源项目,但像这样的建议仍然等同于垃圾邮件。这不是我第一次见到你推荐ServiceStack。除其他问题外,您还没有展示如何使用它来解决这个问题。 – 2011-01-19 00:43:15

+0

我已经提出了如何在他使用其他Web服务框架的情况下很容易实现的建议。原来的问题从未指定过它是什么。我最初的回答也提供了Global.asax事件的位置,可以让他实现他的目标。你为什么不自己提供一个更好的答案?我个人认为,您对特定Web服务技术/框架的规范是您行为的主要动机。 – mythz 2011-01-19 01:02:45

+1

@mythz:它看起来像他指定ASP.NET Web服务。那和我以前从未听说过服务堆的事实可能与我有礼貌地问你,要透露。谢谢你这样做,我希望你每次推荐这个框架时都会这样做。你也应该建议实际展示你的框架如何解决这个问题。 – 2011-01-19 01:13:30

0

如果编程语言不重要,可以将Apache Synapse作为代理服务器放在您的服务之前。您的客户会将请求发送给Synapse,Synapse会将请求委托给您的原始服务。可以将代理配置为对其中的请求执行某些操作,例如日志记录。

请参阅有关详细信息,下面的链接:

http://synapse.apache.org/Synapse_Configuration_Language.html#proxy
http://synapse.apache.org/Synapse_Configuration_Language.html#send
http://synapse.apache.org/Synapse_Configuration_Language.html#log

以下实例的组合可以为你工作:

http://synapse.apache.org/Synapse_Samples.html#Sample0
http://synapse.apache.org/Synapse_Samples.html#ProxyServices

例如: -

<definitions xmlns="http://ws.apache.org/ns/synapse" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://ws.apache.org/ns/synapse http://synapse.apache.org/ns/2010/04/configuration/synapse_config.xsd"> 

<proxy name="StockQuoteProxy"> 
    <target> 
     <endpoint> 
      <address uri="http://localhost:9000/services/SimpleStockQuoteService"/> 
     </endpoint> 
     <outSequence> 
      <!-- log all attributes of messages passing through --> 
      <log level="full"/> 

      <!-- Send the message to implicit destination --> 
      <send/> 
     </outSequence> 
    </target> 
    <publishWSDL uri="file:repository/conf/sample/resources/proxy/sample_proxy_1.wsdl"/> 
</proxy> 

0

如何writing your own HttpModule?这将否定触摸现有Web服务代码的需要。您只需将模块添加到每个web.config文件。

1

将全局应用程序类Global.asax文件添加到您的项目并将日志记录逻辑添加到Application_BeginRequest()方法。 发件人对象将包含HTTP请求和参数。您可以筛选.asmx请求并记录这些请求。

protected void Application_BeginRequest(object sender, EventArgs e) 
    { 

    } 
1

编辑 -
给PostSharp一个尝试。这是获得此功能的最简单方法。对于后代,我会在下面留下我的帖子,但忽略它并使用PostSharp。


如果您的网络服务是WCF,那么你应该检查出http://msdn.microsoft.com/en-us/magazine/cc163302.aspx

在每一步中,他们都提供了可插入的扩展点。您可以使用这些扩展点来实现各种自定义行为,包括消息或参数验证,消息日志记录,消息转换。

毫无疑问,这是WCF服务的方式。否则,如果他们只是Web服务,那么你可以使用Unity框架和连接和Interceptor来做同样的事情。

-1

我不知道如果这是你在找什么,只是将它添加到您WCF配置文件后,“”

这将产生非常广泛的日志记录,你将能够使用微软阅读服务跟踪查看器

<system.diagnostics> 
    <sources> 
    <source name="System.ServiceModel.MessageLogging" switchValue="Warning, ActivityTracing"> 
    <listeners> 
    <add type="System.Diagnostics.DefaultTraceListener" name="Default"> 
     <filter type="" /> 
    </add> 
    <add name="ServiceModelMessageLoggingListener"> 
     <filter type="" /> 
    </add> 
    </listeners> 
    </source> 
    <source name="System.ServiceModel" switchValue="Warning, ActivityTracing" 
    propagateActivity="true"> 
    <listeners> 
    <add type="System.Diagnostics.DefaultTraceListener" name="Default"> 
     <filter type="" /> 
    </add> 
    <add name="ServiceModelTraceListener"> 
     <filter type="" /> 
    </add> 
    </listeners> 
    </source> 
    </sources> 
    <sharedListeners> 
    <add initializeData="C:\ServiceLog.svclog" 
    type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 
    name="ServiceModelMessageLoggingListener" traceOutputOptions="Timestamp"> 
    <filter type="" /> 
    </add> 
    <add initializeData="C:\Tracelog.svclog" 
    type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 
    name="ServiceModelTraceListener" traceOutputOptions="Timestamp"> 
    <filter type="" /> 
    </add> 
    </sharedListeners> 
</system.diagnostics>