Browse Source

UI: Add Produce intermediate result to entity aggregation

pull/14474/head
Vladyslav_Prykhodko 9 months ago
parent
commit
5649a4c626
  1. 1
      ui-ngx/src/app/core/auth/auth.models.ts
  2. 1
      ui-ngx/src/app/core/auth/auth.reducer.ts
  3. 9
      ui-ngx/src/app/modules/home/components/calculated-fields/components/entity-aggregation-configuration/entity-aggregation-component.component.html
  4. 54
      ui-ngx/src/app/modules/home/components/calculated-fields/components/entity-aggregation-configuration/entity-aggregation-component.component.ts
  5. 44
      ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html
  6. 3
      ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts
  7. 1
      ui-ngx/src/app/shared/models/calculated-field.models.ts
  8. 7
      ui-ngx/src/app/shared/models/tenant.model.ts
  9. 13
      ui-ngx/src/assets/locale/locale.constant-en_US.json

1
ui-ngx/src/app/core/auth/auth.models.ts

@ -37,6 +37,7 @@ export interface SysParamsState {
maxRelationLevelPerCfArgument: number;
ruleChainDebugPerTenantLimitsConfiguration?: string;
calculatedFieldDebugPerTenantLimitsConfiguration?: string;
intermediateAggregationIntervalInSecForCF: number;
trendzSettings: TrendzSettings;
}

1
ui-ngx/src/app/core/auth/auth.reducer.ts

@ -39,6 +39,7 @@ const emptyUserAuthState: AuthPayload = {
maxRelationLevelPerCfArgument: 0,
maxDataPointsPerRollingArg: 0,
maxDebugModeDurationMinutes: 0,
intermediateAggregationIntervalInSecForCF: 0,
userSettings: initialUserSettings,
trendzSettings: initialTrendzSettings
};

9
ui-ngx/src/app/modules/home/components/calculated-fields/components/entity-aggregation-configuration/entity-aggregation-component.component.html

@ -124,6 +124,15 @@
</ng-container>
}
</div>
<div class="tb-form-panel stroked">
<mat-slide-toggle class="mat-slide flex" formControlName="produceIntermediateResult">
<div tb-hint-tooltip-icon="{{ 'calculated-fields.entity-aggregation.produce-intermediate-result-hint' | translate: {
time: (intermediateAggregationIntervalInSecForCF * 1000 | milliSecondsToTimeString )
} }}">
{{ 'calculated-fields.entity-aggregation.produce-intermediate-result' | translate }}
</div>
</mat-slide-toggle>
</div>
</div>
<tb-calculate-field-output formControlName="output"
containerInputClass="grid items-start grid-cols-2 gap-3 xs:grid-cols-1"

54
ui-ngx/src/app/modules/home/components/calculated-fields/components/entity-aggregation-configuration/entity-aggregation-component.component.ts

@ -37,7 +37,7 @@ import {
} from '@shared/models/calculated-field.models';
import { filter, map } from 'rxjs/operators';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { AVG_MONTH, AVG_QUARTER, DAY, HOUR, MINUTE, SECOND, YEAR } from '@shared/models/time/time.models';
import { AVG_MONTH, AVG_QUARTER, DAY, HOUR, MINUTE, SECOND, WEEK, YEAR } from '@shared/models/time/time.models';
import { deepClone, isDefinedAndNotNull } from '@core/utils';
import { getCurrentAuthState } from '@core/auth/auth.selectors';
import { Store } from '@ngrx/store';
@ -88,6 +88,7 @@ export class EntityAggregationComponentComponent implements ControlValueAccessor
@Input() testScript: (expression?: string) => Observable<string>;
readonly minAllowedAggregationIntervalInSecForCF = getCurrentAuthState(this.store).minAllowedAggregationIntervalInSecForCF;
readonly intermediateAggregationIntervalInSecForCF = getCurrentAuthState(this.store).intermediateAggregationIntervalInSecForCF;
readonly DayInSec = DAY / SECOND;
entityAggregationConfiguration = this.fb.group({
@ -104,6 +105,7 @@ export class EntityAggregationComponentComponent implements ControlValueAccessor
watermark: this.fb.group({
duration: [HOUR/SECOND, Validators.required],
}),
produceIntermediateResult: [false],
output: this.fb.control<CalculatedFieldOutput>(defaultCalculatedFieldOutput),
});
@ -153,6 +155,15 @@ export class EntityAggregationComponentComponent implements ControlValueAccessor
this.updatedOffsetHint();
});
merge(
this.entityAggregationConfiguration.get('interval.type').valueChanges,
this.entityAggregationConfiguration.get('interval.durationSec').valueChanges
).pipe(
takeUntilDestroyed()
).subscribe(() => {
this.checkProduceIntermediate();
});
this.entityAggregationConfiguration.valueChanges.pipe(
takeUntilDestroyed()
).subscribe((value: CalculatedFieldEntityAggregationConfigurationValue) => {
@ -174,6 +185,7 @@ export class EntityAggregationComponentComponent implements ControlValueAccessor
this.checkAggIntervalType(this.entityAggregationConfiguration.get('interval.type').value);
this.checkIntervalDuration(this.entityAggregationConfiguration.get('interval.allowOffsetSec').value);
this.checkWatermark(this.entityAggregationConfiguration.get('allowWatermark').value);
this.checkProduceIntermediate();
this.updatedOffsetHint();
setTimeout(() => {
this.entityAggregationConfiguration.get('arguments').updateValueAndValidity({onlySelf: true});
@ -194,6 +206,7 @@ export class EntityAggregationComponentComponent implements ControlValueAccessor
this.checkAggIntervalType(this.entityAggregationConfiguration.get('interval.type').value);
this.checkIntervalDuration(this.entityAggregationConfiguration.get('interval.allowOffsetSec').value);
this.checkWatermark(this.entityAggregationConfiguration.get('allowWatermark').value);
this.checkProduceIntermediate();
}
}
@ -255,16 +268,49 @@ export class EntityAggregationComponentComponent implements ControlValueAccessor
}
}
private checkProduceIntermediate() {
const intervalType = this.entityAggregationConfiguration.get('interval.type').value as AggIntervalType;
let durationSec = 0;
switch (intervalType) {
case AggIntervalType.CUSTOM:
durationSec = this.entityAggregationConfiguration.get('interval.durationSec').value;
break
case AggIntervalType.HOUR:
durationSec = HOUR / SECOND;
break
case AggIntervalType.DAY:
durationSec = DAY / SECOND;
break
case AggIntervalType.WEEK:
case AggIntervalType.WEEK_SUN_SAT:
durationSec = WEEK / SECOND;
break
case AggIntervalType.MONTH:
durationSec = AVG_MONTH / SECOND;
break
case AggIntervalType.QUARTER:
durationSec = AVG_QUARTER / SECOND;
break
case AggIntervalType.YEAR:
durationSec = YEAR / SECOND;
break
}
if (durationSec > this.intermediateAggregationIntervalInSecForCF) {
this.entityAggregationConfiguration.get('produceIntermediateResult').enable({emitEvent: false});
} else {
this.entityAggregationConfiguration.get('produceIntermediateResult').disable({emitEvent: false});
}
}
private updatedOffsetHint(): void {
const offset = this.entityAggregationConfiguration.get('interval.offsetSec').value;
const intervalType = this.entityAggregationConfiguration.get('interval.type').value as AggIntervalType;
const durationSec = this.entityAggregationConfiguration.get('interval.durationSec').value;
const offsetCategory = this.getTimeCategory(offset);
const now = _moment.utc();
let interval: string = '';
let interval: string;
if (intervalType === AggIntervalType.CUSTOM) {
const durationSecCategory = this.getTimeCategory(durationSec);
const formatString = this.getCustomFormatString(offsetCategory, durationSecCategory);
const formatString = this.getCustomFormatString(offsetCategory, this.getTimeCategory(durationSec));
const intervals: string[] = [];
let allInterval = durationSec >= HOUR*6/SECOND && durationSec < DAY/SECOND;
now.startOf('year').add(offset, 'seconds');

44
ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html

@ -368,6 +368,34 @@
<mat-hint></mat-hint>
</mat-form-field>
</div>
<div class="flex flex-1 flex-row xs:flex-col gt-xs:gap-4">
<mat-form-field class="mat-block flex-1" appearance="fill" subscriptSizing="dynamic">
<mat-label translate>tenant-profile.intermediate-aggregation-interval</mat-label>
<input matInput required min="0" step="1"
formControlName="intermediateAggregationIntervalInSecForCF"
type="number">
<mat-error *ngIf="tenantProfileConfigurationForm.get('intermediateAggregationIntervalInSecForCF').hasError('required')">
{{ 'tenant-profile.intermediate-aggregation-interval-required' | translate}}
</mat-error>
<mat-error *ngIf="tenantProfileConfigurationForm.get('intermediateAggregationIntervalInSecForCF').hasError('min')">
{{ 'tenant-profile.intermediate-aggregation-interval-range' | translate}}
</mat-error>
<mat-hint></mat-hint>
</mat-form-field>
<mat-form-field class="mat-block flex-1" appearance="fill" subscriptSizing="dynamic">
<mat-label translate>tenant-profile.reevaluation-check-interval</mat-label>
<input matInput required min="0" step="1"
formControlName="cfReevaluationCheckInterval"
type="number">
<mat-error *ngIf="tenantProfileConfigurationForm.get('cfReevaluationCheckInterval').hasError('required')">
{{ 'tenant-profile.reevaluation-check-interval-required' | translate}}
</mat-error>
<mat-error *ngIf="tenantProfileConfigurationForm.get('cfReevaluationCheckInterval').hasError('min')">
{{ 'tenant-profile.reevaluation-check-interval-range' | translate}}
</mat-error>
<mat-hint></mat-hint>
</mat-form-field>
</div>
<div class="flex flex-1 flex-row xs:flex-col gt-xs:gap-4">
<mat-form-field class="mat-block flex-1" appearance="fill" subscriptSizing="dynamic">
<mat-label translate>tenant-profile.relation-search-entity-limit</mat-label>
@ -526,6 +554,22 @@
<mat-hint></mat-hint>
</mat-form-field>
</div>
<div class="fields-element flex flex-1 flex-row xs:flex-col gt-xs:gap-4">
<mat-form-field class="mat-block flex-1" appearance="fill" subscriptSizing="dynamic">
<mat-label translate>tenant-profile.alarms-reevaluation-interval</mat-label>
<input matInput required min="0" step="1"
formControlName="alarmsReevaluationInterval"
type="number">
<mat-error *ngIf="tenantProfileConfigurationForm.get('alarmsReevaluationInterval').hasError('required')">
{{ 'tenant-profile.alarms-reevaluation-interval-required' | translate}}
</mat-error>
<mat-error *ngIf="tenantProfileConfigurationForm.get('alarmsReevaluationInterval').hasError('min')">
{{ 'tenant-profile.alarms-reevaluation-interval-range' | translate}}
</mat-error>
<mat-hint></mat-hint>
</mat-form-field>
<div class="flex-1"></div>
</div>
</fieldset>
<fieldset class="fields-group">

3
ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts

@ -120,6 +120,9 @@ export class DefaultTenantProfileConfigurationComponent implements ControlValueA
minAllowedAggregationIntervalInSecForCF: [0, [Validators.required, Validators.min(0)]],
maxRelatedEntitiesToReturnPerCfArgument: [1, [Validators.required, Validators.min(1)]],
minAllowedScheduledUpdateIntervalInSecForCF: [0, [Validators.required, Validators.min(0)]],
intermediateAggregationIntervalInSecForCF: [0, [Validators.required, Validators.min(1)]],
cfReevaluationCheckInterval: [0, [Validators.required, Validators.min(1)]],
alarmsReevaluationInterval: [0, [Validators.required, Validators.min(1)]],
maxDataPointsPerRollingArg: [0, [Validators.required, Validators.min(0)]],
maxStateSizeInKBytes: [0, [Validators.required, Validators.min(0)]],
calculatedFieldDebugEventsRateLimit: [''],

1
ui-ngx/src/app/shared/models/calculated-field.models.ts

@ -168,6 +168,7 @@ export interface CalculatedFieldEntityAggregationConfiguration {
metrics: Record<string, CalculatedFieldAggMetric>;
interval: AggInterval;
watermark?: WatermarkConfig;
produceIntermediateResult?: boolean;
output: CalculatedFieldOutput & { decimalsByDefault?: number; };
}

7
ui-ngx/src/app/shared/models/tenant.model.ts

@ -111,6 +111,10 @@ export interface DefaultTenantProfileConfiguration {
minAllowedAggregationIntervalInSecForCF: number;
maxRelatedEntitiesToReturnPerCfArgument: number;
minAllowedScheduledUpdateIntervalInSecForCF: number;
intermediateAggregationIntervalInSecForCF: number;
cfReevaluationCheckInterval: number;
alarmsReevaluationInterval: number;
maxDataPointsPerRollingArg: number;
maxStateSizeInKBytes: number;
maxSingleValueArgumentSizeInKBytes: number;
@ -180,6 +184,9 @@ export function createTenantProfileConfiguration(type: TenantProfileType): Tenan
minAllowedAggregationIntervalInSecForCF: 60,
maxRelatedEntitiesToReturnPerCfArgument: 100,
minAllowedScheduledUpdateIntervalInSecForCF: 0,
intermediateAggregationIntervalInSecForCF: 300,
cfReevaluationCheckInterval: 60,
alarmsReevaluationInterval: 60,
maxStateSizeInKBytes: 32,
maxSingleValueArgumentSizeInKBytes: 2,
calculatedFieldDebugEventsRateLimit: ''

13
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -1316,7 +1316,9 @@
"duration": "Duration",
"duration-required": "Duration is required",
"duration-min": "Duration should be at least 1 minute",
"duration-hint": "How long to wait for delayed data after the interval ends"
"duration-hint": "How long to wait for delayed data after the interval ends",
"produce-intermediate-result": "Produce intermediate result",
"produce-intermediate-result-hint": "Calculates metrics during the current interval to produce an intermediate result. Updates occur no more often than once every {{ time }}."
},
"hint": {
"arguments-simple-with-rolling": "Simple type calculated field should not contain keys with time series rolling type.",
@ -6273,6 +6275,15 @@
"min-allowed-deduplication-interval": "Min allowed deduplication interval (seconds)",
"min-allowed-deduplication-interval-range": "Min allowed deduplication interval value can't be negative",
"min-allowed-deduplication-interval-required": "Min allowed deduplication interval is required",
"intermediate-aggregation-interval": "Intermediate aggregation interval (seconds)",
"intermediate-aggregation-interval-range": "Intermediate aggregation interval value can't be less than '1'",
"intermediate-aggregation-interval-required": "Intermediate aggregation interval is required",
"reevaluation-check-interval": "Reevaluation check interval (seconds)",
"reevaluation-check-interval-range": "Reevaluation check interval value can't be less than '1'",
"reevaluation-check-interval-required": "Reevaluation check interval is required",
"alarms-reevaluation-interval": "Alarms reevaluation interval (seconds)",
"alarms-reevaluation-interval-range": "Alarms reevaluation interval value can't be less than '1'",
"alarms-reevaluation-interval-required": "Alarms reevaluation interval is required",
"min-allowed-aggregation-interval": "Min allowed aggregation interval (seconds)",
"min-allowed-aggregation-interval-range": "Min allowed aggregation interval value can't be negative",
"min-allowed-aggregation-interval-required": "Min allowed aggregation interval is required",

Loading…
Cancel
Save