Update notification and rate limit configurations for edge connectivity/failure events

This commit is contained in:
deaflynx 2024-01-23 13:47:20 +02:00
parent ad90b4480c
commit d98a8cd2fa
10 changed files with 105 additions and 42 deletions

View File

@ -32,7 +32,7 @@ public class EdgeConnectivityTriggerProcessor implements NotificationRuleTrigger
@Override @Override
public boolean matchesFilter(EdgeConnectivityTrigger trigger, EdgeConnectivityNotificationRuleTriggerConfig triggerConfig) { public boolean matchesFilter(EdgeConnectivityTrigger trigger, EdgeConnectivityNotificationRuleTriggerConfig triggerConfig) {
EdgeConnectivityEvent event = trigger.isConnected() ? EdgeConnectivityEvent.CONNECTED : EdgeConnectivityEvent.DISCONNECTED; EdgeConnectivityEvent event = trigger.isConnected() ? EdgeConnectivityEvent.CONNECTED : EdgeConnectivityEvent.DISCONNECTED;
if (!triggerConfig.getNotifyOn().contains(event)) { if (CollectionUtils.isEmpty(triggerConfig.getNotifyOn()) || !triggerConfig.getNotifyOn().contains(event)) {
return false; return false;
} }
if (CollectionUtils.isNotEmpty(triggerConfig.getEdges())) { if (CollectionUtils.isNotEmpty(triggerConfig.getEdges())) {

View File

@ -31,7 +31,6 @@ import java.util.UUID;
public class EdgeConnectivityNotificationRuleTriggerConfig implements NotificationRuleTriggerConfig { public class EdgeConnectivityNotificationRuleTriggerConfig implements NotificationRuleTriggerConfig {
private Set<UUID> edges; // if empty - all edges private Set<UUID> edges; // if empty - all edges
@NotEmpty
private Set<EdgeConnectivityEvent> notifyOn; private Set<EdgeConnectivityEvent> notifyOn;
@Override @Override

View File

@ -523,7 +523,7 @@
</mat-panel-description> </mat-panel-description>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<ng-template matExpansionPanelContent> <ng-template matExpansionPanelContent>
<div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px"> <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">
<tb-rate-limits fxFlex formControlName="transportTenantTelemetryDataPointsRateLimit" <tb-rate-limits fxFlex formControlName="transportTenantTelemetryDataPointsRateLimit"
[type]="rateLimitsType.TENANT_TELEMETRY_DATA_POINTS"> [type]="rateLimitsType.TENANT_TELEMETRY_DATA_POINTS">
</tb-rate-limits> </tb-rate-limits>
@ -531,7 +531,7 @@
[type]="rateLimitsType.DEVICE_TELEMETRY_DATA_POINTS"> [type]="rateLimitsType.DEVICE_TELEMETRY_DATA_POINTS">
</tb-rate-limits> </tb-rate-limits>
</div> </div>
<div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px"> <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">
<tb-rate-limits fxFlex formControlName="tenantServerRestLimitsConfiguration" <tb-rate-limits fxFlex formControlName="tenantServerRestLimitsConfiguration"
[type]="rateLimitsType.TENANT_SERVER_REST_LIMITS_CONFIGURATION"> [type]="rateLimitsType.TENANT_SERVER_REST_LIMITS_CONFIGURATION">
</tb-rate-limits> </tb-rate-limits>
@ -539,7 +539,7 @@
[type]="rateLimitsType.CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION"> [type]="rateLimitsType.CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION">
</tb-rate-limits> </tb-rate-limits>
</div> </div>
<div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px"> <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">
<tb-rate-limits fxFlex formControlName="tenantEntityExportRateLimit" <tb-rate-limits fxFlex formControlName="tenantEntityExportRateLimit"
[type]="rateLimitsType.TENANT_ENTITY_EXPORT_RATE_LIMIT"> [type]="rateLimitsType.TENANT_ENTITY_EXPORT_RATE_LIMIT">
</tb-rate-limits> </tb-rate-limits>
@ -547,7 +547,7 @@
[type]="rateLimitsType.TENANT_ENTITY_IMPORT_RATE_LIMIT"> [type]="rateLimitsType.TENANT_ENTITY_IMPORT_RATE_LIMIT">
</tb-rate-limits> </tb-rate-limits>
</div> </div>
<div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px"> <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">
<tb-rate-limits fxFlex formControlName="wsUpdatesPerSessionRateLimit" <tb-rate-limits fxFlex formControlName="wsUpdatesPerSessionRateLimit"
[type]="rateLimitsType.WS_UPDATE_PER_SESSION_RATE_LIMIT"> [type]="rateLimitsType.WS_UPDATE_PER_SESSION_RATE_LIMIT">
</tb-rate-limits> </tb-rate-limits>
@ -555,7 +555,7 @@
[type]="rateLimitsType.CASSANDRA_QUERY_TENANT_RATE_LIMITS_CONFIGURATION"> [type]="rateLimitsType.CASSANDRA_QUERY_TENANT_RATE_LIMITS_CONFIGURATION">
</tb-rate-limits> </tb-rate-limits>
</div> </div>
<div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px"> <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">
<tb-rate-limits fxFlex="50" formControlName="tenantNotificationRequestsRateLimit" <tb-rate-limits fxFlex="50" formControlName="tenantNotificationRequestsRateLimit"
[type]="rateLimitsType.TENANT_NOTIFICATION_REQUEST_RATE_LIMIT"> [type]="rateLimitsType.TENANT_NOTIFICATION_REQUEST_RATE_LIMIT">
</tb-rate-limits> </tb-rate-limits>
@ -563,6 +563,14 @@
[type]="rateLimitsType.TENANT_NOTIFICATION_REQUESTS_PER_RULE_RATE_LIMIT"> [type]="rateLimitsType.TENANT_NOTIFICATION_REQUESTS_PER_RULE_RATE_LIMIT">
</tb-rate-limits> </tb-rate-limits>
</div> </div>
<div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">
<tb-rate-limits fxFlex="50" formControlName="edgeEventRateLimits"
[type]="rateLimitsType.EDGE_EVENTS_RATE_LIMIT">
</tb-rate-limits>
<tb-rate-limits fxFlex="50" formControlName="edgeEventRateLimitsPerEdge"
[type]="rateLimitsType.EDGE_EVENTS_PER_EDGE_RATE_LIMIT">
</tb-rate-limits>
</div>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
</fieldset> </fieldset>

View File

@ -106,7 +106,9 @@ export class DefaultTenantProfileConfigurationComponent implements ControlValueA
maxWsSubscriptionsPerRegularUser: [null, [Validators.min(0)]], maxWsSubscriptionsPerRegularUser: [null, [Validators.min(0)]],
maxWsSubscriptionsPerPublicUser: [null, [Validators.min(0)]], maxWsSubscriptionsPerPublicUser: [null, [Validators.min(0)]],
wsUpdatesPerSessionRateLimit: [null, []], wsUpdatesPerSessionRateLimit: [null, []],
cassandraQueryTenantRateLimitsConfiguration: [null, []] cassandraQueryTenantRateLimitsConfiguration: [null, []],
edgeEventRateLimits: [null, []],
edgeEventRateLimitsPerEdge: [null, []]
}); });
this.defaultTenantProfileConfigurationFormGroup.get('smsEnabled').valueChanges.pipe( this.defaultTenantProfileConfigurationFormGroup.get('smsEnabled').valueChanges.pipe(

View File

@ -35,7 +35,9 @@ export enum RateLimitsType {
TENANT_ENTITY_EXPORT_RATE_LIMIT = 'TENANT_ENTITY_EXPORT_RATE_LIMIT', TENANT_ENTITY_EXPORT_RATE_LIMIT = 'TENANT_ENTITY_EXPORT_RATE_LIMIT',
TENANT_ENTITY_IMPORT_RATE_LIMIT = 'TENANT_ENTITY_IMPORT_RATE_LIMIT', TENANT_ENTITY_IMPORT_RATE_LIMIT = 'TENANT_ENTITY_IMPORT_RATE_LIMIT',
TENANT_NOTIFICATION_REQUEST_RATE_LIMIT = 'TENANT_NOTIFICATION_REQUEST_RATE_LIMIT', TENANT_NOTIFICATION_REQUEST_RATE_LIMIT = 'TENANT_NOTIFICATION_REQUEST_RATE_LIMIT',
TENANT_NOTIFICATION_REQUESTS_PER_RULE_RATE_LIMIT = 'TENANT_NOTIFICATION_REQUESTS_PER_RULE_RATE_LIMIT' TENANT_NOTIFICATION_REQUESTS_PER_RULE_RATE_LIMIT = 'TENANT_NOTIFICATION_REQUESTS_PER_RULE_RATE_LIMIT',
EDGE_EVENTS_RATE_LIMIT = 'EDGE_EVENTS_RATE_LIMIT',
EDGE_EVENTS_PER_EDGE_RATE_LIMIT = 'EDGE_EVENTS_PER_EDGE_RATE_LIMIT'
} }
export const rateLimitsLabelTranslationMap = new Map<RateLimitsType, string>( export const rateLimitsLabelTranslationMap = new Map<RateLimitsType, string>(
@ -54,6 +56,8 @@ export const rateLimitsLabelTranslationMap = new Map<RateLimitsType, string>(
[RateLimitsType.TENANT_ENTITY_IMPORT_RATE_LIMIT, 'tenant-profile.tenant-entity-import-rate-limit'], [RateLimitsType.TENANT_ENTITY_IMPORT_RATE_LIMIT, 'tenant-profile.tenant-entity-import-rate-limit'],
[RateLimitsType.TENANT_NOTIFICATION_REQUEST_RATE_LIMIT, 'tenant-profile.tenant-notification-request-rate-limit'], [RateLimitsType.TENANT_NOTIFICATION_REQUEST_RATE_LIMIT, 'tenant-profile.tenant-notification-request-rate-limit'],
[RateLimitsType.TENANT_NOTIFICATION_REQUESTS_PER_RULE_RATE_LIMIT, 'tenant-profile.tenant-notification-requests-per-rule-rate-limit'], [RateLimitsType.TENANT_NOTIFICATION_REQUESTS_PER_RULE_RATE_LIMIT, 'tenant-profile.tenant-notification-requests-per-rule-rate-limit'],
[RateLimitsType.EDGE_EVENTS_RATE_LIMIT, 'tenant-profile.rate-limits.edge-events-rate-limit'],
[RateLimitsType.EDGE_EVENTS_PER_EDGE_RATE_LIMIT, 'tenant-profile.rate-limits.edge-events-per-edge-rate-limit'],
] ]
); );
@ -73,6 +77,8 @@ export const rateLimitsDialogTitleTranslationMap = new Map<RateLimitsType, strin
[RateLimitsType.TENANT_ENTITY_IMPORT_RATE_LIMIT, 'tenant-profile.rate-limits.edit-tenant-entity-import-rate-limit-title'], [RateLimitsType.TENANT_ENTITY_IMPORT_RATE_LIMIT, 'tenant-profile.rate-limits.edit-tenant-entity-import-rate-limit-title'],
[RateLimitsType.TENANT_NOTIFICATION_REQUEST_RATE_LIMIT, 'tenant-profile.rate-limits.edit-tenant-notification-request-rate-limit-title'], [RateLimitsType.TENANT_NOTIFICATION_REQUEST_RATE_LIMIT, 'tenant-profile.rate-limits.edit-tenant-notification-request-rate-limit-title'],
[RateLimitsType.TENANT_NOTIFICATION_REQUESTS_PER_RULE_RATE_LIMIT, 'tenant-profile.rate-limits.edit-tenant-notification-requests-per-rule-rate-limit-title'], [RateLimitsType.TENANT_NOTIFICATION_REQUESTS_PER_RULE_RATE_LIMIT, 'tenant-profile.rate-limits.edit-tenant-notification-requests-per-rule-rate-limit-title'],
[RateLimitsType.EDGE_EVENTS_RATE_LIMIT, 'tenant-profile.rate-limits.edit-edge-events-rate-limit'],
[RateLimitsType.EDGE_EVENTS_PER_EDGE_RATE_LIMIT, 'tenant-profile.rate-limits.edit-edge-events-per-edge-rate-limit'],
] ]
); );

View File

@ -407,44 +407,58 @@
</section> </section>
</form> </form>
</mat-step> </mat-step>
<mat-step [stepControl]="edgeTemplateForm"
*ngIf="ruleNotificationForm.get('triggerType').value === triggerType.EDGE_FAILURE"> <mat-step [stepControl]="edgeConnectivityTemplateForm"
*ngIf="ruleNotificationForm.get('triggerType').value === triggerType.EDGE_CONNECTIVITY">
<ng-template matStepLabel>{{ 'notification.edge-trigger-settings' | translate }}</ng-template> <ng-template matStepLabel>{{ 'notification.edge-trigger-settings' | translate }}</ng-template>
<form [formGroup]="edgeTemplateForm"> <form [formGroup]="edgeConnectivityTemplateForm">
<section formGroupName="triggerConfig"> <section formGroupName="triggerConfig">
<fieldset class="fields-group tb-margin-before-field"> <fieldset class="fields-group tb-margin-before-field">
<legend translate>notification.filter</legend> <legend translate>notification.filter</legend>
<tb-string-items-list <tb-entity-list
editable formControlName="edges"
label="{{ 'alarm.alarm-type-list' | translate }}" subscriptSizing="dynamic"
placeholder="{{ !alarmTemplateForm.get('triggerConfig.alarmTypes').value?.length ? ('alarm.any-type' | translate) : '' }}" labelText="{{'edge.edge-instances' | translate}}"
floatLabel="always" placeholderText="{{ 'edge.edge-instances' | translate }}"
formControlName="alarmTypes"> hint="{{ 'notification.edge-list-rule-hint' | translate }}"
</tb-string-items-list> [entityType]="entityType.EDGE">
</tb-entity-list>
<mat-form-field fxFlex class="mat-block" floatLabel="always"> <mat-form-field fxFlex class="mat-block" floatLabel="always">
<mat-label translate>alarm.alarm-severity-list</mat-label> <mat-label translate>notification.notify-on</mat-label>
<mat-select formControlName="alarmSeverities" multiple <mat-select formControlName="notifyOn" multiple
placeholder="{{ !alarmTemplateForm.get('triggerConfig.alarmSeverities').value?.length ? ('alarm.any-severity' | translate) : '' }}"> placeholder="{{ !edgeConnectivityTemplateForm.get('triggerConfig.notifyOn').value?.length ? ('event.all-events' | translate) : '' }}">
<mat-option *ngFor="let alarmSeverity of alarmSeverities" [value]="alarmSeverity"> <mat-option *ngFor="let edgeEvent of edgeConnectivityEvents" [value]="edgeEvent">
{{ alarmSeverityTranslationMap.get(alarmSeverity) | translate }} {{ edgeConnectivityEventTranslationMap.get(edgeEvent) | translate }}
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
</fieldset> </fieldset>
<mat-form-field fxFlex class="mat-block"> </section>
<mat-label translate>notification.notify-on</mat-label> </form>
<mat-select formControlName="notifyOn" multiple> <form [formGroup]="ruleNotificationForm">
<mat-option *ngFor="let alarmAction of alarmActions" [value]="alarmAction"> <section formGroupName="additionalConfig">
{{ alarmActionTranslationMap.get(alarmAction) | translate }} <mat-form-field class="mat-block">
</mat-option> <mat-label translate>notification.description</mat-label>
</mat-select> <input matInput formControlName="description">
<mat-error *ngIf="alarmTemplateForm.get('triggerConfig.notifyOn').hasError('required')">
{{ 'notification.notify-on-required' | translate }}
</mat-error>
</mat-form-field> </mat-form-field>
</section> </section>
</form> </form>
</mat-step>
<mat-step [stepControl]="edgeFailureTemplateForm"
*ngIf="ruleNotificationForm.get('triggerType').value === triggerType.EDGE_FAILURE">
<ng-template matStepLabel>{{ 'notification.edge-trigger-settings' | translate }}</ng-template>
<form [formGroup]="edgeFailureTemplateForm">
<section formGroupName="triggerConfig">
<fieldset class="fields-group tb-margin-before-field">
<legend translate>notification.filter</legend>
<tb-entity-list labelText="{{'edge.edge-instances' | translate}}"
[entityType]="entityType.EDGE"
formControlName="edges">
</tb-entity-list>
</fieldset>
</section>
</form>
<form [formGroup]="ruleNotificationForm"> <form [formGroup]="ruleNotificationForm">
<section formGroupName="additionalConfig"> <section formGroupName="additionalConfig">
<mat-form-field class="mat-block"> <mat-form-field class="mat-block">

View File

@ -68,6 +68,7 @@ import {
} from '@shared/models/api-usage.models'; } from '@shared/models/api-usage.models';
import { LimitedApi, LimitedApiTranslationMap } from '@shared/models/limited-api.models'; import { LimitedApi, LimitedApiTranslationMap } from '@shared/models/limited-api.models';
import { StringItemsOption } from '@shared/components/string-items-list.component'; import { StringItemsOption } from '@shared/components/string-items-list.component';
import { EdgeConnectivityEvent, EdgeConnectivityEventTranslationMap } from '@shared/models/edge.models';
export interface RuleNotificationDialogData { export interface RuleNotificationDialogData {
rule?: NotificationRule; rule?: NotificationRule;
@ -98,7 +99,8 @@ export class RuleNotificationDialogComponent extends
apiUsageLimitTemplateForm: FormGroup; apiUsageLimitTemplateForm: FormGroup;
newPlatformVersionTemplateForm: FormGroup; newPlatformVersionTemplateForm: FormGroup;
rateLimitsTemplateForm: FormGroup; rateLimitsTemplateForm: FormGroup;
edgeTemplateForm: FormGroup; edgeFailureTemplateForm: FormGroup;
edgeConnectivityTemplateForm: FormGroup;
triggerType = TriggerType; triggerType = TriggerType;
triggerTypes: TriggerType[]; triggerTypes: TriggerType[];
@ -133,6 +135,9 @@ export class RuleNotificationDialogComponent extends
apiFeatures: ApiFeature[] = Object.values(ApiFeature); apiFeatures: ApiFeature[] = Object.values(ApiFeature);
apiFeatureTranslationMap = ApiFeatureTranslationMap; apiFeatureTranslationMap = ApiFeatureTranslationMap;
edgeConnectivityEvents: EdgeConnectivityEvent[] = Object.values(EdgeConnectivityEvent);
edgeConnectivityEventTranslationMap = EdgeConnectivityEventTranslationMap;
limitedApis: StringItemsOption[]; limitedApis: StringItemsOption[];
entityType = EntityType; entityType = EntityType;
@ -222,11 +227,18 @@ export class RuleNotificationDialogComponent extends
} }
}); });
this.edgeTemplateForm = this.fb.group({ this.edgeConnectivityTemplateForm = this.fb.group({
triggerConfig: this.fb.group({ triggerConfig: this.fb.group({
edges: [null],
notifyOn: [null]
}) })
} });
);
this.edgeFailureTemplateForm = this.fb.group({
triggerConfig: this.fb.group({
edges: [null]
})
});
this.alarmTemplateForm = this.fb.group({ this.alarmTemplateForm = this.fb.group({
triggerConfig: this.fb.group({ triggerConfig: this.fb.group({
@ -335,7 +347,9 @@ export class RuleNotificationDialogComponent extends
[TriggerType.ENTITIES_LIMIT, this.entitiesLimitTemplateForm], [TriggerType.ENTITIES_LIMIT, this.entitiesLimitTemplateForm],
[TriggerType.API_USAGE_LIMIT, this.apiUsageLimitTemplateForm], [TriggerType.API_USAGE_LIMIT, this.apiUsageLimitTemplateForm],
[TriggerType.NEW_PLATFORM_VERSION, this.newPlatformVersionTemplateForm], [TriggerType.NEW_PLATFORM_VERSION, this.newPlatformVersionTemplateForm],
[TriggerType.RATE_LIMITS, this.rateLimitsTemplateForm] [TriggerType.RATE_LIMITS, this.rateLimitsTemplateForm],
[TriggerType.EDGE_FAILURE, this.edgeFailureTemplateForm],
[TriggerType.EDGE_CONNECTIVITY, this.edgeConnectivityTemplateForm]
]); ]);
if (data.isAdd || data.isCopy) { if (data.isAdd || data.isCopy) {

View File

@ -190,3 +190,15 @@ export enum EdgeInstructionsMethod {
} }
export const edgeVersionAttributeKey = 'edgeVersion'; export const edgeVersionAttributeKey = 'edgeVersion';
export enum EdgeConnectivityEvent {
CONNECTED= 'CONNECTED',
DISCONNECTED = 'DISCONNECTED'
}
export const EdgeConnectivityEventTranslationMap = new Map<EdgeConnectivityEvent, string>(
[
[EdgeConnectivityEvent.CONNECTED, 'edge-event.connected'],
[EdgeConnectivityEvent.DISCONNECTED, 'edge-event.disconnected']
]
);

View File

@ -2073,7 +2073,9 @@
"action-type-assigned-to-edge": "Assigned to Edge", "action-type-assigned-to-edge": "Assigned to Edge",
"action-type-unassigned-from-edge": "Unassigned from Edge", "action-type-unassigned-from-edge": "Unassigned from Edge",
"action-type-credentials-request": "Credentials Request", "action-type-credentials-request": "Credentials Request",
"action-type-entity-merge-request": "Entity Merge Request" "action-type-entity-merge-request": "Entity Merge Request",
"connected": "Connected",
"disconnected": "Disconnected"
}, },
"error": { "error": {
"unable-to-connect": "Unable to connect to the server! Please check your internet connection.", "unable-to-connect": "Unable to connect to the server! Please check your internet connection.",
@ -3282,6 +3284,7 @@
"device-profiles-list-rule-hint": "If the field is empty, the trigger will be applied to all device profiles", "device-profiles-list-rule-hint": "If the field is empty, the trigger will be applied to all device profiles",
"disabled": "Disabled", "disabled": "Disabled",
"edge-trigger-settings": "Edge trigger settings", "edge-trigger-settings": "Edge trigger settings",
"edge-list-rule-hint": "If the field is empty, the trigger will be applied to all edge instances",
"edit-notification-recipients-group": "Edit notification recipients group", "edit-notification-recipients-group": "Edit notification recipients group",
"edit-notification-template": "Edit notification template", "edit-notification-template": "Edit notification template",
"edit-rule": "Edit rule", "edit-rule": "Edit rule",
@ -3427,7 +3430,8 @@
"rule-node": "Rule node", "rule-node": "Rule node",
"new-platform-version": "New platform version", "new-platform-version": "New platform version",
"rate-limits": "Exceeded rate limits", "rate-limits": "Exceeded rate limits",
"edge": "Edge" "edge-failure": "Edge error",
"edge-connectivity": "Edge connectivity"
}, },
"templates": "Templates", "templates": "Templates",
"notification-templates": "Notifications / Templates", "notification-templates": "Notifications / Templates",
@ -4173,6 +4177,10 @@
"edit-tenant-entity-import-rate-limit-title": "Edit entity version load rate limits", "edit-tenant-entity-import-rate-limit-title": "Edit entity version load rate limits",
"edit-tenant-notification-request-rate-limit-title": "Edit notification requests rate limits", "edit-tenant-notification-request-rate-limit-title": "Edit notification requests rate limits",
"edit-tenant-notification-requests-per-rule-rate-limit-title": "Edit notification requests per notification rule rate limits", "edit-tenant-notification-requests-per-rule-rate-limit-title": "Edit notification requests per notification rule rate limits",
"edit-edge-events-rate-limit": "Edit edge events rate limits",
"edit-edge-events-per-edge-rate-limit": "Edit edge events per edge rate limits",
"edge-events-rate-limit": "Edge events",
"edge-events-per-edge-rate-limit": "Edge events per edge",
"messages-per": "messages per", "messages-per": "messages per",
"not-set": "Not set", "not-set": "Not set",
"number-of-messages": "Number of messages", "number-of-messages": "Number of messages",