Store app and user states
If your app needs some internal global states or user-specific states, the package @dynatrace-sdk/client-state provides app states and user app states for that purpose. In general, app states can be read by all authenticated users of the app, while user app states are private to the user who wrote that state.
That package exposes those states via key-value interfaced operations. The key designates the purpose of the stored app state, the value contains the stored user app state value. All operations can be imported via the stateClient
namespace.
When you run your app on your local development server, the states that the SDK manipulates are confined to the scope of local development only, so they are persisted separately from the states of the deployed app. As a result, you will not run into the danger of overriding the states of the deployed app during development.
States are persistent across updates of an app. Therefore any migration of states potentially necessary for the new version of an app must be done in the app code itself.
Set a state by key
To set the app state or user app state, you can use the setAppState
or setUserAppState
function from the @dynatrace-sdk/client-state
package.
Adding a version
field to your state is recommended to ease a future migration.
import { stateClient } from '@dynatrace-sdk/client-state';
const dataFetchedFromExternalSource = {
version: '1.2',
timestamp: 1663231611,
weather: [{ city: 'Vienna', temperature: 23, unit: 'celsius' }],
};
stateClient.setAppState({
key: 'weather',
body: { value: JSON.stringify(dataFetchedFromExternalSource) },
});
stateClient.setUserAppState({ key: 'favourite-hosts', body: { value: 'HOST-5A58A3AD724F5ABB,HOST-C09983F94EFCE493' } });
This operation requires the scopes state:app-states:write, state:user-app-states:write
. Read more about scopes in this guide.
Get a state by key
To fetch a previously stored state, you can use the getAppState
and getUserAppState
operations with the key as the parameter that had been used for the corresponding write operation.
import { stateClient } from '@dynatrace-sdk/client-state';
const appStateWeather = await stateClient.getAppState({ key: 'weather' });
const weather = JSON.parse(appStateWeather.value);
const userAppStateFavouriteHosts = await stateClient.getUserAppState({ key: 'favourite-hosts' });
const favouriteHosts = userAppStateFavouriteHosts.value.split(',');
This operation requires the scopes state:app-states:read, state:user-app-states:read
. Read more about scopes in this guide.
These operations throw an exception when the state you try to retrieve does not exist. If that is an expected scenario in your app, you should add some exception handling around it. Alternatively, you could also use the list endpoint by filtering for a specific key to get an empty or one-element array.
List all states
It can be handy to get a list of all app states or user app states currently in use by your app, especially if your app does not use a fixed set of known static keys but dynamically-created keys. The functions getAppStates
and getUserAppStates
provide that functionality.
import { stateClient } from '@dynatrace-sdk/client-state';
const appStateKeys: Array<{ key: string }> = await stateClient.getAppStates({});
const userAppStateKeys: Array<{ key: string }> = await stateClient.getUserAppStates({});
This operation requires the scopes state:app-states:read, state:user-app-states:read
. Read more about scopes in this guide.
By default, getAppStates
and getUserAppStates
only return the keys. You can define additional fields to be returned by specifying them in a comma-separated string in the addFields
parameter.
import { stateClient, ListAppState, ListUserAppState } from '@dynatrace-sdk/client-state';
const appStates: ListAppState[] = await stateClient.getAppStates({
addFields: 'value,modificationInfo.lastModifiedBy',
});
const userAppStates: ListUserAppState[] = await stateClient.getUserAppStates({
addFields: 'value,modificationInfo',
});
This operation requires the scopes state:app-states:read, state:user-app-states:read
. Read more about scopes in this guide.
Filter states
The getAppStates
and getUserAppStates
methods also allow filtering the states via the filter
parameter.
The following fields are supported for filtering:
key
, supports operators:=
,!=
,contains
,starts-with
, andends-with
modificationInfo.lastModifiedTime
, supports operators:=
,!=
,<
,<=
,>
, and>=
modificationInfo.lastModifiedBy
, supports operators:=
,!=
,contains
,starts-with
, andends-with
Operators contains
, starts-with
, and ends-with
are case-insensitive. Comparisons via =
, !=
are case-sensitive.
Conditions can be connected via and
and or
. Individual conditions can be negated by not
.
The filter string may be up to 256 characters long. You can nest conditions (using round brackets) up to 2 levels deep.
import { stateClient } from '@dynatrace-sdk/client-state';
const appStateKeys: Array<{ key: string }> = await stateClient.getAppStates({
filter: "modificationInfo.lastModifiedTime > '2022-07-01T00:10:05.000Z'",
});
const userAppStateKeys: Array<{ key: string }> = await stateClient.getUserAppStates({
filter:
"(key starts-with 'favourite' or key starts-with 'favorite') and not(key contains 'disk' or key contains 'process')",
});
const oneElementOrEmpty: Array<{ key: string }> = await stateClient.getAppStates({
filter: "key = 'might-not-exist'",
});
This operation requires the scopes state:app-states:read, state:user-app-states:read
. Read more about scopes in this guide.
Delete a state by key
Of course, you can delete app states and user app states that are not needed anymore. In addition, this will free the equivalent of the size of the deleted value in the state storage quota available to the app:
import { stateClient } from '@dynatrace-sdk/client-state';
stateClient.deleteAppState({ key: 'weather' });
stateClient.deleteUserAppState({ key: 'favourite-hosts' });
This operation requires the scopes state:app-states:delete, state:user-app-states:delete
. Read more about scopes in this guide.
Delete all states
There are methods provided to delete all app states (deleteAppStates
) and user app states (deleteUserAppStates
) to make it easy to reset the states of the app completely:
import { stateClient } from '@dynatrace-sdk/client-state';
stateClient.deleteAppStates();
stateClient.deleteUserAppStates();
This operation requires the scopes state:app-states:delete, state:user-app-states:delete
. Read more about scopes in this guide.