Skip to content

Commit b483fd4

Browse files
feat: [SRM-11160]: Added SLO Disabling feature (#36006)
* [CVS-11160]: Added LastUpdatedAt, Added Migration for LastDisabledAt, Added disabled minute function, Added enabled status check * [CVS-11160]: Added service for entity disabled time, Added test for get graph with disabled data * [CVS-11160]: fixed failing tests * [CVS-11160]: Added changes for review comments * [CVS-11160]: added index in entitydisabledtime
1 parent 99a70f0 commit b483fd4

21 files changed

Lines changed: 509 additions & 45 deletions

300-cv-nextgen/src/main/java/io/harness/cvng/CVServiceModule.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@
122122
import io.harness.cvng.core.services.api.DebugService;
123123
import io.harness.cvng.core.services.api.DeleteEntityByHandler;
124124
import io.harness.cvng.core.services.api.DynatraceService;
125+
import io.harness.cvng.core.services.api.EntityDisabledTimeService;
125126
import io.harness.cvng.core.services.api.ExecutionLogService;
126127
import io.harness.cvng.core.services.api.FeatureFlagService;
127128
import io.harness.cvng.core.services.api.HostRecordService;
@@ -168,6 +169,7 @@
168169
import io.harness.cvng.core.services.impl.DefaultDeleteEntityByHandler;
169170
import io.harness.cvng.core.services.impl.DynatraceDataCollectionInfoMapper;
170171
import io.harness.cvng.core.services.impl.DynatraceServiceImpl;
172+
import io.harness.cvng.core.services.impl.EntityDisabledTimeServiceImpl;
171173
import io.harness.cvng.core.services.impl.ErrorTrackingDataCollectionInfoMapper;
172174
import io.harness.cvng.core.services.impl.ExecutionLogServiceImpl;
173175
import io.harness.cvng.core.services.impl.FeatureFlagServiceImpl;
@@ -698,6 +700,7 @@ public WaiterConfiguration waiterConfiguration() {
698700
bind(SumoLogicService.class).to(SumoLogicServiceImpl.class);
699701
bind(HealthSourceService.class).to(HealthSourceServiceImpl.class);
700702
bind(MonitoredServiceService.class).to(MonitoredServiceServiceImpl.class);
703+
bind(EntityDisabledTimeService.class).to(EntityDisabledTimeServiceImpl.class);
701704
bind(ServiceDependencyService.class).to(ServiceDependencyServiceImpl.class);
702705
bind(ServiceDependencyGraphService.class).to(ServiceDependencyGraphServiceImpl.class);
703706
bind(SetupUsageEventService.class).to(SetupUsageEventServiceImpl.class);
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright 2022 Harness Inc. All rights reserved.
3+
* Use of this source code is governed by the PolyForm Free Trial 1.0.0 license
4+
* that can be found in the licenses directory at the root of this repository, also available at
5+
* https://polyformproject.org/wp-content/uploads/2020/05/PolyForm-Free-Trial-1.0.0.txt.
6+
*/
7+
8+
package io.harness.cvng.core.entities;
9+
10+
import io.harness.annotation.HarnessEntity;
11+
import io.harness.annotation.StoreIn;
12+
import io.harness.annotations.dev.HarnessTeam;
13+
import io.harness.annotations.dev.OwnedBy;
14+
import io.harness.mongo.index.CompoundMongoIndex;
15+
import io.harness.mongo.index.FdIndex;
16+
import io.harness.mongo.index.MongoIndex;
17+
import io.harness.ng.DbAliases;
18+
import io.harness.persistence.AccountAccess;
19+
import io.harness.persistence.CreatedAtAware;
20+
import io.harness.persistence.PersistentEntity;
21+
import io.harness.persistence.UpdatedAtAware;
22+
import io.harness.persistence.UuidAware;
23+
24+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
25+
import com.google.common.collect.ImmutableList;
26+
import java.util.List;
27+
import lombok.Data;
28+
import lombok.EqualsAndHashCode;
29+
import lombok.NoArgsConstructor;
30+
import lombok.experimental.FieldNameConstants;
31+
import lombok.experimental.SuperBuilder;
32+
import org.mongodb.morphia.annotations.Entity;
33+
import org.mongodb.morphia.annotations.Id;
34+
35+
@Data
36+
@SuperBuilder
37+
@FieldNameConstants(innerTypeName = "EntityDisabledTimeKeys")
38+
@JsonIgnoreProperties(ignoreUnknown = true)
39+
@NoArgsConstructor
40+
@EqualsAndHashCode(callSuper = false)
41+
@Entity(value = "entityDisabledTime", noClassnameStored = true)
42+
@HarnessEntity(exportable = true)
43+
@OwnedBy(HarnessTeam.CV)
44+
@StoreIn(DbAliases.CVNG)
45+
public class EntityDisableTime implements PersistentEntity, UuidAware, AccountAccess, UpdatedAtAware, CreatedAtAware {
46+
@Id private String uuid;
47+
@FdIndex String entityUUID;
48+
@FdIndex String accountId;
49+
Long startTime;
50+
Long endTime;
51+
private long lastUpdatedAt;
52+
private long createdAt;
53+
public boolean contains(long time) {
54+
return time >= startTime && time <= endTime;
55+
}
56+
57+
public static List<MongoIndex> mongoIndexes() {
58+
return ImmutableList.<MongoIndex>builder()
59+
.add(CompoundMongoIndex.builder()
60+
.name("unique_query_idx")
61+
.unique(true)
62+
.field(EntityDisabledTimeKeys.entityUUID)
63+
.field(EntityDisabledTimeKeys.startTime)
64+
.field(EntityDisabledTimeKeys.endTime)
65+
.build())
66+
.build();
67+
}
68+
}

300-cv-nextgen/src/main/java/io/harness/cvng/core/entities/MonitoredService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public static List<MongoIndex> mongoIndexes() {
8383
private long lastUpdatedAt;
8484
private long createdAt;
8585
private boolean enabled;
86+
private long lastDisabledAt;
8687
List<NotificationRuleRef> notificationRuleRefs;
8788
@FdIndex private long nextNotificationIteration;
8889
String templateIdentifier;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright 2022 Harness Inc. All rights reserved.
3+
* Use of this source code is governed by the PolyForm Free Trial 1.0.0 license
4+
* that can be found in the licenses directory at the root of this repository, also available at
5+
* https://polyformproject.org/wp-content/uploads/2020/05/PolyForm-Free-Trial-1.0.0.txt.
6+
*/
7+
8+
package io.harness.cvng.core.services.api;
9+
10+
import io.harness.cvng.core.entities.EntityDisableTime;
11+
12+
import java.util.List;
13+
14+
public interface EntityDisabledTimeService {
15+
void save(EntityDisableTime entityDisableTime);
16+
17+
List<EntityDisableTime> get(String entityId, String accountId);
18+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2022 Harness Inc. All rights reserved.
3+
* Use of this source code is governed by the PolyForm Free Trial 1.0.0 license
4+
* that can be found in the licenses directory at the root of this repository, also available at
5+
* https://polyformproject.org/wp-content/uploads/2020/05/PolyForm-Free-Trial-1.0.0.txt.
6+
*/
7+
8+
package io.harness.cvng.core.services.impl;
9+
10+
import static io.harness.persistence.HQuery.excludeAuthorityCount;
11+
12+
import io.harness.cvng.core.entities.EntityDisableTime;
13+
import io.harness.cvng.core.services.api.EntityDisabledTimeService;
14+
import io.harness.persistence.HPersistence;
15+
16+
import com.google.inject.Inject;
17+
import java.util.List;
18+
import lombok.extern.slf4j.Slf4j;
19+
import org.mongodb.morphia.query.Sort;
20+
21+
@Slf4j
22+
public class EntityDisabledTimeServiceImpl implements EntityDisabledTimeService {
23+
@Inject private HPersistence hPersistence;
24+
25+
@Override
26+
public void save(EntityDisableTime entityDisableTime) {
27+
hPersistence.save(entityDisableTime);
28+
}
29+
30+
@Override
31+
public List<EntityDisableTime> get(String entityId, String accountId) {
32+
return hPersistence.createQuery(EntityDisableTime.class, excludeAuthorityCount)
33+
.filter(EntityDisableTime.EntityDisabledTimeKeys.entityUUID, entityId)
34+
.filter(EntityDisableTime.EntityDisabledTimeKeys.accountId, accountId)
35+
.order(Sort.ascending(EntityDisableTime.EntityDisabledTimeKeys.startTime))
36+
.asList();
37+
}
38+
}

300-cv-nextgen/src/main/java/io/harness/cvng/core/services/impl/monitoredService/MonitoredServiceServiceImpl.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,13 @@
6262
import io.harness.cvng.core.beans.params.logsFilterParams.LiveMonitoringLogsFilter;
6363
import io.harness.cvng.core.beans.template.TemplateDTO;
6464
import io.harness.cvng.core.entities.CVConfig;
65+
import io.harness.cvng.core.entities.EntityDisableTime;
6566
import io.harness.cvng.core.entities.MonitoredService;
6667
import io.harness.cvng.core.entities.MonitoredService.MonitoredServiceKeys;
6768
import io.harness.cvng.core.handler.monitoredService.BaseMonitoredServiceHandler;
6869
import io.harness.cvng.core.services.api.CVConfigService;
6970
import io.harness.cvng.core.services.api.CVNGLogService;
71+
import io.harness.cvng.core.services.api.EntityDisabledTimeService;
7072
import io.harness.cvng.core.services.api.FeatureFlagService;
7173
import io.harness.cvng.core.services.api.SetupUsageEventService;
7274
import io.harness.cvng.core.services.api.VerificationTaskService;
@@ -101,7 +103,6 @@
101103
import io.harness.cvng.notification.services.api.NotificationRuleTemplateDataGenerator.NotificationData;
102104
import io.harness.cvng.servicelevelobjective.entities.SLOHealthIndicator;
103105
import io.harness.cvng.servicelevelobjective.entities.ServiceLevelObjective;
104-
import io.harness.cvng.servicelevelobjective.services.api.SLODashboardService;
105106
import io.harness.cvng.servicelevelobjective.services.api.SLOHealthIndicatorService;
106107
import io.harness.cvng.servicelevelobjective.services.api.ServiceLevelIndicatorService;
107108
import io.harness.cvng.servicelevelobjective.services.api.ServiceLevelObjectiveService;
@@ -199,7 +200,6 @@ public class MonitoredServiceServiceImpl implements MonitoredServiceService {
199200
@Inject private CVNGLogService cvngLogService;
200201
@Inject private NotificationRuleService notificationRuleService;
201202
@Inject private TemplateFacade templateFacade;
202-
@Inject private SLODashboardService sloDashboardService;
203203
@Inject private ServiceLevelObjectiveService serviceLevelObjectiveService;
204204
@Inject private NotificationClient notificationClient;
205205
@Inject private ActivityService activityService;
@@ -211,6 +211,8 @@ public class MonitoredServiceServiceImpl implements MonitoredServiceService {
211211
private Map<NotificationRuleConditionType, NotificationRuleTemplateDataGenerator>
212212
notificationRuleConditionTypeTemplateDataGeneratorMap;
213213

214+
@Inject private EntityDisabledTimeService entityDisabledTimeService;
215+
214216
@Override
215217
public MonitoredServiceResponse create(String accountId, MonitoredServiceDTO monitoredServiceDTO) {
216218
ServiceEnvironmentParams environmentParams = ServiceEnvironmentParams.builder()
@@ -881,6 +883,7 @@ private void saveMonitoredServiceEntity(ProjectParams projectParams, MonitoredSe
881883
.type(monitoredServiceDTO.getType())
882884
// SRM-10798: enabled should come from monitoredServiceDTO
883885
.enabled(monitoredServiceDTO.isEnabled())
886+
.lastDisabledAt(clock.millis())
884887
.tags(TagMapper.convertToList(monitoredServiceDTO.getTags()))
885888
.notificationRuleRefs(notificationRuleService.getNotificationRuleRefs(projectParams,
886889
monitoredServiceDTO.getNotificationRuleRefs(), NotificationRuleType.MONITORED_SERVICE,
@@ -1256,9 +1259,21 @@ public HealthMonitoringFlagResponse setHealthMonitoringFlag(
12561259
projectParams, monitoredService.getIdentifier(), enable);
12571260
serviceLevelIndicatorService.setMonitoredServiceSLIsEnableFlag(
12581261
projectParams, monitoredService.getIdentifier(), enable);
1262+
if (enable
1263+
&& featureFlagService.isFeatureFlagEnabled(
1264+
projectParams.getAccountIdentifier(), FeatureFlagNames.CVNG_SLO_DISABLE_ENABLE)) {
1265+
entityDisabledTimeService.save(EntityDisableTime.builder()
1266+
.entityUUID(monitoredService.getUuid())
1267+
.accountId(monitoredService.getAccountId())
1268+
.startTime(monitoredService.getLastDisabledAt())
1269+
.endTime(clock.millis())
1270+
.build());
1271+
}
12591272
hPersistence.update(
12601273
hPersistence.createQuery(MonitoredService.class).filter(MonitoredServiceKeys.uuid, monitoredService.getUuid()),
1261-
hPersistence.createUpdateOperations(MonitoredService.class).set(MonitoredServiceKeys.enabled, enable));
1274+
hPersistence.createUpdateOperations(MonitoredService.class)
1275+
.set(MonitoredServiceKeys.enabled, enable)
1276+
.set(MonitoredServiceKeys.lastDisabledAt, clock.millis()));
12621277

12631278
MonitoredServiceDTO newMonitoredServiceDTO = getMonitoredServiceDTO(monitoredServiceParams);
12641279
MonitoredService newMonitoredService = getMonitoredService(projectParams, identifier);

300-cv-nextgen/src/main/java/io/harness/cvng/core/utils/FeatureFlagNames.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@
1010
public class FeatureFlagNames {
1111
public static final String CVNG_MONITORED_SERVICE_DEMO = "CVNG_MONITORED_SERVICE_DEMO";
1212
public static final String CVNG_LICENSE_ENFORCEMENT = "CVNG_LICENSE_ENFORCEMENT";
13+
14+
public static final String CVNG_SLO_DISABLE_ENABLE = "CVNG_SLO_DISABLE_ENABLE";
1315
}

300-cv-nextgen/src/main/java/io/harness/cvng/migration/CVNGBackgroundMigrationList.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import io.harness.cvng.migration.list.AddDeploymentMonitoringSourcePerpetualTask;
1313
import io.harness.cvng.migration.list.AddEnabledFlagToSLISLOMigration;
1414
import io.harness.cvng.migration.list.AddEnvRefsToMonitoredServiceMigration;
15+
import io.harness.cvng.migration.list.AddLastDisabledAtToMonitoredServiceMigration;
1516
import io.harness.cvng.migration.list.AddMetricIdentifierInCVConfigsAndMetricPacks;
1617
import io.harness.cvng.migration.list.AddMetricIdentifierToTimeSeriesThreshold;
1718
import io.harness.cvng.migration.list.AddMonitoredServiceToActivityMigration;
@@ -112,6 +113,7 @@ public static List<Pair<Integer, Class<? extends CVNGMigration>>> getMigrations(
112113
.add(Pair.of(48, SetNotRequiredActivityAnalysisStatusToIgnored.class))
113114
.add(Pair.of(49, PrometheusConnectorAuthenticationPerpetualTaskMigration.class))
114115
.add(Pair.of(50, AddEnabledFlagToSLISLOMigration.class))
116+
.add(Pair.of(51, AddLastDisabledAtToMonitoredServiceMigration.class))
115117
.build();
116118
}
117119
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2022 Harness Inc. All rights reserved.
3+
* Use of this source code is governed by the PolyForm Free Trial 1.0.0 license
4+
* that can be found in the licenses directory at the root of this repository, also available at
5+
* https://polyformproject.org/wp-content/uploads/2020/05/PolyForm-Free-Trial-1.0.0.txt.
6+
*/
7+
8+
package io.harness.cvng.migration.list;
9+
10+
import io.harness.cvng.core.entities.MonitoredService;
11+
import io.harness.cvng.core.entities.MonitoredService.MonitoredServiceKeys;
12+
import io.harness.cvng.migration.CVNGMigration;
13+
import io.harness.cvng.migration.beans.ChecklistItem;
14+
import io.harness.persistence.HPersistence;
15+
16+
import com.google.inject.Inject;
17+
import java.time.Clock;
18+
import lombok.extern.slf4j.Slf4j;
19+
import org.mongodb.morphia.query.Query;
20+
21+
@Slf4j
22+
public class AddLastDisabledAtToMonitoredServiceMigration implements CVNGMigration {
23+
@Inject private HPersistence hPersistence;
24+
@Inject private Clock clock;
25+
26+
@Override
27+
public void migrate() {
28+
log.info("Begin migration for updating SLI with enabled flag");
29+
Query<MonitoredService> monitoredServiceQuery =
30+
hPersistence.createQuery(MonitoredService.class).filter(MonitoredServiceKeys.lastDisabledAt, null);
31+
hPersistence.update(monitoredServiceQuery,
32+
hPersistence.createUpdateOperations(MonitoredService.class)
33+
.set(MonitoredServiceKeys.lastDisabledAt, clock.millis()));
34+
}
35+
36+
@Override
37+
public ChecklistItem whatHappensOnRollback() {
38+
return ChecklistItem.NA;
39+
}
40+
41+
@Override
42+
public ChecklistItem whatHappensIfOldVersionIteratorPicksMigratedEntity() {
43+
return ChecklistItem.NA;
44+
}
45+
}

300-cv-nextgen/src/main/java/io/harness/cvng/servicelevelobjective/beans/SLIMissingDataType.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,24 @@ public enum SLIMissingDataType {
1616
@JsonProperty("Ignore") IGNORE;
1717

1818
public SLIValue calculateSLIValue(long goodCount, long badCount, long totalMinutes) {
19+
return calculateSLIValue(goodCount, badCount, totalMinutes, 0L);
20+
}
21+
22+
public SLIValue calculateSLIValue(long goodCount, long badCount, long totalMinutes, long disabledMinutes) {
1923
Preconditions.checkState(totalMinutes != 0);
20-
long missingDataCount = totalMinutes - (goodCount + badCount);
24+
long missingDataCount = totalMinutes - (goodCount + badCount) - disabledMinutes;
2125
switch (this) {
2226
case GOOD:
2327
return SLIValue.builder()
2428
.goodCount((int) (goodCount + missingDataCount))
2529
.badCount((int) badCount)
26-
.total((int) totalMinutes)
30+
.total((int) (totalMinutes - disabledMinutes))
2731
.build();
2832
case BAD:
2933
return SLIValue.builder()
3034
.goodCount((int) goodCount)
3135
.badCount((int) (badCount + missingDataCount))
32-
.total((int) totalMinutes)
36+
.total((int) (totalMinutes - disabledMinutes))
3337
.build();
3438
case IGNORE:
3539
return SLIValue.builder()

0 commit comments

Comments
 (0)