Freigeben über


Schreiben von Telemetriedaten an Ihre Application Insights-Ressource mithilfe von ILogger

Wichtig

Um diese Funktion nutzen zu können, müssen Sie zuerst die Funktion für die Application Insights-Integration aktivieren. Mehr Informationen: Modellgesteuerte Apps und Microsoft Dataverse-Telemetrie mit Application Insights analysieren

Es gibt derzeit keine Unterstützung von ILogger innerhalb einer Plug-In-Profilerstellung-/Debugsitzung des Plugin Registration Tools oder der Power Platform Tools-Erweiterung für Visual Studio.

Wenn Sie Application Insights für Ihre Organisation aktivieren, schreiben alle Plug-Ins, die über die in den SDK für .NET-Assemblys bereitgestellte ILogger-Schnittstelle geschrieben wurden, Telemetriedaten an Ihre Application Insights-Ressource.

Die Dataverse-Plattform erfasst die Dataverse- und modellgesteuerten App-Telemetriedaten und exportiert sie in Ihre Application Insights-Ressource. Es gibt eine gewisse Latenz zwischen dem Zeitpunkt der Erfassung und der Verfügbarkeit für Sie in Application Insights. Da Microsoft diese Telemetriedaten erfasst, müssen Sie keinen Code schreiben, um sie zu aktivieren.

Telemetriedaten, die von Plug-Ins stammen, die die ILogger-Schnittstelle verwenden, unterscheiden sich in zweierlei Hinsicht:

  • Diese Telemetriedaten wird direkt in Ihre Application Insights-Ressource geschrieben und nie an Microsoft gesendet.
    • Die Latenz beim Anzeigen dieser Daten ist geringer.
  • Sie müssen Ihren Plug-In-Code aktualisieren, um die ILogger-Schnittstelle verwenden zu können.

Die Verwendung von ILogger liefert echte Telemetriedaten und soll mit den vorhandenen Plug-In-Ablaufverfolgungsprotokollen zusammenarbeiten, die mithilfe der ITracingService-Schnittstelle geschrieben wurden. In der folgenden Tabelle werden die Funktionen verglichen:

Kriterien ILogger für Application Insights ITracingService-Überwachung für Plug-In-Ablaufverfolgungsprotokolle
Verwendungszweck Erfassen Sie Telemetriedaten im Laufe der Zeit für Analysen und Debugging. Beim Entwickeln und Debuggen von Plug-Ins
Speicherdauer von Daten Entsprechend deines Application Insights-Datenaufbewahrungszeitraums, der standardmäßig 90 Tage beträgt 24 Stunden
Verfügbar Nur für Organisationen, die die Application Insights-Integration abonniert haben. Verfügbar für jede Organisation, wenn die Plug-In-Ablaufverfolgung aktiviert ist.
Datenmenge Jede Protokollnachricht kann einen Zeichenfolgenwert übergeben. Für jede Plug-In-Ausführung können nur 10 KB Text geschrieben werden. Alles Weitere wird abgeschnitten.
Verfügbar in Runtime-Fehlern Nein Verfügbar bei modellgesteuerten App-Client-Fehlern und als Anmerkungen in der Web-API. Mehr Informationen: Mehr Details bei Fehlern hinzufügen

Sie sollten weiterhin ITracingService.Trace verwenden, um bei Bedarf in die Tabelle für das Plug-In-Ablaufverfolgungsprotokoll zu schreiben. Nicht jede Organisation aktiviert Application Insights. Wenn Ihr Plug-In-Code die ILogger-Schnittstelle verwendet und bei der Organisation keine Application Insights-Integration aktiviert ist, wird nichts geschrieben. Daher ist es wichtig, weiterhin die Methode ITracingService-Ablaufverfolgung in Ihren Plug-Ins zu verwenden. Plug-In-Ablaufverfolgungsprotokolle sind nach wie vor eine wichtige Methode zum Erfassen von Daten beim Entwickeln und Debuggen von Plug-Ins, aber sie waren nie dazu gedacht, Telemetriedaten bereitzustellen. Weitere Informationen: Plug-Ins-Ablaufverfolgung und -Protokollierung

Sie sollten ILogger verwenden, da es Telemetrie darüber bereitstellt, was in einem Plug-In passiert. Diese Telemetrie ist in den größeren Datenumfang integriert, der mit der Application Insights-Integration erfasst wird. Die Application Insights-Integration teilt Ihnen mit, wann ein Plug-In ausgeführt wird, wie lange die Ausführung dauert, und ob es externe HTTP-Anforderungen ausführt, aber Microsoft kann keinen Telemetriecode in die Plug-Ins einfügen, die von Ihnen geschrieben werden, um das Verhalten der Plattform zu erweitern.

Wenn Sie ein ISV mit einem Produkt sind, das Plug-Ins enthält, werden Ihre Kunden, die Application Insights aktivieren, es zu schätzen wissen, dass sie sehen können, was in Ihren Plug-Ins vor sich geht, und diese Daten können Ihnen beim Support helfen, sollten einmal Probleme auftreten. Mit ILogger erfasste Daten werden jedoch nur an die Ressource des abonnierenden Kunden gesendet. Sie können die für Ihre eigenen Umgebungen erfassten Daten nur sehen, wenn Sie Application Insights aktiviert haben.

ILogger verwenden

ILogger ist eine allgemeine Schnittstelle zum Erfassen von Protokollinformationen. Die mit den SDK für .NET-Assemblys bereitgestellte Implementierung bietet allgemeine Methoden zur Unterstützung der Einrichtung eines Bereichs und verschiedener Protokollierungsebenen. Es gibt derzeit keine Einstellung, um zu steuern, welche Protokollebenen geschrieben werden. Die Level können innerhalb von Application Insights verwendet werden, um zu filtern, welche Protokolle angezeigt werden sollen.

Im Folgenden sehen Sie ein Beispiel für ein Plug-In, das sowohl ILogger als auch ITracingService.Trace verwendet.

Hinweis

Vergewissern Sie sich, using Microsoft.Xrm.Sdk.PluginTelemetry; einzuschließen. Verwenden Sie nicht using Microsoft.Extensions.Logging;, ansonsten ist die ILogger-Instanz null.

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.PluginTelemetry;
using System;
using System.Net.Http;

namespace ILoggerExample
{
    public class AccountPostOperation : IPlugin
    {
        private string webAddress;
        public AccountPostOperation(string config)
        {

            if (string.IsNullOrEmpty(config))
            {
                webAddress = "https://www.bing.com";
            }
            else
            {
                webAddress = config;
            }
        }


        public void Execute(IServiceProvider serviceProvider)
        {
            ITracingService tracingService =
               (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            ILogger logger = (ILogger)serviceProvider.GetService(typeof(ILogger));

            IPluginExecutionContext context = (IPluginExecutionContext)
               serviceProvider.GetService(typeof(IPluginExecutionContext));

            try
            {
                string startExecMsg = "Start execution of AccountPostOperation";
                logger.LogInformation(startExecMsg);
                tracingService.Trace(startExecMsg);

                Entity entity = (Entity)context.InputParameters["Target"];
                if (entity.LogicalName != "account")
                {

                    string wrongEntityMsg = "Plug-in registered for wrong entity {0}";
                    logger.LogWarning(wrongEntityMsg, entity.LogicalName);
                    tracingService.Trace(wrongEntityMsg, entity.LogicalName);
                    return;
                }

                string activityMsg = "Callback";

                using (logger.BeginScope(activityMsg))
                {
                    tracingService.Trace(activityMsg);

                    string startTaskMsg = "Start Task Creation";
                    logger.LogInformation(startTaskMsg);
                    tracingService.Trace(startTaskMsg);

                    Entity followup = new Entity("task");
                    followup["subject"] = "Send e-mail to the new customer.";
                    followup["description"] =
                        "Follow up with the customer. Check if there are any new issues that need resolution.";
                    followup["scheduledstart"] = DateTime.Now.AddDays(7);
                    followup["scheduledend"] = DateTime.Now.AddDays(7);
                    followup["category"] = context.PrimaryEntityName;

                    // Refer to the account in the task activity.
                    if (context.OutputParameters.Contains("id"))
                    {
                        Guid regardingobjectid = new Guid(context.OutputParameters["id"].ToString());
                        string regardingobjectidType = "account";

                        followup["regardingobjectid"] =
                        new EntityReference(regardingobjectidType, regardingobjectid);

                    }

                    // Obtain the IOrganizationService reference.
                    IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider
                    .GetService(typeof(IOrganizationServiceFactory));

                    IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
                    //Create the task
                    service.Create(followup);

                    string endTaskMsg = "Task creation completed";
                    logger.LogInformation(endTaskMsg);
                    tracingService.Trace(endTaskMsg);
                }

                string outBoundScope = "OutboundCall";

                using (logger.BeginScope(outBoundScope))
                {

                    string outboundStartMsg = "Outbound call started";
                    logger.LogInformation(outboundStartMsg);
                    tracingService.Trace(outboundStartMsg);

                    using (HttpClient client = new HttpClient())
                    {
                        client.Timeout = TimeSpan.FromMilliseconds(15000); //15 seconds
                        client.DefaultRequestHeaders.ConnectionClose = true; //Set KeepAlive to false

                        HttpResponseMessage response = client
                            .GetAsync(webAddress)
                            .GetAwaiter()
                            .GetResult(); //Make sure it is synchronous

                        response.EnsureSuccessStatusCode();

                        string responseText = response.Content
                            .ReadAsStringAsync()
                            .GetAwaiter()
                            .GetResult(); //Make sure it is synchronous

                        string shortResponseText = responseText.Substring(0, 20);

                        logger.LogInformation(shortResponseText);
                        tracingService.Trace(shortResponseText);

                        string outboundEndMsg = "Outbound call ended successfully";

                        logger.LogInformation(outboundEndMsg);
                        tracingService.Trace(outboundEndMsg);

                    }

                }

            }
            catch (Exception e)
            {
                string errMsg = "Plugin failed";
                logger.LogError(e, errMsg);
                tracingService.Trace($"{errMsg}:{e.Message}");
                throw new InvalidPluginExecutionException(e.Message, e);
            }
        }
    }
}

Wenn dieses Plug-In auf einem synchronen PostOperation-Schritt für den Create-Vorgang einer account-Entität registriert ist, können Sie Application Insights-Protokolle verwenden, um die Ausgabe innerhalb weniger Minuten anzuzeigen. Sie können die Kusto-Abfragesprache (KQL) verwenden, um die Ergebnisse abzufragen.

Sie können Elemente für einen einzelnen Vorgang filtern, indem Sie die operation_ParentId verwenden, die die Anforderungs-ID des Antwortheaders darstellt.

Elemente für einen einzelnen Vorgang mithilfe der operation_ParentId filtern .

Der entsprechende Plug-In-Ablaufverfolgungsprotokoll-Eintrag sieht so aus:

Start execution of AccountPostOperation
Callback
Start Task Creation
Task creation completed
Outbound call started
<!doctype html><html
Outbound call ended successfully 

Die mit der BeginScope-Methode festgelegten Informationen sind nicht in den Zeilen sichtbar sind, die in Application Insights zurückgegeben werden. Diese Daten werden innerhalb der customDimensions der Protokolle festgelegt, die in diesem Bereich hinzugefügt werden. Sie können diese Abfrage verwenden, um die Protokolle innerhalb des Bereichs anzuzeigen.

Diese Abfrage beschränkt die Ergebnisse auf die Protokolle, die während des Callback-Umfangs hinzugefügt wurden

Abfrage beschränkt die Ergebnisse auf die Protokolle, die während des Rückruf-Umfangs hinzugefügt wurden.

Und diese Abfrage beschränkt die Ergebnisse auf die Protokolle, die während des OutboundCall-Umfangs hinzugefügt wurden:

Abfrage beschränkt die Ergebnisse auf die Protokolle, die während des OutboundCall-Umfangs hinzugefügt wurden.

Ausnahmen protokollieren

Im unteren Bereich des Plug-In-Codebeispiels oben verwendet der folgende Code LogError, um eine erkannte Ausnahme zu protokollieren, und gibt eine InvalidPluginExecutionException zurück:

catch (Exception e)
{
    string errMsg = "Plugin failed";
    logger.LogError(e, errMsg);
    tracingService.Trace($"{errMsg}:{e.Message}");
    throw new InvalidPluginExecutionException(e.Message, e);
}

Mit dem obigen Plug-In-Code können Sie eine Ausnahme auslösen, indem Sie einen ungültigen Wert an die Konfigurationsdaten der Schrittregistrierung übergeben. In diesem Beispiel lautet der Wert NOT_A_URL.

Fehler durch Eingabe eines ungültigen Konfigurationswerts in der Plug-In-Schrittregistrierung verursachen.

Durch diesen Wert wird der Standardwert (https://www.bing.com) überschrieben und es wird dafür gesorgt, dass der ausgehende Anruf fehlschlägt.

An der Anfrage, die ein Client senden kann, ist nichts auszusetzen:

POST [Organization URI]/api/data/v9.1/accounts HTTP/1.1
Prefer: odata.include-annotations="*"
Authorization: Bearer [REDACTED]
Content-Type: application/json

{
  "name":"Test account"
}

Aufgrund der falschen Registrierung des Plug-In-Schritts gibt die Antwort jedoch den folgenden Fehler mit allen Details zurück, wenn der Prefer: odata.include-annotations="*"-Header verwendet wird:

HTTP/1.1 400 Bad Request
Content-Type: application/json; odata.metadata=minimal
x-ms-service-request-id: 8fd35fd6-5329-4bd5-a1b7-757f91822322
REQ_ID: 8fd35fd6-5329-4bd5-a1b7-757f91822322
OData-Version: 4.0
Date: Sat, 24 Apr 2021 18:24:46 GMT

{
    "error": {
        "code": "0x80040265",
        "message": "An invalid request URI was provided. The request URI must either be an absolute URI or BaseAddress must be set.",
        "@Microsoft.PowerApps.CDS.ErrorDetails.OperationStatus": "0",
        "@Microsoft.PowerApps.CDS.ErrorDetails.SubErrorCode": "-2146233088",
        "@Microsoft.PowerApps.CDS.HelpLink": "http://go.microsoft.com/fwlink/?LinkID=398563&error=Microsoft.Crm.CrmException%3a80040265&client=platform",
        "@Microsoft.PowerApps.CDS.TraceText": "\r\n[ILoggerExample: ILoggerExample.AccountPostOperation]\r\n[2ee952aa-90a4-eb11-b1ac-000d3a8f6891: ILoggerExample.AccountPostOperation: Create of account]\r\n\r\n\t\r\n\tStart execution of AccountPostOperation\r\n\tCallback\r\n\tStart Task Creation\r\n\tTask creation completed\r\n\tOutbound call started\r\n\tPlugin failed:An invalid request URI was provided. The request URI must either be an absolute URI or BaseAddress must be set.\r\n\t\r\n",
        "@Microsoft.PowerApps.CDS.InnerError.Message": "An invalid request URI was provided. The request URI must either be an absolute URI or BaseAddress must be set."
    }
}

Das Plug-In-Ablaufverfolgungsprotokoll enthält diese Ausnahmedaten, einschließlich der ExceptionDetails-Daten.

Exception type: System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]
Message: An invalid request URI was provided. The request URI must either be an absolute URI or BaseAddress must be set.Detail: 
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
  <ActivityId>09bf305c-8272-4fc4-801b-479280cb3069</ActivityId>
  <ErrorCode>-2147220891</ErrorCode>
  <ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic">
    <KeyValuePairOfstringanyType>
      <d2p1:key>OperationStatus</d2p1:key>
      <d2p1:value xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:int">0</d2p1:value>
    </KeyValuePairOfstringanyType>
    <KeyValuePairOfstringanyType>
      <d2p1:key>SubErrorCode</d2p1:key>
      <d2p1:value xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:int">-2146233088</d2p1:value>
    </KeyValuePairOfstringanyType>
  </ErrorDetails>
  <HelpLink i:nil="true" />
  <Message>An invalid request URI was provided. The request URI must either be an absolute URI or BaseAddress must be set.</Message>
  <Timestamp>2021-04-24T18:24:46.4900727Z</Timestamp>
  <ExceptionRetriable>false</ExceptionRetriable>
  <ExceptionSource>PluginExecution</ExceptionSource>
  <InnerFault i:nil="true" />
  <OriginalException>PluginExecution</OriginalException>
  <TraceText>
Start execution of AccountPostOperation
Callback
Start Task Creation
Task creation completed
Outbound call started
Plugin failed:An invalid request URI was provided. The request URI must either be an absolute URI or BaseAddress must be set.
</TraceText>
</OrganizationServiceFault>

Wenn Sie innerhalb von Application Insights Ablaufverfolgungen anzeigen, die dieser Anforderung zugeordnet sind, und deren Bereich wie zuvor gezeigt auf OutboundCall festgelegt ist, sehen Sie, dass der einzige Eintrag darin besteht, dass der ausgehende Anruf gestartet wurde.

Ablaufverfolgungen anzeigen, die dieser Anforderung zugeordnet sind. und deren Bereich auf OutboundCall festgelegt ist.

Wenn Sie Ihre Abfrage innerhalb von Application Insights ändern, sodass exceptions statt traces verwendet wird, sehen Sie drei protokollierte Ausnahmen:

Abfrage ändern, um statt Ablaufverfolgungen Ausnahmen zu verwenden.

Das Beispiel, bei dem cloud_RoleInstance gleich SandboxRoleInstance ist, wurde aufgrund der ILogger-LogError-Methode geschrieben. Die anderen beiden stellen unterschiedliche Orte dar, an denen der Fehler auf dem Server protokolliert wurde.

Hinweis

Die „SandboxRoleInstance“ client_Type ist PC. Dies liegt daran, dass das Plug-In in einer isolierten Sandbox als Client und nicht auf dem Server ausgeführt wird.

Sie können sich auf das von Ihrem Code geschriebene Fehlerprotokoll konzentrieren, indem Sie nach cloud_RoleInstance filtern:

Durch das Filtern nach cloud_RoleInstance auf das von Ihrem Code geschriebene Fehlerprotokoll konzentrieren.

Der formatierte Nachrichtentext wird als Teil der customDimensions erfasst.

Siehe auch

Modellgesteuerte Apps und Microsoft Dataverse-Telemetrie mit Application Insights analysieren
Plug-Ins
Debuggen Sie ein Plug-In
Ablaufverfolgungsprotokolle anzeigen
Ablaufverfolgungsdienst
PluginTraceLog-Tabelle

Hinweis

Können Sie uns Ihre Präferenzen für die Dokumentationssprache mitteilen? Nehmen Sie an einer kurzen Umfrage teil. (Beachten Sie, dass diese Umfrage auf Englisch ist.)

Die Umfrage dauert etwa sieben Minuten. Es werden keine personenbezogenen Daten erhoben. (Datenschutzbestimmungen).