Skip to main content
🛟 Aarzel niet om contact met ons op te nemen als u problemen tegenkomt bij het implementeren van aangepaste instrumentaties. We helpen u graag!
Het opnemen van aangepaste instrumentatie in uw applicatie kan nuttig zijn om de specifieke regels code te identificeren die prestatieproblemen veroorzaken. AppSignal biedt helpers waarmee u relevante gegevens over de toestand van uw applicatie kunt tonen naast prestatiemetingen, om u te helpen de oorzaken van eventuele prestatieproblemen van uw applicatie te identificeren.

Installatie

Om de helperfuncties van AppSignal in uw instrumentatie te gebruiken, moet u eerst opentelemetry importeren en een tracer-object definiëren. Afhankelijk van uw instrumentatie moet u mogelijk ook aanvullende spans aanmaken. Onze Voorbeelden van use cases laten zien hoe u tracers, spans en helpers kunt gebruiken om uw aangepaste instrumentatie te maken.

OpenTelemetry importeren en tracer definiëren

De AppSignal-integratie voor Node.js gebruikt OpenTelemetry tracer-objecten. Deze tracers bevatten diverse functies voor het maken van aangepaste instrumentaties. De Tracer biedt functies voor het aanmaken en creëren van nieuwe spans. Deze documentatie beschrijft hoe u tracers en spans kunt gebruiken om uw aangepaste integratie te implementeren. U moet eerst het trace-object importeren uit @opentelemetry/api voordat u met tracers en spans gaat werken. Door de functie getTracer op het trace-object aan te roepen, kan een nieuw tracer-object worden aangemaakt. U moet uw tracer-object in deze functie een naam geven, zoals te zien in het onderstaande voorbeeld, waar de functie getTracer wordt gebruikt om een tracer met de naam "my interesting app" te definiëren.
import { trace } from "@opentelemetry/api";

const tracer = trace.getTracer("my-interesting-app");

Spans

Een span is de naam van het object dat we gebruiken om gegevens vast te leggen over de prestaties van uw applicatie, eventuele fouten en de omringende context. Een span maakt deel uit van een bredere trace, een hiërarchische weergave van de datastroom door uw applicatie. Spans houden de start- en eindtijd van een gebeurtenis bij, samen met andere informatie zoals de naam of andere gerelateerde gegevens. U kunt meer lezen over spans in de OpenTelemetry Tracing-documentatie.

Een actieve span aanmaken

Nieuwe spans kunnen worden aangeroepen via het trace-object. Code die binnen een Express- of Koa-handler wordt geïnstrumenteerd, bevindt zich al binnen een span. U kunt nieuwe spans aanmaken door de functie startActiveSpan() op het tracer-object aan te roepen. Nieuw aangemaakte spans worden het kind van de span waarin ze zijn aangemaakt, als die bestaat. U kunt onderliggende spans gebruiken om de prestaties te meten van taken die binnen een bovenliggende span worden uitgevoerd. Geef uw span een naam die het doel duidelijk maakt. Voer alle taken die u wilt monitoren uit binnen de functie startActiveSpan(), zoals in het onderstaande voorbeeld.
tracer.startActiveSpan("printing coffee beans", async (span) => {
  const coffeeBeans = await fetchAllCoffeeBeans();
  console.log(coffeeBeans);

  span.end();
});
Nadat de taak is voltooid, moet u de span sluiten: span.end()

Voorbeelden van use cases

Bij het implementeren van aangepaste instrumentatie kunt u nieuwsgierig zijn naar het gedrag van bepaalde functies, bijvoorbeeld hoe lang het duurt om ze uit te voeren.

Helpers gebruiken

In het onderstaande voorbeeld zijn we nieuwsgierig naar de prestaties van ons “order-coffee” GET-endpoint voor verschillende koffiebrandingen. Om dit te onderzoeken gebruiken we de functie setAttribute om een tag met de naam flavor aan te maken, waarvan we de waarde uit de request parameters halen. Let op: Omdat dit zich binnen een Express request handler bevindt, is er al een root-span aangemaakt.
app.get('/order-coffee', (req, res) => {
    const roast = req.params.roast
    setTag("roast", roast)

    const coffeeBeans = pickCoffeeBeans(roast)
    prepareCoffeeBag(coffeeBeans)
  })
}
Om diepere inzichten te krijgen in hoe onze code presteert, kunnen we onderliggende spans gebruiken om functies te inspecteren die binnen onze Express-handler worden aangeroepen. De onderstaande code maakt een onderliggende span aan van de span "picking coffee beans" die in de functie pickCoffeeBeans is gedefinieerd. Zodra het attribuut is toegewezen en alle functies zijn uitgevoerd, beëindigen we de span met .end() om te garanderen dat AppSignal de start- en eindtijd en de door ons toegekende attributen ontvangt:
function pickCoffeeBeans(roast) {
  tracer.startActiveSpan("picking coffee beans", async (span) => {
    const roastBrands = {
      light: "Caffinated Cloud",
      medium: "Feeling The Buzz",
      dark: "The Jitters",
    };

    const roastBrand = roastBrands[roast];

    setTag("brand", roastBrand);
    await retrieveDrinkTypes(roastBrand);
    span.end();
  });
}
In AppSignal kunnen we prestatiegegevens voor deze functie zien. We kunnen de roast- en batch-tags gebruiken om de gegevens te filteren en meer inzicht te krijgen in welke parameters mogelijk invloed hebben op het gedrag van de code van onze applicatie. Screenshot van tags

Actieve spans

Hoewel tags nuttig zijn om prestatieverschillen op dezelfde functie te analyseren, geven ze geen inzicht in de prestaties van eventuele functies die vanuit onze functie worden aangeroepen. Om ons meer inzicht te geven in wat er binnen pickCoffeeBeans() gebeurt, maken we een nieuwe activeSpan aan en geven deze de naam “picking coffee beans”. Alle logica die we willen volgen, wordt uitgevoerd binnen een async-functie. We await de promise die door retrieveDrinkTypes() wordt teruggegeven, zodat we de prestaties ervan kunnen volgen als onderliggende span van de span "picking coffee beans" die we in pickCoffeeBeans() hebben aangemaakt.
function pickCoffeeBeans(roast) {
  tracer.startActiveSpan("picking coffee beans", async (span) => {
    const roastBrands = {
      light: "Caffinated Cloud",
      medium: "Feeling The Buzz",
      dark: "The Jitters",
    };

    const roastBrand = roastBrands[roast];
    await retrieveDrinkTypes(roastBrand);
    span.end();
  });
}

function retrieveDrinkTypes(roastBrand) {
  return new Promise((resolve) => {
    const span = tracer.startActiveSpan("Fetching coffee types");

    const brandDrinks = {
      "Caffinated Cloud": ["americano", "capuccino"],
      "Feeling The Buzz": ["capuccino", "latte"],
      "The Jitters": ["espresso"],
    };

    const drinkTypes = brandDrinks[roastBrand];

    // we want to give our Barista's some time prepare the machine
    setTimeout(() => {
      resolve(drinkTypes);
      span.end();
    }, 60000);
  });
}
Met deze instrumentatie biedt AppSignal inzicht in de prestaties van pickCoffeeBeans(), met inbegrip van de prestatiegegevens van de functie retrieveDrinkTypes(), waardoor u meer inzicht krijgt in welke factoren de algehele prestaties van een functie beïnvloeden.

Helpers

Gegevens die naar AppSignal worden verstuurd, mogen geen persoonsgegevens bevatten, zoals namen, e-mailadressen, enz. Het is uw verantwoordelijkheid ervoor te zorgen dat de gegevens van uw applicatie worden geschoond voordat ze naar AppSignal worden doorgestuurd. Wanneer het identificeren van een persoon noodzakelijk is, moet uw applicatie alternatieve vormen van identificatie gebruiken zoals een gebruikers-ID, hash of pseudoniem.
Om helperfuncties te gebruiken, moet u ze eerst importeren uit @appsignal/nodejs. In het onderstaande voorbeeld wordt de namespace waarin de code wordt uitgevoerd aan AppSignal gerapporteerd. Alle beschikbare helperfuncties worden beschreven in de onderstaande documentatie.
import { setNamespace } from "@appsignal/nodejs";

setNamespace("web");
Alle beschikbare helperfuncties voor aangepaste instrumentatie-attributen worden beschreven in de onderstaande lijst.

Helperfuncties

De codefragmenten voor de onderstaande helpers gaan ervan uit dat uw code al wordt geïnstrumenteerd (bijvoorbeeld binnen een Express- of Koa-request handler). Als uw code nog niet wordt geïnstrumenteerd, moet u een span aanmaken en de helpers daarbinnen gebruiken.

Namespace

Stelt de stringwaarde in van de namespace van de root-span.
import { setNamespace } from "@appsignal/nodejs";
setNamespace("app");

Tag

Stelt een tag in, bijvoorbeeld op basis van een request parameter, die als filter kan worden gebruikt binnen de AppSignal-applicatie. In het onderstaande voorbeeld maken we een tag met de naam color en de waarde blue. U kunt tags configureren met namen die relevant zijn voor de context van uw applicatie.
import { setTag } from "@appsignal/nodejs";
setTag("color", "blue");

Request Parameters

Een object dat serialiseerbaar is naar JSON. Binnenkomende request parameters, request body en query parameters.
import { setParams } from "@appsignal/nodejs";

const exampleParams = { action: "delete" };
setParams(exampleParams);

Set Session Data

Een object dat serialiseerbaar is naar JSON.
import { setSessionData } from "@appsignal/nodejs";

const exampleSessionData = { locale: "en-GB" };
setSessionData(exampleSessionData);

Request Headers

Een string die de headerwaarde bevat.
import { setHeader } from "@appsignal/nodejs";
setHeader("Content-type", "application/json");

Root Name

Stelt u in staat om de naam van de trace in te stellen. Samples worden op basis van hun trace-naam in acties gegroepeerd.
import { setRootName } from "@appsignal/nodejs";

// somewhere in your code where there's an active span...
setRootName("The action name");

Voorbeeld-use case

Uw applicatie heeft een endpoint genaamd GET /coffee.
app.get("/coffee", (req, res) => {
  // ...
});
Alle requests naar dit endpoint genereren samples met de naam GET /coffee, maar uw endpoint handelt meerdere acties af: coffee?action=buy en coffee?action=sell. Span zonder Root Name Hoewel ze allemaal het endpoint GET /coffee gebruiken, zijn ze conceptueel zeer verschillend en dus zou het logisch zijn ze in AppSignal apart te groeperen in plaats van in hetzelfde GET /coffee-sample. Hiervoor kunt u de helper setRootName() gebruiken:
import { setRootName } from "@appsignal/nodejs";

app.get("/coffee", (req, res) => {
  if (req.query.action === "buy") {
    setRootName("Buy coffee");
    // ... buy coffee
  } else if (req.query.action === "sell") {
    setRootName("Sell coffee");
    // ... sell coffee
  }
});
Door setRootName te gebruiken, verandert de naam van de root-span, waardoor de samples voor de requests coffee?action=buy en coffee?action=sell in afzonderlijke acties worden gegroepeerd: Root Name Span

Custom Data

Een object dat serialiseerbaar is naar JSON.
import { setCustomData } from "@appsignal/nodejs";

const exampleCustomData = { stroopwaffle: "true", coffee: "false" };
setCustomData(exampleCustomData);

Helpers voor onderliggende spans

De volgende helpers zijn alleen van toepassing op onderliggende spans. Om een onderliggende span aan te maken, moet u een nieuwe actieve span creëren. Nieuwe spans zijn automatisch kinderen van hun bovenliggende span.

Category

Een string die de categorie van de onderliggende span bevat. De naam moet . gebruiken om de hiërarchische overerving van de categorie uit te drukken. Bijvoorbeeld: cafe.coffee.cupsize
import { setCategory } from "@appsignal/nodejs";
setCategory("category.name");

Name

Een string die de titel van de onderliggende span in de event timeline bevat.
import { setName } from "@appsignal/nodejs";
setName("Users query");

Body

🔐 Stuur geen Persoonlijk Identificeerbare Informatie (PII) naar AppSignal. Filter PII (bijv. namen, e-mailadressen) en gebruik in plaats daarvan een ID, hash of gepseudonimiseerde identificator.

Voor onder HIPAA vallende entiteiten vindt u meer informatie over het ondertekenen van een Business Associate Agreement (BAA) in onze documentatie over Business Add-Ons.
De body van de span kan aanvullende informatie over de gebeurtenis bevatten, zoals het HTTP-request, de verbonden host, enz. Zorg ervoor dat u de informatie schoont voordat u deze aan de span toevoegt, zodat er geen persoonlijk identificeerbare informatie naar AppSignal wordt verstuurd. Deze informatie is voor de span zichtbaar wanneer u over de event timeline beweegt. Om SQL-queries in de body van de span op te slaan, gebruikt u in plaats hiervan de setSqlBody-helper.
import { setBody } from "@appsignal/nodejs";
setBody("Span body");

SQL body

Beschikbaar sinds Node.js-pakket 3.0.25.
Stel een SQL-query in als de body van de span zoals deze verschijnt in de event timeline van prestatie-events in de detailweergave van het incident-sample. Dit is vergelijkbaar met de setBody-helper, maar is gespecialiseerd voor SQL-queries. Elke SQL-query die met dit attribuut als body wordt ingesteld, wordt geschoond om te voorkomen dat PII-gegevens (persoonlijk identificeerbare informatie) naar onze servers worden verzonden. Zie de setBody-helper voor meer details over hoe het body-attribuut werkt. Wanneer zowel de setBody- als de setSqlBody-helper op dezelfde span worden aangeroepen, is de waarde van de setSqlBody-helper leidend en wordt de waarde van de setBody-helper genegeerd.
import { setSqlBody } from "@appsignal/nodejs";
setSqlBody("SELECT * FROM users");