Skip to main content

Forecasting with Davis® AI service

The latest Dynatrace platform provides general-purpose AI/ML services covering various functionalities. In this guide, you'll learn the intricacies of using the Davis® predictive and causal AI platform service from your Dynatrace® Apps.

Get available analyzers

Before getting started, one of the main questions to answer is what Davis® AI analyzers you have at your disposal. To get the available analyzers, you have two options:

  • Check out the /analyzers endpoint in the . It's the easiest way of accessing every option of the different endpoints.

  • Use the Davis® AI analyzers SDK in your app:

    import { analyzersClient } from '@dynatrace-sdk/client-davis-analyzers';

    const { analyzers, totalCount, nextPageKey } = await analyzersClient.queryAnalyzers({
    filter: "name contains 'statistic'",
    addFields: 'baseAnalyzer, type, input',
    });
    Tip

    This operation requires the scope davis:analyzers:read. Read more about scopes in this guide.

Once you've decided which analyzer better fits your use case, you need to understand the subtleties of that analyzer, which we'll see in the next section.

Analyzers input and output

All Davis® AI analyzers have a base standard set of input parameters, like timeframe or logVerbosity. Additionally, each analyzer needs a specific set of input parameters, which vary from one to another. There are a couple of ways of getting this information:

  • Using the .

  • Use the SDK to get the analyzer definition:

    const analyzer = await analyzersClient.getAnalyzer({
    analyzerName: 'dt.statistics.GenericForecastAnalyzer',
    });
    Tip

    This operation requires the scope davis:analyzers:read. Read more about scopes in this guide.

The output of each analyzer can be very different as well. You need to query the analyzer definition using any of the two methods above to get the output definition.

Time series forecast analysis

At this point, we know the analyzer we want to use and understand its input parameters and its output definition. Now, we get to use it. Let's look at a complete example of how you would use the dt.statistics.GenericForecastAnalyzer analyzer to get a forecast of any time series metric.

Execute analyzer

Tip

This operation requires the scope davis:analyzers:execute. Read more about scopes in this guide.

Let's begin by creating a function that will request the forecast analysis:

loadForecast.ts
import { analyzersClient } from '@dynatrace-sdk/client-davis-analyzers';

export const loadForecast = async (query: string) => {
const analyzerName = 'dt.statistics.GenericForecastAnalyzer';
const response = await analyzersClient.executeAnalyzer({
analyzerName,
body: {
timeSeriesData: {
expression: query,
},
},
});

// ...
};
Note

Depending on the chosen analyzer and the analyzer input, additional scopes might be required, for example, storage:buckets:read and storage:metrics:read to enable the analyzer to read time series data from Grail™.

This function receives a DQL query as a parameter and triggers an async forecast analysis on the results of running said query via the executeAnalyzer function from the analyzersClient. If the analysis takes more than two seconds to finish, the response will contain a requestToken that will allow you to poll until the results are available.

Poll analyzer execution

Let's create a new pollExecution function to handle the polling logic.

pollExecution.ts
import { AnalyzerResult, AnalyzerResultExecutionStatus, analyzersClient } from '@dynatrace-sdk/client-davis-analyzers';

export const pollExecution = async (analyzerName: string, requestToken: string): Promise<AnalyzerResult> => {
const MAX_ATTEMPTS = 10;
const INTERVAL_MS = 1000;
let attempts = 0;

while (attempts < MAX_ATTEMPTS) {
await new Promise((resolve) => setTimeout(resolve, INTERVAL_MS));

const { result } = await analyzersClient.pollAnalyzerExecution({
analyzerName,
requestToken,
});

if (result.executionStatus === AnalyzerResultExecutionStatus.Completed) {
return result;
}

if (result.executionStatus === AnalyzerResultExecutionStatus.Aborted) {
throw new Error('The analyzer execution was aborted');
}

attempts++;
}

const cancelResponse = await analyzersClient.cancelAnalyzerExecution({
analyzerName,
requestToken,
});

if (cancelResponse && cancelResponse.result.executionStatus === AnalyzerResultExecutionStatus.Completed) {
return cancelResponse.result;
}

throw new Error('Max polling retries reached');
};

Aside from the simple polling implementation, we've introduced two new functions:

  • pollAnalyzerExecution: This function allows you to check the analysis execution status with the analyzer name and the request token you got in the initial request.
  • cancelAnalyzerExecution: Once we've reached the max polling attempts, we recommend canceling the analysis execution. If the analysis finishes between the last poll and the cancellation, this function will return the analysis results. Otherwise, the response will be undefined.

Handle analyzer output

We can now use pollExecution in our main function and extract the forecasting information as a TimeseriesBand from the analysis output:

loadForecast.ts
import {
AnalyzerResultExecutionStatus,
analyzersClient,
} from '@dynatrace-sdk/client-davis-analyzers';
import { convertToTimeseriesBand, TimeseriesBand } from '@dynatrace/strato-components-preview';
import { pollExecution } from './pollExecution';

export const loadForecast = async (query: string): Promise<TimeseriesBand> => {
const analyzerName = 'dt.statistics.GenericForecastAnalyzer';
const response = await analyzersClient.executeAnalyzer({
analyzerName,
body: {
timeSeriesData: {
expression: query,
},
},
});

const analysisResult = response.requestToken
? await pollExecution(analyzerName, response.requestToken)
: response.result;

if (analysisResult.executionStatus === AnalyzerResultExecutionStatus.Completed) {
const analyzerOutput = analysisResult.output[0];
const timeseriesBandData = convertToTimeseriesBand(
analyzerOutput.timeSeriesDataWithPredictions.records[0],
analyzerOutput.timeSeriesDataWithPredictions.types[0],
);

if (timeseriesBandData) {
return timeseriesBandData.timeseriesBand;
}

throw new Error('Unexpected error');
}

throw new Error('The analyzer execution was aborted');
};

Your loadForecast function is now ready. You can provide any time series DQL query to this function, and it will handle the forecast analysis and return it in TimeseriesBand format, which you can use to visualize it.

Tip

You can learn more about visualizing a TimeseriesBand from the TimeseriesChart reference page.

Troubleshooting

Davis® AI analyzer executions might fail for different reasons. In these cases, the response will contain a log array that you can use to figure out why the analysis was unsuccessful. For instance, if the provided query doesn't return enough data points, the response will look something like this:

{
"result": {
"resultId": "4e1a8a1efd560193",
"resultStatus": "FAILED",
"executionStatus": "COMPLETED",
"input": {
...
},
"logs": [
{
"level": "WARNING",
"message": "More historical data is required to generate a reliable forecast. Increase the timeframe or adapt the resolution to include a minimum of 14 non-NaN observations.",
"analyzerName": "dt.statistics.GenericForecastAnalyzer"
},
{
"level": "SEVERE",
"message": "The analysis of the data was not successful.",
"analyzerName": "dt.statistics.GenericForecastAnalyzer"
}
],
"output": []
}
}
Still have questions?
Find answers in the Dynatrace Community