Skip to main content

Troubleshoot app functions

Code written in app functions, Dynatrace Workflows, or Dynatrace Notebooks is executed within the Dynatrace JavaScript runtime. This page provides an overview of the issues that you might encounter while developing functions and suggested solutions.

Serialization errors

JSON serialization errors ("Failed to serialize result to JSON") might occur when returning a value from a function.

Whenever an app function returns a value, the runtime internally calls JSON.stringify to convert the given value to a JSON representation. Therefore, the same limitations also apply when returning a value from a function:

Event loop behavior

The behavior of deployed Dynatrace app functions differs from that of other JavaScript runtimes like Bun or Deno. Deployed Dynatrace app functions always wait for the JavaScript event loop to finish. For example, you might expect your function invocation to finish immediately rather than waiting for five seconds. This isn't the case, though. The function runs until the timeout finishes.

export default function () {
setTimeout(() => {}, 5000);
}

Promises that never resolve or reject can behave in a similar way. You might encounter issues with third-party packages that do work in the background if those background tasks aren't gracefully shut down. In such cases, your Dynatrace app function will appear stuck and eventually run into a timeout error if the event loop doesn't terminate.

DNS errors

Due to platform limitations, you might encounter DNS error messages such as:

dns error: Device or resource busy (os error 16)

There are two primary causes of this error:

  • The host targeted by an HTTP request doesn't exist, for example, due to a typo.
  • The system is overloaded because too many requests are sent concurrently. This error is standard when ingesting a lot of data split into several requests, especially when you don't await such requests. Consider sending all your data in a single request (if supported by the server) or batch your requests instead.

Batching requests

Find a simple implementation for request batching below. Note that this code only serves as a minimal example. Consider handling errors and potential rate limits of the remote service gracefully in a production environment.

async function fetchInBatches(urls: string[], batchSize: number): any {
const results = [];
for (let i = 0; i < urls.length; i += batchSize) {
const batch = urls.slice(i, i + batchSize);
const batchResults = await Promise.all(batch.map((url) => fetch(url).then((res) => res.json())));
results.push(...batchResults);
}
return results;
}

export default async function () {
const urls = [
'https://some-api.example.com/item/1',
'https://some-api.example.com/item/2',
'https://some-api.example.com/item/3',
'https://some-api.example.com/item/4',
'https://some-api.example.com/item/5',
'https://some-api.example.com/item/6',
// ...
];

const batchSize = 5; // Adjust this number based on expected load
const allData = await fetchInBatches(urls, batchSize);
console.log(allData);
}
Still have questions?
Find answers in the Dynatrace Community