← Back to all articles

Observability · 2024-10-28 · 3 min read

Dynatrace Custom Apps: Correlating Logs Across Distributed Layers

Dynatrace is great for creating simple and complex dashboards and notebooks. While the use-case below can be solved with a standard dashboard, it serves as a clean, practical blueprint for building custom apps in Dynatrace AppEngine.

Our Use-Case

Our setup consists of two decoupled systems—a booking system and a processing layer:

  1. The booking system takes orders, saves them to a database, and logs them with a trx_id (transaction ID) and a newly created session_id.
  2. The processing layer picks up the order and processes it via several transformations. However, subsequent log entries only carry the session_id, not the original trx_id.

We want to give engineers and support teams a simple form where they can enter a trx_id and automatically retrieve all log entries across both systems.

Querying with DQL

First, we match on the trx_id to extract the session_id, and then run a DQL query to stitch the full lifecycle together:

sql
fetch logs
| parse content, """DATA 'trx_id:'LD:trx_id', session_id:'LD:session_id"""
| parse content, """DATA 'session_id:'LD:session_idx','"""
| filter isNotNull(trx_id) or isNotNull(session_idx)
| filter matchesValue(session_id, "465654-65454-5458") or matchesValue(session_idx, "465654-65454-5458")
| sort timestamp
| fieldsAdd session_id = if(isNull(session_id), session_idx, else: session_id)
| fields trx_id, session_id, content

Building the Dynatrace React App

Using @dynatrace/strato-components and @dynatrace-sdk/react-hooks, we can chain the two DQL queries cleanly inside a React component:

tsx
import React, { useState } from 'react';
import { Flex } from '@dynatrace/strato-components/layouts';
import { TitleBar } from '@dynatrace/strato-components-preview/layouts';
import { DataTable, TableColumn } from '@dynatrace/strato-components-preview/tables';
import { ProgressCircle } from '@dynatrace/strato-components/content';
import { useDqlQuery } from '@dynatrace-sdk/react-hooks';
import { FormField, Label, TextInput } from '@dynatrace/strato-components-preview/forms';
import { Button } from '@dynatrace/strato-components/buttons';
import { logTrxQuery, logSessionQuery } from '../queries';

function ResultsTable({ trxid }: { trxid: string }) {
  const columns: TableColumn[] = [
    { header: 'Transaction ID', accessor: 'trx_id', autoWidth: true },
    { header: 'Session ID', accessor: 'session_id', autoWidth: true },
    { header: 'Content', accessor: 'content', autoWidth: true },
  ];

  const result = useDqlQuery({ body: { query: logTrxQuery(trxid) } });

  let session_id = "";
  if (!result.isLoading) {
    result?.data?.records.forEach((value) => {
      session_id = value?.session_id?.toString() ?? "";
    });
  }

  const resultSess = useDqlQuery({ body: { query: logSessionQuery(session_id) } });

  if (resultSess.isLoading) return <ProgressCircle />;
  return (
    <DataTable data={resultSess?.data?.records || []} columns={columns}>
      <DataTable.Pagination />
    </DataTable>
  );
}

export const LogMesh = () => {
  const [trxid, setTrxid] = useState("");
  const [sent, setSent] = useState(false);

  return (
    <Flex width="100%" flexDirection="column" justifyContent="center" gap={16}>
      <TitleBar>
        <TitleBar.Title>Log Meshing</TitleBar.Title>
      </TitleBar>
      <FormField>
        <Label>Enter Transaction ID</Label>
        <TextInput
          type="text"
          id="trxid"
          name="trxid"
          value={trxid}
          onChange={(val) => { setTrxid(val); setSent(false); }}
        />
        <Button onClick={() => setSent(true)} variant="emphasized">Search</Button>
        {sent && <ResultsTable trxid={trxid} />}
      </FormField>
    </Flex>
  );
};

If you'd like the full repository or need help building custom Dynatrace extensions and apps, get in touch.

Stay in the loop

Enjoyed this technical breakdown?

Subscribe for occasional engineering field notes on load testing, synthetic data, and observability—or talk to us about your system.