arazzo: 1.0.1 info: title: Dynatrace Ingest Log Records and Search Them Back summary: Stream log records into Grail and immediately search them back to confirm ingestion. description: >- Validates a custom log-shipping integration end to end. The workflow ingests an array of log records into the Grail data lakehouse, then runs a DQL search over the same source to confirm the records are queryable. Every step spells out its request inline so the flow can be read and executed without opening the underlying OpenAPI description. version: 1.0.0 sourceDescriptions: - name: logsApi url: ../openapi/dynatrace-log-monitoring-api-v2-openapi.yml type: openapi workflows: - workflowId: ingest-and-search-logs summary: Ingest log records and search them back to confirm ingestion. description: >- Ingests an array of log records, then searches Grail with a DQL query to verify the freshly ingested records are retrievable. inputs: type: object required: - records - searchQuery properties: records: type: array description: An array of log record objects, each with at least a content field. items: type: object searchQuery: type: string description: DQL search query used to read the records back (e.g. 'fetch logs | filter log.source=="my-app"'). from: type: string description: Start of the search time range (e.g. now-15m). steps: - stepId: ingestLogs description: >- Ingest the array of log records into the Grail data lakehouse. Records are accepted asynchronously with a 204 status. operationId: ingestLogs requestBody: contentType: application/json payload: $inputs.records successCriteria: - condition: $statusCode == 204 outputs: statusCode: $statusCode - stepId: searchLogs description: >- Search Grail with the supplied DQL query to confirm the freshly ingested records are now retrievable, newest first. operationId: searchLogs parameters: - name: query in: query value: $inputs.searchQuery - name: from in: query value: $inputs.from - name: sort in: query value: -timestamp - name: limit in: query value: 1000 successCriteria: - condition: $statusCode == 200 outputs: firstContent: $response.body#/results/0/content firstSeverity: $response.body#/results/0/severity nextSliceKey: $response.body#/nextSliceKey outputs: ingestStatus: $steps.ingestLogs.outputs.statusCode firstContent: $steps.searchLogs.outputs.firstContent