трассировка / журнал веб-сервисов - PullRequest
6 голосов
/ 08 января 2011

У меня есть набор веб-сервисов, и я хочу добавить слой трассировки.Я не хочу изменять каждый веб-сервис, так как у меня их много.Я хотел бы записывать журнал при каждом входе в веб-службу: имя веб-службы и параметры.

Как лучше всего это сделать?

PS Я использую asp.net и C #.

РЕДАКТИРОВАТЬ: я хочу только обернуть веб-сервисы, так как каждый из них будет иметь журнал (..) в начале.

Ответы [ 7 ]

6 голосов
/ 17 января 2011

Распространенным способом достижения этого является внедрение расширения 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>
1 голос
/ 17 января 2011

EDIT -
Дайте PostSharp попробовать. Это самый простой способ получить эту функциональность. Для потомков я оставлю свое сообщение ниже, но просто проигнорирую его и использую PostSharp.


Если ваши веб-сервисы WCF, вам следует проверить http://msdn.microsoft.com/en-us/magazine/cc163302.aspx.

На каждом этапе работы они предоставляют точки расширения, к которым вы можете подключиться. Вы можете использовать эти точки расширяемости для реализации широкого спектра пользовательских действий, включая проверку сообщений или параметров, ведение журнала сообщений, преобразования сообщений.

Нет сомнений в том, что это путь к услугам WCF. В противном случае, если они являются просто веб-сервисами, вы можете использовать платформу Unity, а также перехват и перехватчик, чтобы сделать то же самое.

1 голос
/ 17 января 2011

Добавьте файл Global Application Class Global.asax в ваш проект и добавьте логику ведения журнала в метод Application_BeginRequest (). Объект sender будет содержать HTTP-запрос и параметры. Вы можете фильтровать только запросы .asmx и регистрировать их.

    protected void Application_BeginRequest(object sender, EventArgs e)
    {

    }
0 голосов
/ 18 января 2011

Я не знаю, если это то, что вы ищете, просто добавьте это в ваш файл конфигурации WCF после ""

Это создаст очень обширный журнал, который вы сможете прочитать с помощью Microsoft Service Trace Viewer

<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>
0 голосов
/ 17 января 2011

Как насчет написания собственного HttpModule ?Это исключило бы необходимость трогать существующий код веб-службы.Вам просто нужно добавить свой модуль в каждый файл web.config.

0 голосов
/ 17 января 2011

Если язык программирования не важен, вы можете поставить Apache 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 голосов
/ 08 января 2011

Я поддерживаю Фреймворк веб-сервисов с открытым исходным кодом , который позволяет вам просто добиться этого, заставляя все веб-сервисы наследовать от базового класса и вести свою собственную регистрацию.* пример базового класса , где я веду распределенный скользящий журнал для всех исключений в 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 Я бы посмотрел на события Global.asax, в частности на событие Application_BeginRequest, которое запускается каждый раз при поступлении нового запроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...