Remote environment data

With code tiles (in Dashboards) and code sections (in Notebooks), you can consolidate data from multiple Dynatrace environments.

The example JavaScript code described below uses the credential vault for secure token storage, and OAuth for authentication, to offer a robust and secure way to fetch data from a remote Dynatrace environment.

Prerequisites

Before you create the code for your dashboard tile or notebook section:

  • Create an OAuth client. For details, see Authentication.
  • Create a Dynatrace credential vault entry on the primary environment to store the OAuth token that is later used in the code tile or section for authentication. For details, see Credential vault.

You will use these in the JavaScript that you add to your code tile or section.

Code overview

Before you start coding, review the skeleton code in this section to see how the three main functions are used.

  1. authenticateToDynatrace(clientId = '', clientSecret = '')

    To authenticate against SSO, this function:

    1. Takes two parameters: clientId and clientSecret.
    2. Returns an access token.
  2. fetchFromDynatrace(credentialId = "", url = "", query = "")

    To fetch data from Dynatrace, this function:

    1. Retrieves the credentials from the credential vault entry on the primary tenant.
    2. Gets an access token for the secondary tenant via SSO.
    3. Makes the API call on the APIs of the secondary/remote tenant.
  3. async function()

    This is the main function. It calls fetchFromDynatrace (see above) with the necessary parameters.

import { credentialVaultClient } from "@dynatrace-sdk/client-classic-environment-v2";
async function authenticateToDynatrace(clientId = '', clientSecret = '') {
// authentication against SSO
// ...
}
async function fetchFromDynatrace(credentialId = "", url = "", query = "") {
// gets the credentials from the credential vault entry on the primary tenant (this tenant)
// gets access token for the secondary tenant via SSO, needed for the subsequent API call below
// the actual API call on the APIs of the secondary/remote tenant
// ...
}
export default async function() {
// dev stage -> CREDENTIALS_VAULT-XXXXXXXXXXXXXXXX
// prod stage -> CREDENTIALS_VAULT-XXXXXXXXXXXXXXXX
// ...
}

Code details

Now that you have completed the prerequisites and reviewed the general code structure, you're ready to code.

  • Base your code on the example below.

  • Read the comments in the code example for code details.

  • Replace CREDENTIALS_VAULT-XXXXXXXXXXXXXXXX with your own credential ID.

  • Replace https://remote-environment-id.apps.dynatrace.com/platform/storage/query/v1/query:execute?enrich:metric-metadata with your own URL.

  • Customize the "fetch logs | limit 1" query according to your needs.

  • Run your code in a code tile (Dashboards) or code section (Notebooks).

    If you encounter errors when you run your code, they will be caught and logged with the prefixes [DynatraceAuthError], [CredentialVaultError], or [ExecutionError] for easier debugging.

import { credentialVaultClient } from "@dynatrace-sdk/client-classic-environment-v2";
// 1 authentication against SSO
async function authenticateToDynatrace(clientId = '', clientSecret = '') {
const scopes = [
"environment-api",
"storage:buckets:read",
"storage:bizevents:read",
"storage:logs:read",
"storage:metrics:read",
"storage:entities:read"
].join(" ")
const {access_token} = await fetch("https://sso.dynatrace.com/sso/oauth2/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: `grant_type=client_credentials&client_id=${clientId}&client_secret=${clientSecret}&scopes=${scopes}`,
})
.then((resp) => resp.json())
.catch(error => `[DynatraceAuthError] ${error}`)
return access_token
}
async function fetchFromDynatrace(credentialId = "", url = "", query = "") {
// 1 - gets the credentials from the credential vault entry on the primary tenant (this tenant)
const {password, username } = await credentialVaultClient
.getCredentialsDetails({ id: credentialId })
.catch((e) => console.error(`[CredentialVaultError] ${e}`));
// 2 - gets an access token for the secondary tenant via SSO, needed for the subsequent API call below
const accessToken = await authenticateToDynatrace(username, password)
// 3 - the actual API call on the APIs of the secondary/remote tenant
return await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify({
query,
requestTimeoutMilliseconds: 60000,
enablePreview: true,
}),
}).then((res) => res.json())
.catch(e => `[ExecutionError] ${e}`);
}
export default async function() {
const { result } = await fetchFromDynatrace(
"CREDENTIALS_VAULT-XXXXXXXXXXXXXXXX",
"https://remote-environment-id.apps.dynatrace.com/platform/storage/query/v1/query:execute?enrich:metric-metadata",
"fetch logs | limit 1"
);
return result
}