Monitorare le API con Gestione API di Azure, Hub eventi e RunscopeMonitor your APIs with Azure API Management, Event Hubs, and Runscope

Il servizio Gestione API offre molte capacità per migliorare l'elaborazione di richieste HTTP inviate all'API HTTP.The API Management service provides many capabilities to enhance the processing of HTTP requests sent to your HTTP API. L'esistenza di richieste e risposte è tuttavia temporanea.However, the existence of the requests and responses is transient. La richiesta viene effettuata e passa attraverso al servizio Gestione API fino all'API back-end.The request is made and it flows through the API Management service to your backend API. L'API elabora la richiesta e una risposta viene restituita al consumer dell'API.Your API processes the request and a response flows back through to the API consumer. Il servizio Gestione API mantiene alcune statistiche importanti sulle API da visualizzare nel dashboard del portale di Azure, ma eventuali altri dettagli verranno eliminati.The API Management service keeps some important statistics about the APIs for display in the Azure portal dashboard, but beyond that, the details are gone.

L'uso del criterio log-to-eventhub nel servizio Gestione API consente di inviare eventuali dettagli dalla richiesta e dalla risposta a un Hub eventi di Azure.By using the log-to-eventhub policy in the API Management service, you can send any details from the request and response to an Azure Event Hub. È possibile che si voglia generare eventi dai messaggi HTTP inviati alle API per diversi motivi,There are a variety of reasons why you may want to generate events from HTTP messages being sent to your APIs. ad esempio per ottenere audit trail di aggiornamenti, analisi di utilizzo, avvisi relativi alle eccezioni e integrazioni di terze parti.Some examples include audit trail of updates, usage analytics, exception alerting, and third-party integrations.

Questo articolo illustra come acquisire l'intero messaggio di richiesta e risposta HTTP, inviarlo a un hub eventi e quindi inoltrare il messaggio a un servizio d terze parti che fornisce servizi di registrazione HTTP e monitoraggio.This article demonstrates how to capture the entire HTTP request and response message, send it to an Event Hub and then relay that message to a third-party service that provides HTTP logging and monitoring services.

Vantaggi dell'invio dal servizio Gestione APIWhy Send From API Management Service?

È possibile scrivere middleware HTTP in grado di collegarsi ai framework API HTTP per acquisire richieste e risposte HTTP e fornirle ai sistemi di registrazione e monitoraggio.It is possible to write HTTP middleware that can plug into HTTP API frameworks to capture HTTP requests and responses and feed them into logging and monitoring systems. Lo svantaggio di questo approccio consiste nel fatto che il middleware HTTP deve essere integrato nell'API back-end e deve corrispondere alla piattaforma dell'API.The downside to this approach is the HTTP middleware needs to be integrated into the backend API and must match the platform of the API. Se sono disponibili più API, ognuna dovrà distribuire il middleware.If there are multiple APIs, then each one must deploy the middleware. Spesso non è possibile aggiornare le API back-end.Often there are reasons why backend APIs cannot be updated.

L'uso del servizio Gestione API di Azure per l'integrazione con l'infrastruttura di registrazione offre una soluzione centralizzata e indipendente dalla piattaforma,Using the Azure API Management service to integrate with logging infrastructure provides a centralized and platform-independent solution. oltre alla scalabilità, in parte grazie alla capacità di replica geografica di Gestione API di Azure.It is also scalable, in part due to the geo-replication capabilities of Azure API Management.

Vantaggi dell'invio a un Hub eventi di AzureWhy send to an Azure Event Hub?

È legittimo domandarsi quali siano i vantaggi della creazione di un criterio specifico dell'Hub eventi di Azure.It is a reasonable to ask, why create a policy that is specific to Azure Event Hubs? È possibile registrare le richieste in molte posizione diverse.There are many different places where I might want to log my requests. L'invio delle richieste direttamente alla destinazione finaleWhy not just send the requests directly to the final destination? è una delle opzioni disponibili.That is an option. Quando si effettuano richieste di registrazione da un servizio di gestione API, è tuttavia necessario valutare l'impatto della registrazione dei messaggi sulle prestazioni dell'API.However, when making logging requests from an API management service, it is necessary to consider how logging messages impact the performance of the API. Gli incrementi graduali nel carico possono essere gestiti da istanze a disponibilità crescente dei componenti di sistema o sfruttando i vantaggi della replica geografica.Gradual increases in load can be handled by increasing available instances of system components or by taking advantage of geo-replication. I brevi picchi di traffico possono tuttavia provocare un ritardo delle richieste se le richieste all'infrastruttura di registrazione iniziano a rallentare a causa del carico.However, short spikes in traffic can cause requests to be delayed if requests to logging infrastructure start to slow under load.

Hub eventi di Azure è stato progettato per inserire volumi elevati di dati, con una capacità sufficiente per la gestione di un numero di eventi molto più elevato rispetto al numero di richieste HTTP elaborate dalla maggior parte delle API.The Azure Event Hubs is designed to ingress huge volumes of data, with capacity for dealing with a far higher number of events than the number of HTTP requests most APIs process. L'Hub eventi è analogo a un buffer avanzato tra il servizio di gestione API e l'infrastruttura che archivia ed elabora i messaggi.The Event Hub acts as a kind of sophisticated buffer between your API management service and the infrastructure that stores and processes the messages. Ciò assicura che le prestazioni dell'API non saranno danneggiate dall'infrastruttura di registrazione.This ensures that your API performance will not suffer due to the logging infrastructure.

Dopo il passaggio a un hub eventi, i dati verranno resi persistenti e rimarranno in attesa di elaborazione da parte dei consumer dell'Hub eventi.Once the data has been passed to an Event Hub, it is persisted and will wait for Event Hub consumers to process it. Hub eventi non prevede requisiti specifici per la modalità di elaborazione dei dati, si impegna semplicemente nell'assicurare che il messaggio venga recapitato correttamente.The Event Hub does not care how it is processed, it just cares about making sure the message will be successfully delivered.

Gli hub eventi possono effettuare lo streaming di eventi a più gruppi di consumer.Event Hubs has the ability to stream events to multiple consumer groups. Ciò consente l'elaborazione degli eventi da parte di sistemi diversi.This allows events to be processed by different systems. Sarà quindi possibile supportare molti scenari di integrazione senza ritardare ulteriormente l'elaborazione della richiesta API entro il servizio Gestione API, perché è necessario generare solo un evento.This enables supporting many integration scenarios without putting addition delays on the processing of the API request within the API Management service as only one event needs to be generated.

Criterio per l'invio di messaggi applicazione/HTTPA policy to send application/http messages

Un hub eventi accetta i dati evento sotto forma di semplice stringa.An Event Hub accepts event data as a simple string. I contenuti della stringa possono essere definiti dall'utente.The contents of that string are up to you. Per potere creare un pacchetto di una richiesta HTTP e inviarlo all'Hub eventi, è necessario formattare la stringa con le informazioni di richiesta o di risposta.To be able to package up an HTTP request and send it off to Event Hubs, we need to format the string with the request or response information. In situazioni come queste, se è disponibile una formattazione esistente che può essere usata, potrebbe non essere necessario scrivere codice di analisi specifico.In situations like this, if there is an existing format we can reuse, then we may not have to write our own parsing code. È stata inizialmente valutata la possibilità di usare HAR per l'invio di richieste e risposte HTTP,Initially I considered using the HAR for sending HTTP requests and responses. ma questo formato è ottimizzato per l'archiviazione di una sequenza di richieste HTTP in un formato basato su JSON.However, this format is optimized for storing a sequence of HTTP requests in a JSON-based format. Contiene alcuni elementi obbligatori che aggiungono una complessità superflua per lo scenario del passaggio del messaggio HTTP in rete.It contained a number of mandatory elements that added unnecessary complexity for the scenario of passing the HTTP message over the wire.

Un'opzione alternativa consiste nell'usare il tipo di dati multimediali application/http , come illustrato nella specifica HTTP RFC 7230.An alternative option was to use the application/http media type as described in the HTTP specification RFC 7230. Questo tipo di dati multimediali usa esattamente lo stesso formato adottato per inviare effettivamente i messaggi HTTP in rete, ma l'intero messaggio può essere inserito nel corpo di un'altra richiesta HTTP.This media type uses the exact same format that is used to actually send HTTP messages over the wire, but the entire message can be put in the body of another HTTP request. In questo caso il corpo verrà usato come messaggio da inviare all'Hub eventi.In our case, we are just going to use the body as our message to send to Event Hubs. Il parser disponibile nelle librerie Microsoft ASP.NET Web API 2.2 Client può essere usato per analizzare questo formato e convertirlo negli oggetti HttpRequestMessage e HttpResponseMessage nativi.Conveniently, there is a parser that exists in Microsoft ASP.NET Web API 2.2 Client libraries that can parse this format and convert it into the native HttpRequestMessage and HttpResponseMessage objects.

Per potere creare questo messaggio, è necessario sfruttare le espressioni di criteri basate su C# disponibili in Gestione API di Azure.To be able to create this message, we need to take advantage of C# based Policy expressions in Azure API Management. Ecco il criterio che invia un messaggio di richiesta HTTP all'Hub eventi di Azure.Here is the policy, which sends an HTTP request message to Azure Event Hubs.

<log-to-eventhub logger-id="conferencelogger" partition-id="0">
@{
   var requestLine = string.Format("{0} {1} HTTP/1.1\r\n",
                                               context.Request.Method,
                                               context.Request.Url.Path + context.Request.Url.QueryString);

   var body = context.Request.Body?.As<string>(true);
   if (body != null && body.Length > 1024)
   {
       body = body.Substring(0, 1024);
   }

   var headers = context.Request.Headers
                          .Where(h => h.Key != "Authorization" && h.Key != "Ocp-Apim-Subscription-Key")
                          .Select(h => string.Format("{0}: {1}", h.Key, String.Join(", ", h.Value)))
                          .ToArray<string>();

   var headerString = (headers.Any()) ? string.Join("\r\n", headers) + "\r\n" : string.Empty;

   return "request:"   + context.Variables["message-id"] + "\n"
                       + requestLine + headerString + "\r\n" + body;
}
</log-to-eventhub>

Dichiarazione di criteriPolicy declaration

È necessario evidenziare alcuni aspetti di questa espressione di criteri.There a few particular things worth mentioning about this policy expression. Il criterio log-to-eventhub ha un attributo denominato logger-id che fa riferimento al nome del logger creato nel servizio Gestione API.The log-to-eventhub policy has an attribute called logger-id, which refers to the name of logger that has been created within the API Management service. I dettagli relativi alla configurazione di un logger dell'Hub eventi nel servizio Gestione API sono disponibili nel documento Come registrare eventi nell'Hub eventi di Azure in Gestione API di Azure.The details of how to set up an Event Hub logger in the API Management service can be found in the document How to log events to Azure Event Hubs in Azure API Management. Il secondo attributo è un parametro opzionale che indica all'Hub eventi la partizione in cui archiviare il messaggio.The second attribute is an optional parameter that instructs Event Hubs which partition to store the message in. Hub eventi usa le partizioni per abilitare la scalabilità e richiede almeno due partizioni.Event Hubs uses partitions to enable scalability and require a minimum of two. Il recapito ordinato dei messaggi è garantito solo entro una partizione.The ordered delivery of messages is only guaranteed within a partition. Se non si indica all'Hub eventi la partizione in cui inserire il messaggio, verrà usato un algoritmo round-robin per distribuire il carico.If we do not instruct Event Hub in which partition to place the message, it uses a round-robin algorithm to distribute the load. È tuttavia possibile che ciò provochi l'elaborazione non ordinata di alcuni messaggi.However, that may cause some of our messages to be processed out of order.

PartitionsPartitions

Per assicurarsi che i messaggi vengano recapitati ai consumer in base all'ordine stabilito e sfruttare i vantaggi della capacità di distribuzione del carico delle partizioni, è possibile scegliere di inviare messaggi di richiesta HTTP a una partizione e messaggi di risposta HTTP a una seconda partizione.To ensure our messages are delivered to consumers in order and take advantage of the load distribution capability of partitions, I chose to send HTTP request messages to one partition and HTTP response messages to a second partition. In questo modo si assicura una distribuzione uniforme del carico e sarà possibile garantire che tutte le richieste e le risposte vengano utilizzate nell'ordine stabilito.This ensures an even load distribution and we can guarantee that all requests will be consumed in order and all responses are consumed in order. È possibile che una risposta venga utilizzata prima della risposta corrispondente, ma questo non costituisce un problema, perché è disponibile un meccanismo diverso per la correlazione delle richieste alle risposte e si sa che le richieste precedono sempre le risposte.It is possible for a response to be consumed before the corresponding request, but as that is not a problem as we have a different mechanism for correlating requests to responses and we know that requests always come before responses.

Payload HTTPHTTP payloads

Dopo avere compilato requestLine, verificare se il corpo della richiesta deve essere troncato.After building the requestLine, we check to see if the request body should be truncated. Il corpo della richiesta viene troncato solo a 1024.The request body is truncated to only 1024. È possibile aumentare questo valore, ma i singoli messaggi dell'Hub eventi sono limitati a 256 KB, quindi è probabile che alcuni corpi di messaggio HTTP non rientrino in un singolo messaggio.This could be increased, however individual Event Hub messages are limited to 256 KB, so it is likely that some HTTP message bodies will not fit in a single message. Durante la registrazione e l'analisi, è possibile ottenere una quantità significativa di informazioni semplicemente dalla riga e dalle intestazioni della richiesta HTTP.When doing logging and analytics a significant amount of information can be derived from just the HTTP request line and headers. Molte richieste API restituiscono inoltre corpi piccoli, quindi la perdita del valore di informazioni derivante dal troncamento di corpi di grandi dimensioni è abbastanza ridotta rispetto alla riduzione dei costi di trasferimento, elaborazione e archiviazione per la conservazione di tutti i contenuti del corpo.Also, many APIs request only return small bodies and so the loss of information value by truncating large bodies is fairly minimal in comparison to the reduction in transfer, processing, and storage costs to keep all body contents. È infine necessario notare, in merito all'elaborazione del corpo, che occorre passare true al metodo As() poiché si stanno leggendo i contenuti del corpo, ma è anche necessario che l'API back-end sia in grado di leggere il corpo.One final note about processing the body is that we need to pass true to the As() method because we are reading the body contents, but was also wanted the backend API to be able to read the body. Se si passa true a questo metodo, il corpo verrà sottoposto a buffering, in modo che sia possibile leggerlo una seconda volta.By passing true to this method, we cause the body to be buffered so that it can be read a second time. È importante tenere in considerazione questo aspetto se si usa un'API che carica file di grandi dimensioni o usa polling di lunga durata.This is important to be aware of if you have an API that does uploading of large files or uses long polling. In questi casi è consigliabile evitare completamente la lettura del corpo.In these cases, it would be best to avoid reading the body at all.

Intestazioni HTTPHTTP headers

Le intestazioni HTTP possono essere trasferite nel formato del messaggio sotto forma di semplice coppia chiave/valore.HTTP Headers can be transferred over into the message format in a simple key/value pair format. Alcuni campi che richiedono una sicurezza specifica sono stati eliminati per evitare la diffusione non necessaria delle informazioni relative alle credenziali.We have chosen to strip out certain security sensitive fields, to avoid unnecessarily leaking credential information. È poco probabile che le chiavi API e altre credenziali vengano usate per finalità analitiche.It is unlikely that API keys and other credentials would be used for analytics purposes. Se si vuole effettuare un'analisi dell'utente e del prodotto specifico usato, sarà possibile ottenere queste informazioni dall'oggetto context e aggiungerle al messaggio.If we wish to do analysis on the user and the particular product they are using, then we could get that from the context object and add that to the message.

Metadati del messaggioMessage Metadata

Durante la creazione del messaggio completo da inviare all'hub eventi, la prima riga non fa effettivamente parte del messaggio application/http .When building the complete message to send to the event hub, the first line is not actually part of the application/http message. La prima riga include metadati aggiuntivi che indicano se il messaggio è un messaggio di richiesta o di risposta e l'ID del messaggio, che viene usato per correlare le richieste e l risposte.The first line is additional metadata consisting of whether the message is a request or response message and a message ID, which is used to correlate requests to responses. L'ID del messaggio viene creato mediante un altro criterio, analogo al seguente:The message ID is created by using another policy that looks like this:

<set-variable name="message-id" value="@(Guid.NewGuid())" />

È anche possibile creare il messaggio di richiesta, archiviarlo in una variabile fino alla restituzione della risposta e quindi inviare la richiesta e la risposta come singolo messaggio,We could have created the request message, stored that in a variable until the response was returned and then sent the request and response as a single message. ma l'invio indipendente di richiesta e risposta e l'uso di un ID del messaggio per correlarle consente di ottenere una maggiore flessibilità a livello di dimensioni del messaggio, di sfruttare i vantaggi offerti dalle partizioni multiple e di mantenere al tempo stesso l'ordine dei messaggi, oltre a visualizzare più rapidamente la richiesta nel dashboard di registrazione.However, by sending the request and response independently and using a message id to correlate the two, we get a bit more flexibility in the message size, the ability to take advantage of multiple partitions whilst maintaining message order and the request will appear in our logging dashboard sooner. In alcuni scenari è anche possibile che non venga mai inviata all'hub eventi alcuna risposta valida, probabilmente a causa di un errore della richiesta nel servizio Gestione API, ma viene comunque mantenuto un record della richiesta.There also may be some scenarios where a valid response is never sent to the event hub, possibly due to a fatal request error in the API Management service, but we still have a record of the request.

Il criterio per l'invio del messaggio di risposta HTTP è simile alla richiesta, quindi la configurazione completa del criterio sarà analoga alla seguente:The policy to send the response HTTP message looks similar to the request and so the complete policy configuration looks like this:

<policies>
  <inbound>
      <set-variable name="message-id" value="@(Guid.NewGuid())" />
      <log-to-eventhub logger-id="conferencelogger" partition-id="0">
      @{
          var requestLine = string.Format("{0} {1} HTTP/1.1\r\n",
                                                      context.Request.Method,
                                                      context.Request.Url.Path + context.Request.Url.QueryString);

          var body = context.Request.Body?.As<string>(true);
          if (body != null && body.Length > 1024)
          {
              body = body.Substring(0, 1024);
          }

          var headers = context.Request.Headers
                               .Where(h => h.Key != "Authorization" && h.Key != "Ocp-Apim-Subscription-Key")
                               .Select(h => string.Format("{0}: {1}", h.Key, String.Join(", ", h.Value)))
                               .ToArray<string>();

          var headerString = (headers.Any()) ? string.Join("\r\n", headers) + "\r\n" : string.Empty;

          return "request:"   + context.Variables["message-id"] + "\n"
                              + requestLine + headerString + "\r\n" + body;
      }
  </log-to-eventhub>
  </inbound>
  <backend>
      <forward-request follow-redirects="true" />
  </backend>
  <outbound>
      <log-to-eventhub logger-id="conferencelogger" partition-id="1">
      @{
          var statusLine = string.Format("HTTP/1.1 {0} {1}\r\n",
                                              context.Response.StatusCode,
                                              context.Response.StatusReason);

          var body = context.Response.Body?.As<string>(true);
          if (body != null && body.Length > 1024)
          {
              body = body.Substring(0, 1024);
          }

          var headers = context.Response.Headers
                                          .Select(h => string.Format("{0}: {1}", h.Key, String.Join(", ", h.Value)))
                                          .ToArray<string>();

          var headerString = (headers.Any()) ? string.Join("\r\n", headers) + "\r\n" : string.Empty;

          return "response:"  + context.Variables["message-id"] + "\n"
                              + statusLine + headerString + "\r\n" + body;
     }
  </log-to-eventhub>
  </outbound>
</policies>

Il criterio set-variable crea un valore accessibile dal criterio log-to-eventhub nella sezione <inbound> e nella sezione <outbound>.The set-variable policy creates a value that is accessible by both the log-to-eventhub policy in the <inbound> section and the <outbound> section.

Ricezione di eventi dall'Hub eventiReceiving events from Event Hubs

Gli eventi dall'Hub eventi di Azure vengono ricevuti mediante il protocollo AMQP.Events from Azure Event Hub are received using the AMQP protocol. Il team del bus di servizio Microsoft ha reso disponibili le librerie client per semplificare l'utilizzo degli eventi.The Microsoft Service Bus team have made client libraries available to make the consuming events easier. Sono supportati due approcci diversi, ovvero la modalità consumer diretto e l'uso della classe EventProcessorHost.There are two different approaches supported, one is being a Direct Consumer and the other is using the EventProcessorHost class. Gli esempi relativi a questi due approcci sono disponibili nella Guida alla programmazione di Hub eventi.Examples of these two approaches can be found in the Event Hubs Programming Guide. In breve, Direct Consumer offre il controllo completo e EventProcessorHost esegue alcune operazioni di base ma include alcune ipotesi in merito al modo in cui gli eventi vengono elaborati.The short version of the differences is, Direct Consumer gives you complete control and the EventProcessorHost does some of the plumbing work for you but makes certain assumptions about how you process those events.

EventProcessorHostEventProcessorHost

Per semplificare, in questo esempio verrà usato l'approccio EventProcessorHost, anche se è possibile che non sia ottimale per questo scenario specifico.In this sample, we use the EventProcessorHost for simplicity, however it may not the best choice for this particular scenario. EventProcessorHost esegue le operazioni necessarie per gestire automaticamente eventuali errori di threading relativi a una classe specifica del processore di eventi.EventProcessorHost does the hard work of making sure you don't have to worry about threading issues within a particular event processor class. In questo scenario, tuttavia, si converte semplicemente il messaggio in un altro formato e lo si passa a un altro servizio mediante un metodo asincrono.However, in our scenario, we are simply converting the message to another format and passing it along to another service using an async method. Non è necessario aggiornare lo stato condiviso e quindi non si rischia che si verifichino problemi di threading.There is no need for updating shared state and therefore no risk of threading issues. Nella maggior parte degli scenari la scelta migliore è probabilmente costituita da EventProcessorHost , che è sicuramente l'opzione più semplice.For most scenarios, EventProcessorHost is probably the best choice and it is certainly the easier option.

IEventProcessorIEventProcessor

Il concetto centrale dell'uso di EventProcessorHost consiste nel creare un'implementazione dell'interfaccia IEventProcessor, che include il metodo ProcessEventAsync.The central concept when using EventProcessorHost is to create an implementation of the IEventProcessor interface, which contains the method ProcessEventAsync. Gli elementi fondamentali del metodo sono illustrati di seguito:The essence of that method is shown here:

async Task IEventProcessor.ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
{

   foreach (EventData eventData in messages)
   {
       _Logger.LogInfo(string.Format("Event received from partition: {0} - {1}", context.Lease.PartitionId,eventData.PartitionKey));

       try
       {
           var httpMessage = HttpMessage.Parse(eventData.GetBodyStream());
           await _MessageContentProcessor.ProcessHttpMessage(httpMessage);
       }
       catch (Exception ex)
       {
           _Logger.LogError(ex.Message);
       }
   }
    ... checkpointing code snipped ...
}

Un elenco di oggetti EventData viene passato al metodo e viene eseguita l'iterazione dell'elenco.A list of EventData objects are passed into the method and we iterate over that list. I byte di ogni metodo vengono analizzati in un oggetto HttpMessage e questo oggetto viene passato a un'istanza di IHttpMessageProcessor.The bytes of each method are parsed into an HttpMessage object and that object is passed to an instance of IHttpMessageProcessor.

HttpMessageHttpMessage

L'istanza HttpMessage contiene tre parti di dati:The HttpMessage instance contains three pieces of data:

public class HttpMessage
{
   public Guid MessageId { get; set; }
   public bool IsRequest { get; set; }
   public HttpRequestMessage HttpRequestMessage { get; set; }
   public HttpResponseMessage HttpResponseMessage { get; set; }

... parsing code snipped ...

}

L'istanza HttpMessage contiene un GUID MessageId che consente di connettere la richiesta HTTP alla risposta HTTP corrispondente e un valore booleano che indica se l'oggetto contiene un'istanza di HttpRequestMessage e HttpResponseMessage.The HttpMessage instance contains a MessageId GUID that allows us to connect the HTTP request to the corresponding HTTP response and a boolean value that identifies if the object contains an instance of a HttpRequestMessage and HttpResponseMessage. Usando le classi HTTP predefinite da System.Net.Http, è possibile sfruttare i vantaggi del codice di analisi application/http incluso in System.Net.Http.Formatting.By using the built-in HTTP classes from System.Net.Http, I was able to take advantage of the application/http parsing code that is included in System.Net.Http.Formatting.

IHttpMessageProcessorIHttpMessageProcessor

L'istanza HttpMessage viene quindi inoltrata all'implementazione di IHttpMessageProcessor, che è un'interfaccia creata per disaccoppiare la ricezione e l'interpretazione dell'evento dall'Hub eventi di Azure e l'effettiva elaborazione dell'evento.The HttpMessage instance is then forwarded to implementation of IHttpMessageProcessor, which is an interface I created to decouple the receiving and interpretation of the event from Azure Event Hub and the actual processing of it.

Inoltro del messaggio HTTPForwarding the HTTP message

Per questo esempio è possibile provare a effettuare il push della richiesta HTTP in Runscope.For this sample, I decided it would be interesting to push the HTTP Request over to Runscope. Runscope è un servizio basato sul cloud specializzato nel debug, nella registrazione e nel monitoraggio HTTP.Runscope is a cloud-based service that specializes in HTTP debugging, logging and monitoring. È disponibile un livello gratuito, quindi è possibile provare a usarlo per visualizzare il passaggio in tempo reale delle richieste HTTP nel servizio Gestione API.They have a free tier, so it is easy to try and it allows us to see the HTTP requests in real time flowing through our API Management service.

L'implementazione IHttpMessageProcessor ha un aspetto analogo al seguente,The IHttpMessageProcessor implementation looks like this,

public class RunscopeHttpMessageProcessor : IHttpMessageProcessor
{
   private HttpClient _HttpClient;
   private ILogger _Logger;
   private string _BucketKey;
   public RunscopeHttpMessageProcessor(HttpClient httpClient, ILogger logger)
   {
       _HttpClient = httpClient;
       var key = Environment.GetEnvironmentVariable("APIMEVENTS-RUNSCOPE-KEY", EnvironmentVariableTarget.User);
       _HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", key);
       _HttpClient.BaseAddress = new Uri("https://api.runscope.com");
       _BucketKey = Environment.GetEnvironmentVariable("APIMEVENTS-RUNSCOPE-BUCKET", EnvironmentVariableTarget.User);
       _Logger = logger;
   }

   public async Task ProcessHttpMessage(HttpMessage message)
   {
       var runscopeMessage = new RunscopeMessage()
       {
           UniqueIdentifier = message.MessageId
       };

       if (message.IsRequest)
       {
           _Logger.LogInfo("Sending HTTP request " + message.MessageId.ToString());
           runscopeMessage.Request = await RunscopeRequest.CreateFromAsync(message.HttpRequestMessage);
       }
       else
       {
           _Logger.LogInfo("Sending HTTP response " + message.MessageId.ToString());
           runscopeMessage.Response = await RunscopeResponse.CreateFromAsync(message.HttpResponseMessage);
       }

       var messagesLink = new MessagesLink() { Method = HttpMethod.Post };
       messagesLink.BucketKey = _BucketKey;
       messagesLink.RunscopeMessage = runscopeMessage;
       var runscopeResponse = await _HttpClient.SendAsync(messagesLink.CreateRequest());
       _Logger.LogDebug("Request sent to Runscope");
   }
}

È stato possibile sfruttare una libreria client esistente per Runscope che semplifica il push delle istanze HttpRequestMessage e HttpResponseMessage nel servizio.I was able to take advantage of an existing client library for Runscope that makes it easy to push HttpRequestMessage and HttpResponseMessage instances up into their service. Per accedere all'API Runscope, sono necessari un account e una chiave API.In order to access the Runscope API, you need an account and an API Key. Le istruzioni per ottenere una chiave API sono disponibili nello screencast relativo alla creazione di applicazioni per l'accesso all'API Runscope .Instructions for getting an API key can be found in the Creating Applications to Access Runscope API screencast.

Esempio completoComplete sample

Il codice sorgente e i test per l'esempio sono disponibili su GitHub.The source code and tests for the sample are on GitHub. Per eseguire l'esempio, è necessario disporre di un servizio Gestione API, un hub eventi connesso e un account di archiviazione.You need an API Management Service, a connected Event Hub, and a Storage Account to run the sample for yourself.

L'esempio è costituito da una semplice applicazione console che rimane in attesa di eventi provenienti dall'Hub eventi, quindi li converte in oggetti HttpRequestMessage e HttpResponseMessage e li inoltra all'API Runscope.The sample is just a simple Console application that listens for events coming from Event Hub, converts them into a HttpRequestMessage and HttpResponseMessage objects and then forwards them on to the Runscope API.

L'immagine animata seguente illustra l'effettuazione di una richiesta a un'API nel portale per sviluppatori, la ricezione, l'elaborazione e l'inoltro del messaggio nell'applicazione console e quindi la visualizzazione della richiesta e della risposta in Runscope Traffic Inspector.In the following animated image, you can see a request being made to an API in the Developer Portal, the Console application showing the message being received, processed, and forwarded and then the request and response showing up in the Runscope Traffic inspector.

Illustrazione dell'inoltro di una richiesta a Runscope

SummarySummary

Il servizio Gestione API di Azure è la posizione ideale per acquisire il traffico HTTP verso e dalle API.Azure API Management service provides an ideal place to capture the HTTP traffic traveling to and from your APIs. Hub eventi di Azure è una soluzione a scalabilità elevata e costi ridotti per l'acquisizione e l'inserimento del traffico in sistemi di elaborazione secondari per operazioni di registrazione e monitoraggio e per altre analisi avanzate.Azure Event Hubs is a highly scalable, low-cost solution for capturing that traffic and feeding it into secondary processing systems for logging, monitoring, and other sophisticated analytics. La connessione a sistemi di monitoraggio del traffico di terze parti come Runscope è semplice quanto scrivere qualche decina di righe di codice.Connecting to third-party traffic monitoring systems like Runscope is as simple as a few dozen lines of code.

Passaggi successiviNext steps