Egyéni műveletek nyomon követése az Application Elemzések .NET SDK-val

Az alkalmazás Elemzések SDK-k automatikusan nyomon követik a függő szolgáltatásokhoz érkező HTTP-kéréseket és hívásokat, például HTTP-kéréseket és SQL-lekérdezéseket. A kérelmek és függőségek nyomon követése és korrelációja lehetővé teszi az alkalmazás válaszkészségének és megbízhatóságának áttekintését az alkalmazás összes olyan mikroszolgáltatásában, amely kombinálja ezt az alkalmazást.

Vannak olyan alkalmazásminták, amelyek általánosan nem támogatottak. Az ilyen minták megfelelő monitorozása manuális kódrendszerezést igényel. Ez a cikk néhány olyan mintát mutat be, amelyek manuális rendszerezést igényelhetnek, például egyéni üzenetsor-feldolgozást és hosszú ideig futó háttérfeladatok futtatását.

Ez a cikk útmutatást nyújt az egyéni műveletek nyomon követéséhez az Alkalmazás Elemzések SDK-val. Ez a dokumentáció a következő célokra vonatkozik:

  • Alkalmazás Elemzések a .NET (más néven Alap SDK) 2.4-es verziójához.
  • Alkalmazás Elemzések webalkalmazásokhoz (ASP.NET) 2.4-es vagy újabb verzióhoz.
  • Alkalmazás Elemzések ASP.NET Core 2.1-es verziójához.

Feljegyzés

Az alábbi dokumentáció az Alkalmazás Elemzések klasszikus API-ra támaszkodik. Az Alkalmazás Elemzések hosszú távú terve az Adatok gyűjtése Az OpenTelemetria használatával. További információ: Az Azure Monitor OpenTelemetria engedélyezése .NET-, Node.js-, Python- és Java-alkalmazásokhoz.

Áttekintés

A művelet egy alkalmazás által futtatott logikai munkadarab. Neve, kezdési időpontja, időtartama, eredménye és a végrehajtás környezete, például felhasználónév, tulajdonságok és eredmény. Ha az A műveletet a B művelet kezdeményezte, akkor a B művelet az A szülőjeként van beállítva. Egy műveletnek csak egy szülője lehet, de számos gyermekművelettel rendelkezhet. A műveletekről és a telemetriai korrelációról további információt az Alkalmazás Elemzések telemetriai korrelációban talál.

Az Application Elemzések .NET SDK-ban a műveletet az OperationTelemetry absztrakt osztály és annak leszármazottai, a RequestTelemetry és a DependencyTelemetry írja le.

Bejövő műveletek nyomon követése

Az Alkalmazás Elemzések webes SDK automatikusan http-kéréseket gyűjt az IIS-folyamatban futó ASP.NET alkalmazásokhoz és az összes ASP.NET Core-alkalmazáshoz. Más platformokhoz és keretrendszerekhez is léteznek közösség által támogatott megoldások. Ha az alkalmazást egyik standard vagy közösség által támogatott megoldás sem támogatja, manuálisan is rendszerezheti.

Egy másik példa, amely egyéni nyomon követést igényel, az a feldolgozó, amely elemeket fogad az üzenetsorból. Egyes üzenetsorok esetében az üzenetsorhoz üzenet hozzáadására irányuló hívás függőségként van nyomon követve. A rendszer nem gyűjti automatikusan az üzenetfeldolgozást leíró magas szintű műveletet.

Lássuk, hogyan követhetők nyomon az ilyen műveletek.

Magas szinten a feladat az ismert tulajdonságok létrehozása RequestTelemetry és beállítása. A művelet befejezése után nyomon követheti a telemetriát. Az alábbi példa ezt a feladatot mutatja be.

HTTP-kérés az Owin saját üzemeltetésű alkalmazásában

Ebben a példában a nyomkövetési környezet propagálása a http protokollnak megfelelően történik a korrelációhoz. Az itt leírt fejléceket várhatóan megkapja.

public class ApplicationInsightsMiddleware : OwinMiddleware
{
    // You may create a new TelemetryConfiguration instance, reuse one you already have,
    // or fetch the instance created by Application Insights SDK.
    private readonly TelemetryConfiguration telemetryConfiguration = TelemetryConfiguration.CreateDefault();
    private readonly TelemetryClient telemetryClient = new TelemetryClient(telemetryConfiguration);
    
    public ApplicationInsightsMiddleware(OwinMiddleware next) : base(next) {}

    public override async Task Invoke(IOwinContext context)
    {
        // Let's create and start RequestTelemetry.
        var requestTelemetry = new RequestTelemetry
        {
            Name = $"{context.Request.Method} {context.Request.Uri.GetLeftPart(UriPartial.Path)}"
        };

        // If there is a Request-Id received from the upstream service, set the telemetry context accordingly.
        if (context.Request.Headers.ContainsKey("Request-Id"))
        {
            var requestId = context.Request.Headers.Get("Request-Id");
            // Get the operation ID from the Request-Id (if you follow the HTTP Protocol for Correlation).
            requestTelemetry.Context.Operation.Id = GetOperationId(requestId);
            requestTelemetry.Context.Operation.ParentId = requestId;
        }

        // StartOperation is a helper method that allows correlation of 
        // current operations with nested operations/telemetry
        // and initializes start time and duration on telemetry items.
        var operation = telemetryClient.StartOperation(requestTelemetry);

        // Process the request.
        try
        {
            await Next.Invoke(context);
        }
        catch (Exception e)
        {
            requestTelemetry.Success = false;
            requestTelemetry.ResponseCode;
            telemetryClient.TrackException(e);
            throw;
        }
        finally
        {
            // Update status code and success as appropriate.
            if (context.Response != null)
            {
                requestTelemetry.ResponseCode = context.Response.StatusCode.ToString();
                requestTelemetry.Success = context.Response.StatusCode >= 200 && context.Response.StatusCode <= 299;
            }
            else
            {
                requestTelemetry.Success = false;
            }

            // Now it's time to stop the operation (and track telemetry).
            telemetryClient.StopOperation(operation);
        }
    }
    
    public static string GetOperationId(string id)
    {
        // Returns the root ID from the '|' to the first '.' if any.
        int rootEnd = id.IndexOf('.');
        if (rootEnd < 0)
            rootEnd = id.Length;

        int rootStart = id[0] == '|' ? 1 : 0;
        return id.Substring(rootStart, rootEnd - rootStart);
    }
}

A http protokoll a korrelációhoz is deklarálja a fejlécet Correlation-Context . Itt hiányzik az egyszerűség kedvéért.

Üzenetsor-kialakítás

A W3C trace context és a HTTP Protocol for Correlation pass korrelációs adatokat ad át a HTTP-kérésekkel, de minden üzenetsor-protokollnak meg kell határoznia, hogy a rendszer hogyan továbbítja ugyanazokat a részleteket az üzenetsor-üzenetben. Egyes üzenetsor-protokollok, például az AMQP lehetővé teszik további metaadatok átadását. Más protokollok, például az Azure Storage Queue megkövetelik, hogy a környezet az üzenet hasznos adataiba legyen kódolva.

Feljegyzés

Az üzenetsorok még nem támogatják az összetevők közötti nyomkövetést.

A HTTP használatával, ha a gyártó és a fogyasztó telemetriát küld különböző alkalmazás-Elemzések-erőforrásokba, a tranzakciódiagnosztikai élmény és az Alkalmazástérkép a tranzakciókat és a végpontok közötti leképezést jeleníti meg. Üzenetsorok esetén ez a képesség még nem támogatott.

Service Bus-üzenetsor

A nyomkövetési információkért lásd : Elosztott nyomkövetés és korreláció az Azure Service Bus-üzenetkezelésen keresztül.

Azure Storage-üzenetsor

Az alábbi példa bemutatja, hogyan követheti nyomon az Azure Storage-üzenetsor műveleteit, és hogyan korrelálhatja a telemetriát a gyártó, a fogyasztó és az Azure Storage között.

A Storage-üzenetsor http API-val rendelkezik. Az üzenetsorra irányuló összes hívást az alkalmazás Elemzések HTTP-kérelmek függőséggyűjtője követi nyomon. Alapértelmezés szerint ASP.NET és ASP.NET Core-alkalmazásokban van konfigurálva. Más típusú alkalmazásokkal kapcsolatban tekintse meg a konzolalkalmazások dokumentációját.

Érdemes lehet korrelálni az alkalmazás Elemzések műveletazonosítóját a Storage-kérelem azonosítójával. A Storage-kérelemügyfél és a kiszolgálókérés azonosítójának beállításáról és lekéréséről további információt az Azure Storage monitorozása, diagnosztizálása és hibaelhárítása című témakörben talál.

Enqueue

Mivel a tárolási üzenetsorok támogatják a HTTP API-t, az alkalmazás Elemzések automatikusan nyomon követi az üzenetsor összes műveletét. Sok esetben ennek a rendszerezésnek elégnek kell lennie. Ha a fogyasztói oldalon lévő nyomkövetéseket a gyártói nyomkövetésekkel szeretné korrelálni, a korreláció http protokolljában használthoz hasonlóan át kell adnia néhány korrelációs összefüggést.

Ez a példa bemutatja, hogyan követheti nyomon a Enqueue műveletet. A következőket teheti:

  • Újrapróbálkozási újrapróbálkozások korrelálása (ha van ilyen):: Mindegyiknek van egy közös szülője, amely a Enqueue művelet. Ellenkező esetben a bejövő kérés gyermekeiként lesznek nyomon követve. Ha több logikai kérés is van az üzenetsorhoz, előfordulhat, hogy nehéz megtalálni, hogy melyik hívás eredményezett újrapróbálkozásokat.
  • Tárnaplók korrelálása (ha és ha szükséges): Az alkalmazás Elemzések telemetriával vannak korrelálva.

A Enqueue művelet egy szülőművelet gyermeke. Ilyen például egy bejövő HTTP-kérés. A HTTP-függőségi hívás a művelet gyermeke Enqueue és a bejövő kérés unokája.

public async Task Enqueue(CloudQueue queue, string message)
{
    var operation = telemetryClient.StartOperation<DependencyTelemetry>("enqueue " + queue.Name);
    operation.Telemetry.Type = "Azure queue";
    operation.Telemetry.Data = "Enqueue " + queue.Name;

    // MessagePayload represents your custom message and also serializes correlation identifiers into payload.
    // For example, if you choose to pass payload serialized to JSON, it might look like
    // {'RootId' : 'some-id', 'ParentId' : '|some-id.1.2.3.', 'message' : 'your message to process'}
    var jsonPayload = JsonConvert.SerializeObject(new MessagePayload
    {
        RootId = operation.Telemetry.Context.Operation.Id,
        ParentId = operation.Telemetry.Id,
        Payload = message
    });
    
    CloudQueueMessage queueMessage = new CloudQueueMessage(jsonPayload);

    // Add operation.Telemetry.Id to the OperationContext to correlate Storage logs and Application Insights telemetry.
    OperationContext context = new OperationContext { ClientRequestID = operation.Telemetry.Id};

    try
    {
        await queue.AddMessageAsync(queueMessage, null, null, new QueueRequestOptions(), context);
    }
    catch (StorageException e)
    {
        operation.Telemetry.Properties.Add("AzureServiceRequestID", e.RequestInformation.ServiceRequestID);
        operation.Telemetry.Success = false;
        operation.Telemetry.ResultCode = e.RequestInformation.HttpStatusCode.ToString();
        telemetryClient.TrackException(e);
    }
    finally
    {
        // Update status code and success as appropriate.
        telemetryClient.StopOperation(operation);
    }
}  

Ha csökkenteni szeretné az alkalmazásjelentések telemetriai adatait, vagy ha más okból nem szeretné nyomon követni a Enqueue műveletet, használja közvetlenül az Activity API-t:

  • Hozzon létre (és kezdjen el) egy újat Activity az Alkalmazás Elemzések művelet indítása helyett. A művelet neve kivételével nem kell tulajdonságokat hozzárendelnie hozzá.
  • Szerializálja yourActivity.Id az üzenet hasznos adatait ahelyett, hogy operation.Telemetry.Id. A parancsot is használhatja Activity.Current.Id.

Sorból való törlés

Ehhez hasonlóan Enqueuea Storage-üzenetsorba irányuló tényleges HTTP-kéréseket az alkalmazás Elemzések automatikusan nyomon követi. A Enqueue művelet feltehetően a szülőkörnyezetben történik, például egy bejövő kérelemkörnyezetben. Az alkalmazás Elemzések SDK-k automatikusan korrelálnak egy ilyen műveletet és annak HTTP-részét, a szülőkérelmet és az ugyanabban a hatókörben jelentett egyéb telemetriát.

A Dequeue művelet trükkös. Az alkalmazás Elemzések SDK automatikusan nyomon követi a HTTP-kéréseket. Az üzenet elemzéséig azonban nem ismeri a korrelációs környezetet. Nem lehet korrelálni a HTTP-kérést az üzenet lekéréséhez a többi telemetriával, különösen akkor, ha egynél több üzenet érkezik.

public async Task<MessagePayload> Dequeue(CloudQueue queue)
{
    var operation = telemetryClient.StartOperation<DependencyTelemetry>("dequeue " + queue.Name);
    operation.Telemetry.Type = "Azure queue";
    operation.Telemetry.Data = "Dequeue " + queue.Name;
    
    try
    {
        var message = await queue.GetMessageAsync();
    }
    catch (StorageException e)
    {
        operation.telemetry.Properties.Add("AzureServiceRequestID", e.RequestInformation.ServiceRequestID);
        operation.telemetry.Success = false;
        operation.telemetry.ResultCode = e.RequestInformation.HttpStatusCode.ToString();
        telemetryClient.TrackException(e);
    }
    finally
    {
        // Update status code and success as appropriate.
        telemetryClient.StopOperation(operation);
    }

    return null;
}

Feldolgozás

Az alábbi példában a bejövő üzenetek a bejövő HTTP-kérésekhez hasonló módon lesznek nyomon követve:

public async Task Process(MessagePayload message)
{
    // After the message is dequeued from the queue, create RequestTelemetry to track its processing.
    RequestTelemetry requestTelemetry = new RequestTelemetry { Name = "process " + queueName };
    
    // It might also make sense to get the name from the message.
    requestTelemetry.Context.Operation.Id = message.RootId;
    requestTelemetry.Context.Operation.ParentId = message.ParentId;

    var operation = telemetryClient.StartOperation(requestTelemetry);

    try
    {
        await ProcessMessage();
    }
    catch (Exception e)
    {
        telemetryClient.TrackException(e);
        throw;
    }
    finally
    {
        // Update status code and success as appropriate.
        telemetryClient.StopOperation(operation);
    }
}

Hasonlóképpen más üzenetsor-műveletek is rendszerezhetők. A betekintő műveletet a dequeue művelethez hasonlóan kell végrehajtani. A rendszerállapot-kezelési műveletek nem szükségesek. Az alkalmazás Elemzések nyomon követi az olyan műveleteket, mint a HTTP, és a legtöbb esetben elegendő.

Az eszközüzenetek törlésekor győződjön meg arról, hogy beállítja a művelet (korreláció) azonosítóit. Másik lehetőségként használhatja az Activity API-t. Ezután nem kell műveleti azonosítókat beállítania a telemetriai elemeken, mert az Application Elemzések SDK elvégzi Önnek:

  • Hozzon létre egy újat Activity , miután már kapott egy elemet az üzenetsorból.
  • A Activity.SetParentId(message.ParentId) fogyasztói és a termelői naplók korrelációja.
  • Indítsa el a Activity.
  • Nyomon követheti a lekérési, feldolgozási és törlési műveleteket segítők használatával Start/StopOperation . Végezze el ugyanabból az aszinkron vezérlési folyamatból (végrehajtási környezetből). Ily módon megfelelően vannak korrelálva.
  • Állítsa le a Activity.
  • Telemetria manuális használata Start/StopOperation vagy meghívása Track .

Függőségtípusok

Az alkalmazás Elemzések függőségtípussal szabja testre a felhasználói felületi szolgáltatásokat. Az üzenetsorok esetében a tranzakciódiagnosztikai élményt javító alábbi típusokat DependencyTelemetry ismeri fel:

  • Azure queue Azure Storage-üzenetsorokhoz
  • Azure Event Hubs Az Azure Event Hubshoz
  • Azure Service Bus Az Azure Service Bushoz

Kötegelt feldolgozás

Egyes üzenetsorokkal több üzenetet is lekérhet egyetlen kéréssel. Az ilyen üzenetek feldolgozása feltehetően független, és a különböző logikai műveletekhez tartozik. A művelet nem kapcsolható össze Dequeue egy feldolgozandó üzenettel.

Minden üzenetet a saját aszinkron vezérlőfolyamatában kell feldolgozni. További információ: Kimenő függőségek nyomon követése szakasz.

Hosszan futó háttérfeladatok

Egyes alkalmazások hosszú ideig futó műveleteket indítanak el, amelyeket felhasználói kérések okozhatnak. A nyomkövetés/rendszerállapot szempontjából ez nem különbözik a kéréstől vagy a függőségi rendszerállapottól:

async Task BackgroundTask()
{
    var operation = telemetryClient.StartOperation<DependencyTelemetry>(taskName);
    operation.Telemetry.Type = "Background";
    try
    {
        int progress = 0;
        while (progress < 100)
        {
            // Process the task.
            telemetryClient.TrackTrace($"done {progress++}%");
        }
        // Update status code and success as appropriate.
    }
    catch (Exception e)
    {
        telemetryClient.TrackException(e);
        // Update status code and success as appropriate.
        throw;
    }
    finally
    {
        telemetryClient.StopOperation(operation);
    }
}

Ebben a példában telemetryClient.StartOperation létrehozza DependencyTelemetry és kitölti a korrelációs környezetet. Tegyük fel, hogy van egy szülőművelete, amelyet a műveletet ütemező bejövő kérések hoztak létre. Mindaddig, amíg BackgroundTask ugyanabban az aszinkron vezérlőfolyamatban indul el, mint egy bejövő kérés, a szülőművelettel van összefüggésben. BackgroundTask és az összes beágyazott telemetriai elem automatikusan korrelál az azt okozó kéréssel, még a kérés befejeződése után is.

Ha a feladat olyan háttérszálból indul, amelyhez nincs társítva semmilyen művelet (Activity) , BackgroundTask nincs szülője. Azonban beágyazott műveleteket is tartalmazhat. A tevékenységből jelentett összes telemetriai elem korrelációban van a DependencyTelemetry létrehozott BackgroundTaskelemekkel.

Kimenő függőségek nyomon követése

Nyomon követheti a saját függőségi típusát, vagy egy olyan műveletet, amelyet az alkalmazás Elemzések nem támogat.

A Enqueue Service Bus-üzenetsor vagy a Storage-üzenetsor metódusa példaként szolgálhat az ilyen egyéni nyomon követéshez.

Az egyéni függőségek nyomon követésének általános megközelítése a következő:

  • Hívja meg a TelemetryClient.StartOperation (bővítmény) metódust, amely kitölti a korrelációhoz szükséges tulajdonságokat és más tulajdonságokat, például a kezdést, az időbélyeget és az DependencyTelemetry időtartamot.
  • Adja meg a többi egyéni tulajdonságot, DependencyTelemetrypéldául a nevet és a szükséges egyéb környezeteket.
  • Hozzon létre egy függőségi hívást, és várja meg.
  • Állítsa le a műveletet StopOperation , ha befejeződött.
  • Kivételek kezelése.
public async Task RunMyTaskAsync()
{
    using (var operation = telemetryClient.StartOperation<DependencyTelemetry>("task 1"))
    {
        try 
        {
            var myTask = await StartMyTaskAsync();
            // Update status code and success as appropriate.
        }
        catch(...) 
        {
            // Update status code and success as appropriate.
        }
    }
}

A művelet letiltása leállítja a műveletet, ezért a hívás StopOperationhelyett ezt is megteheti.

Figyelmeztetés

Bizonyos esetekben előfordulhat, hogy a nem kezelt kivétel nemfinally hívható meg, ezért előfordulhat, hogy a műveletek nem lesznek nyomon követve.

Párhuzamos műveletek feldolgozása és nyomon követése

A hívás StopOperation csak az elindított műveletet állítja le. Ha az aktuális futó művelet nem egyezik meg a leállítani kívánt művelettel, StopOperation semmit sem tesz. Ez a helyzet akkor fordulhat elő, ha egyszerre több műveletet is elindít ugyanabban a végrehajtási környezetben.

var firstOperation = telemetryClient.StartOperation<DependencyTelemetry>("task 1");
var firstTask = RunMyTaskAsync();

var secondOperation = telemetryClient.StartOperation<DependencyTelemetry>("task 2");
var secondTask = RunMyTaskAsync();

await firstTask;

// FAILURE!!! This will do nothing and will not report telemetry for the first operation
// as currently secondOperation is active.
telemetryClient.StopOperation(firstOperation); 

await secondTask;

Győződjön meg arról, hogy a műveletet mindig ugyanabban az aszinkron metódusban hívja meg StartOperation és dolgozza fel, hogy elkülönítse a párhuzamosan futó műveleteket. Ha a művelet szinkron (vagy nem aszinkron), csomagolja be a folyamatot, és kövesse a következőt Task.Run: .

public void RunMyTask(string name)
{
    using (var operation = telemetryClient.StartOperation<DependencyTelemetry>(name))
    {
        Process();
        // Update status code and success as appropriate.
    }
}

public async Task RunAllTasks()
{
    var task1 = Task.Run(() => RunMyTask("task 1"));
    var task2 = Task.Run(() => RunMyTask("task 2"));
    
    await Task.WhenAll(task1, task2);
}

Application Elemzések operations vs. System.Diagnostics.Activity

System.Diagnostics.Activity az elosztott nyomkövetési környezetet jelöli, és keretrendszerek és kódtárak használják a környezet létrehozásának és propagálásának folyamaton belüli és kívüli létrehozására és propagálására, valamint a telemetriai elemek korrelációjára. Activity együttműködik a keretrendszer/tár közötti értesítési mechanizmussal System.Diagnostics.DiagnosticSource , hogy értesítést küldjön az olyan érdekes eseményekről, mint a bejövő vagy kimenő kérések és kivételek.

A tevékenységek első osztályú állampolgárok az Application Elemzések-ban. Az automatikus függőségek és kérések gyűjtése nagyban támaszkodik rájuk az események mellett DiagnosticSource . Ha az alkalmazásban hozta létreActivity, az nem eredményezné az alkalmazás Elemzések telemetriai adatok létrehozását. Az alkalmazás Elemzések eseményeket kell fogadniaDiagnosticSource, és ismernie kell az események nevét és hasznos adatait, hogy telemetria legyen lefordítvaActivity.

Minden alkalmazás Elemzések művelet (kérés vagy függőség) magában foglalja a Activity. Amikor StartOperation meghívják, az alatta jön létre Activity . StartOperation A kérések vagy függőségi telemetriák manuális nyomon követésének és annak ellenőrzésének ajánlott módja, hogy minden összefüggésben legyen.

Következő lépések