diff --git a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java b/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java index 2c8879ba94..c7fda26dac 100644 --- a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java @@ -23,16 +23,18 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; import org.springframework.data.util.Pair; import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.ApiFeature; import org.thingsboard.server.common.data.ApiUsageRecordKey; import org.thingsboard.server.common.data.ApiUsageState; +import org.thingsboard.server.common.data.ApiUsageStateValue; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.id.ApiUsageStateId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.common.data.kv.BasicTsKvEntry; -import org.thingsboard.server.common.data.kv.BooleanDataEntry; import org.thingsboard.server.common.data.kv.LongDataEntry; +import org.thingsboard.server.common.data.kv.StringDataEntry; import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.data.page.PageDataIterable; import org.thingsboard.server.common.data.tenant.profile.TenantProfileConfiguration; @@ -57,8 +59,10 @@ import org.thingsboard.server.service.telemetry.InternalTelemetryService; import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; @@ -137,7 +141,7 @@ public class DefaultTbApiUsageStateService implements TbApiUsageStateService { TenantId tenantId = new TenantId(new UUID(statsMsg.getTenantIdMSB(), statsMsg.getTenantIdLSB())); TenantApiUsageState tenantState; List updatedEntries; - Map result = new HashMap<>(); + Map result; updateLock.lock(); try { tenantState = getOrFetchState(tenantId); @@ -148,17 +152,16 @@ public class DefaultTbApiUsageStateService implements TbApiUsageStateService { tenantState.setHour(newHourTs); } updatedEntries = new ArrayList<>(ApiUsageRecordKey.values().length); + Set apiFeatures = new HashSet<>(); for (UsageStatsKVProto kvProto : statsMsg.getValuesList()) { ApiUsageRecordKey recordKey = ApiUsageRecordKey.valueOf(kvProto.getKey()); long newValue = tenantState.add(recordKey, kvProto.getValue()); updatedEntries.add(new BasicTsKvEntry(ts, new LongDataEntry(recordKey.getApiCountKey(), newValue))); long newHourlyValue = tenantState.addToHourly(recordKey, kvProto.getValue()); updatedEntries.add(new BasicTsKvEntry(hourTs, new LongDataEntry(recordKey.getApiCountKey() + HOURLY, newHourlyValue))); - Pair update = tenantState.checkStateUpdatedDueToThreshold(recordKey); - if (update != null) { - result.put(update.getFirst(), update.getSecond()); - } + apiFeatures.add(recordKey.getApiFeature()); } + result = tenantState.checkStateUpdatedDueToThreshold(apiFeatures); } finally { updateLock.unlock(); } @@ -196,7 +199,9 @@ public class DefaultTbApiUsageStateService implements TbApiUsageStateService { state = otherTenantStates.get(tenantId); if (state == null) { state = apiUsageStateService.findTenantApiUsageState(tenantId); - otherTenantStates.put(tenantId, state); + if (state != null) { + otherTenantStates.put(tenantId, state); + } } } finally { updateLock.unlock(); @@ -245,7 +250,7 @@ public class DefaultTbApiUsageStateService implements TbApiUsageStateService { TenantProfileData oldProfileData = state.getTenantProfileData(); state.setTenantProfileId(tenantProfile.getId()); state.setTenantProfileData(tenantProfile.getProfileData()); - Map result = state.checkStateUpdatedDueToThresholds(); + Map result = state.checkStateUpdatedDueToThresholds(); if (!result.isEmpty()) { persistAndNotify(state, result); } @@ -269,14 +274,15 @@ public class DefaultTbApiUsageStateService implements TbApiUsageStateService { } } - private void persistAndNotify(TenantApiUsageState state, Map result) { + private void persistAndNotify(TenantApiUsageState state, Map result) { log.info("[{}] Detected update of the API state: {}", state.getTenantId(), result); apiUsageStateService.update(state.getApiUsageState()); clusterService.onApiStateChange(state.getApiUsageState(), null); long ts = System.currentTimeMillis(); List stateTelemetry = new ArrayList<>(); - result.forEach(((apiFeature, aState) -> stateTelemetry.add(new BasicTsKvEntry(ts, new BooleanDataEntry(apiFeature.getApiStateKey(), aState))))); + result.forEach(((apiFeature, aState) -> stateTelemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(apiFeature.getApiStateKey(), aState.name()))))); tsWsService.saveAndNotifyInternal(state.getTenantId(), state.getApiUsageState().getId(), stateTelemetry, VOID_CALLBACK); + //TODO: notify tenant admin via email! } private void checkStartOfNextCycle() { diff --git a/application/src/main/java/org/thingsboard/server/service/apiusage/TenantApiUsageState.java b/application/src/main/java/org/thingsboard/server/service/apiusage/TenantApiUsageState.java index 8fcc1d46cb..a43afcd2c5 100644 --- a/application/src/main/java/org/thingsboard/server/service/apiusage/TenantApiUsageState.java +++ b/application/src/main/java/org/thingsboard/server/service/apiusage/TenantApiUsageState.java @@ -18,17 +18,21 @@ package org.thingsboard.server.service.apiusage; import lombok.Getter; import lombok.Setter; import org.springframework.data.util.Pair; +import org.thingsboard.server.common.data.ApiFeature; import org.thingsboard.server.common.data.ApiUsageRecordKey; import org.thingsboard.server.common.data.ApiUsageState; +import org.thingsboard.server.common.data.ApiUsageStateValue; import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantProfileId; -import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; import org.thingsboard.server.common.data.tenant.profile.TenantProfileData; import org.thingsboard.server.common.msg.tools.SchedulerUtils; +import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public class TenantApiUsageState { @@ -103,99 +107,80 @@ public class TenantApiUsageState { return tenantProfileData.getConfiguration().getProfileThreshold(key); } - public TenantId getTenantId() { - return apiUsageState.getTenantId(); - } - - public boolean isTransportEnabled() { - return apiUsageState.isTransportEnabled(); - } - - public boolean isDbStorageEnabled() { - return apiUsageState.isDbStorageEnabled(); - } - - public boolean isRuleEngineEnabled() { - return apiUsageState.isReExecEnabled(); - } - - public boolean isJsExecEnabled() { - return apiUsageState.isJsExecEnabled(); - } - - public void setTransportEnabled(boolean transportEnabled) { - apiUsageState.setTransportEnabled(transportEnabled); + public long getProfileWarnThreshold(ApiUsageRecordKey key) { + return tenantProfileData.getConfiguration().getWarnThreshold(key); } - public void setDbStorageEnabled(boolean dbStorageEnabled) { - apiUsageState.setDbStorageEnabled(dbStorageEnabled); - } - - public void setRuleEngineEnabled(boolean ruleEngineEnabled) { - apiUsageState.setReExecEnabled(ruleEngineEnabled); - } - - public void setJsExecEnabled(boolean jsExecEnabled) { - apiUsageState.setJsExecEnabled(jsExecEnabled); + public TenantId getTenantId() { + return apiUsageState.getTenantId(); } - public boolean isFeatureEnabled(ApiUsageRecordKey recordKey) { - switch (recordKey) { - case TRANSPORT_MSG_COUNT: - case TRANSPORT_DP_COUNT: - return isTransportEnabled(); - case RE_EXEC_COUNT: - return isRuleEngineEnabled(); - case STORAGE_DP_COUNT: - return isDbStorageEnabled(); - case JS_EXEC_COUNT: - return isJsExecEnabled(); + public ApiUsageStateValue getFeatureValue(ApiFeature feature) { + switch (feature) { + case TRANSPORT: + return apiUsageState.getTransportState(); + case RE: + return apiUsageState.getReExecState(); + case DB: + return apiUsageState.getDbStorageState(); + case JS: + return apiUsageState.getJsExecState(); default: - return true; + return ApiUsageStateValue.ENABLED; } } - public ApiFeature setFeatureValue(ApiUsageRecordKey recordKey, boolean value) { - ApiFeature feature = null; - boolean currentValue = isFeatureEnabled(recordKey); - switch (recordKey) { - case TRANSPORT_MSG_COUNT: - case TRANSPORT_DP_COUNT: - feature = ApiFeature.TRANSPORT; - setTransportEnabled(value); + public boolean setFeatureValue(ApiFeature feature, ApiUsageStateValue value) { + ApiUsageStateValue currentValue = getFeatureValue(feature); + switch (feature) { + case TRANSPORT: + apiUsageState.setTransportState(value); break; - case RE_EXEC_COUNT: - feature = ApiFeature.RE; - setRuleEngineEnabled(value); + case RE: + apiUsageState.setReExecState(value); break; - case STORAGE_DP_COUNT: - feature = ApiFeature.DB; - setDbStorageEnabled(value); + case DB: + apiUsageState.setDbStorageState(value); break; - case JS_EXEC_COUNT: - feature = ApiFeature.JS; - setJsExecEnabled(value); + case JS: + apiUsageState.setJsExecState(value); break; } - return currentValue == value ? null : feature; + return !currentValue.equals(value); } - public Map checkStateUpdatedDueToThresholds() { - Map result = new HashMap<>(); - for (ApiUsageRecordKey key : ApiUsageRecordKey.values()) { - Pair featureUpdate = checkStateUpdatedDueToThreshold(key); - if (featureUpdate != null) { - result.put(featureUpdate.getFirst(), featureUpdate.getSecond()); + public Map checkStateUpdatedDueToThresholds() { + return checkStateUpdatedDueToThreshold(new HashSet<>(Arrays.asList(ApiFeature.values()))); + } + + public Map checkStateUpdatedDueToThreshold(Set features) { + Map result = new HashMap<>(); + for (ApiFeature feature : features) { + Pair tmp = checkStateUpdatedDueToThreshold(feature); + if (tmp != null) { + result.put(tmp.getFirst(), tmp.getSecond()); } } return result; } - public Pair checkStateUpdatedDueToThreshold(ApiUsageRecordKey recordKey) { - long value = get(recordKey); - long threshold = getProfileThreshold(recordKey); - boolean featureValue = threshold == 0 || value < threshold; - ApiFeature feature = setFeatureValue(recordKey, featureValue); - return feature != null ? Pair.of(feature, featureValue) : null; + public Pair checkStateUpdatedDueToThreshold(ApiFeature feature) { + ApiUsageStateValue featureValue = ApiUsageStateValue.ENABLED; + for (ApiUsageRecordKey recordKey : ApiUsageRecordKey.getKeys(feature)) { + long value = get(recordKey); + long threshold = getProfileThreshold(recordKey); + long warnThreshold = getProfileWarnThreshold(recordKey); + ApiUsageStateValue tmpValue; + if (threshold == 0 || value < warnThreshold) { + tmpValue = ApiUsageStateValue.ENABLED; + } else if (value < threshold) { + tmpValue = ApiUsageStateValue.WARNING; + } else { + tmpValue = ApiUsageStateValue.DISABLED; + } + featureValue = ApiUsageStateValue.toMoreRestricted(featureValue, tmpValue); + } + return setFeatureValue(feature, featureValue) ? Pair.of(feature, featureValue) : null; } + } diff --git a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java index d6068b9616..19727684a3 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java @@ -28,6 +28,7 @@ import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.device.DeviceProfileService; import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.tenant.TenantService; +import org.thingsboard.server.dao.usagerecord.ApiUsageStateService; import org.thingsboard.server.service.install.sql.SqlDbHelper; import java.nio.charset.Charset; @@ -96,6 +97,9 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService @Autowired private DeviceProfileService deviceProfileService; + @Autowired + private ApiUsageStateService apiUsageStateService; + @Override public void upgradeDatabase(String fromVersion) throws Exception { @@ -352,6 +356,22 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService } catch (Exception e) { } + try { + conn.createStatement().execute("CREATE TABLE IF NOT EXISTS api_usage_state (" + + " id uuid NOT NULL CONSTRAINT usage_record_pkey PRIMARY KEY," + + " created_time bigint NOT NULL," + + " tenant_id uuid," + + " entity_type varchar(32)," + + " entity_id uuid," + + " transport varchar(32)," + + " db_storage varchar(32)," + + " re_exec varchar(32)," + + " js_exec varchar(32)," + + " CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id)\n" + + ");"); + } catch (Exception e) { + } + schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "3.1.1", "schema_update_before.sql"); loadSql(schemaUpdateFile, conn); @@ -367,6 +387,10 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService do { pageData = tenantService.findTenants(pageLink); for (Tenant tenant : pageData.getData()) { + try { + apiUsageStateService.createDefaultApiUsageState(tenant.getId()); + } catch (Exception e) { + } List deviceTypes = deviceService.findDeviceTypesByTenantId(tenant.getId()).get(); try { deviceProfileService.createDefaultDeviceProfile(tenant.getId()); diff --git a/application/src/main/java/org/thingsboard/server/service/apiusage/ApiFeature.java b/common/data/src/main/java/org/thingsboard/server/common/data/ApiFeature.java similarity index 83% rename from application/src/main/java/org/thingsboard/server/service/apiusage/ApiFeature.java rename to common/data/src/main/java/org/thingsboard/server/common/data/ApiFeature.java index f2dfab54d4..e12cb5fb14 100644 --- a/application/src/main/java/org/thingsboard/server/service/apiusage/ApiFeature.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ApiFeature.java @@ -13,12 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.service.apiusage; +package org.thingsboard.server.common.data; import lombok.Getter; public enum ApiFeature { - TRANSPORT("transportApiState"), DB("dbApiState"), RE("ruleEngineApiState"), JS("jsExecutionApiState"); + TRANSPORT("transportApiState"), + DB("dbApiState"), + RE("ruleEngineApiState"), + JS("jsExecutionApiState"); @Getter private final String apiStateKey; @@ -26,4 +29,5 @@ public enum ApiFeature { ApiFeature(String apiStateKey) { this.apiStateKey = apiStateKey; } + } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageRecordKey.java b/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageRecordKey.java index b1ff230e71..dc8556a755 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageRecordKey.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageRecordKey.java @@ -19,20 +19,42 @@ import lombok.Getter; public enum ApiUsageRecordKey { - TRANSPORT_MSG_COUNT("transportMsgCount", "transportMsgLimit"), - TRANSPORT_DP_COUNT("transportDataPointsCount", "transportDataPointsLimit"), - STORAGE_DP_COUNT("storageDataPointsCount", "storageDataPointsLimit"), - RE_EXEC_COUNT("ruleEngineExecutionCount", "ruleEngineExecutionLimit"), - JS_EXEC_COUNT("jsExecutionCount", "jsExecutionLimit"); + TRANSPORT_MSG_COUNT(ApiFeature.TRANSPORT, "transportMsgCount", "transportMsgLimit"), + TRANSPORT_DP_COUNT(ApiFeature.TRANSPORT, "transportDataPointsCount", "transportDataPointsLimit"), + STORAGE_DP_COUNT(ApiFeature.DB, "storageDataPointsCount", "storageDataPointsLimit"), + RE_EXEC_COUNT(ApiFeature.RE, "ruleEngineExecutionCount", "ruleEngineExecutionLimit"), + JS_EXEC_COUNT(ApiFeature.JS, "jsExecutionCount", "jsExecutionLimit"); + private static final ApiUsageRecordKey[] JS_RECORD_KEYS = {JS_EXEC_COUNT}; + private static final ApiUsageRecordKey[] RE_RECORD_KEYS = {RE_EXEC_COUNT}; + private static final ApiUsageRecordKey[] DB_RECORD_KEYS = {STORAGE_DP_COUNT}; + private static final ApiUsageRecordKey[] TRANSPORT_RECORD_KEYS = {TRANSPORT_MSG_COUNT, TRANSPORT_DP_COUNT}; + @Getter + private final ApiFeature apiFeature; @Getter private final String apiCountKey; @Getter private final String apiLimitKey; - ApiUsageRecordKey(String apiCountKey, String apiLimitKey) { + ApiUsageRecordKey(ApiFeature apiFeature, String apiCountKey, String apiLimitKey) { + this.apiFeature = apiFeature; this.apiCountKey = apiCountKey; this.apiLimitKey = apiLimitKey; } + public static ApiUsageRecordKey[] getKeys(ApiFeature feature) { + switch (feature) { + case TRANSPORT: + return TRANSPORT_RECORD_KEYS; + case DB: + return DB_RECORD_KEYS; + case RE: + return RE_RECORD_KEYS; + case JS: + return JS_RECORD_KEYS; + default: + return new ApiUsageRecordKey[]{}; + } + } + } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageState.java b/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageState.java index 5144861790..52797baa3b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageState.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageState.java @@ -37,16 +37,16 @@ public class ApiUsageState extends BaseData implements HasTenan private EntityId entityId; @Getter @Setter - private boolean transportEnabled = true; + private ApiUsageStateValue transportState; @Getter @Setter - private boolean dbStorageEnabled = true; + private ApiUsageStateValue dbStorageState; @Getter @Setter - private boolean reExecEnabled = true; + private ApiUsageStateValue reExecState; @Getter @Setter - private boolean jsExecEnabled = true; + private ApiUsageStateValue jsExecState; public ApiUsageState() { super(); @@ -60,9 +60,25 @@ public class ApiUsageState extends BaseData implements HasTenan super(ur); this.tenantId = ur.getTenantId(); this.entityId = ur.getEntityId(); - this.transportEnabled = ur.isTransportEnabled(); - this.dbStorageEnabled = ur.isDbStorageEnabled(); - this.reExecEnabled = ur.isReExecEnabled(); - this.jsExecEnabled = ur.isJsExecEnabled(); + this.transportState = ur.getTransportState(); + this.dbStorageState = ur.getDbStorageState(); + this.reExecState = ur.getReExecState(); + this.jsExecState = ur.getJsExecState(); + } + + public boolean isTransportEnabled() { + return !ApiUsageStateValue.DISABLED.equals(transportState); + } + + public boolean isReExecEnabled() { + return !ApiUsageStateValue.DISABLED.equals(reExecState); + } + + public boolean isDbStorageEnabled() { + return !ApiUsageStateValue.DISABLED.equals(dbStorageState); + } + + public boolean isJsExecEnabled() { + return !ApiUsageStateValue.DISABLED.equals(jsExecState); } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageStateValue.java b/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageStateValue.java new file mode 100644 index 0000000000..ae14ff80bf --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageStateValue.java @@ -0,0 +1,26 @@ +/** + * Copyright © 2016-2020 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.data; + +public enum ApiUsageStateValue { + + ENABLED, WARNING, DISABLED; + + + public static ApiUsageStateValue toMoreRestricted(ApiUsageStateValue a, ApiUsageStateValue b) { + return a.ordinal() > b.ordinal() ? a : b; + } +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java index 1804731c04..250f9c75a5 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java @@ -39,6 +39,8 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura private long maxDPStorageDays; private int maxRuleNodeExecutionsPerMessage; + private double warnThreshold; + @Override public long getProfileThreshold(ApiUsageRecordKey key) { switch (key) { @@ -56,6 +58,10 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura return 0L; } + @Override + public long getWarnThreshold(ApiUsageRecordKey key) { + return (long) (getProfileThreshold(key) * (warnThreshold > 0.0 ? warnThreshold : 0.8)); + } @Override public TenantProfileType getType() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/TenantProfileConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/TenantProfileConfiguration.java index c4c6d7563a..ea4a0e1fbe 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/TenantProfileConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/TenantProfileConfiguration.java @@ -37,6 +37,9 @@ public interface TenantProfileConfiguration { @JsonIgnore long getProfileThreshold(ApiUsageRecordKey key); + @JsonIgnore + long getWarnThreshold(ApiUsageRecordKey key); + @JsonIgnore int getMaxRuleNodeExecsPerMessage(); diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/settings/TbQueueCoreSettings.java b/common/queue/src/main/java/org/thingsboard/server/queue/settings/TbQueueCoreSettings.java index d406139dbb..d78c6d1bad 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/settings/TbQueueCoreSettings.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/settings/TbQueueCoreSettings.java @@ -26,7 +26,7 @@ public class TbQueueCoreSettings { @Value("${queue.core.topic}") private String topic; - @Value("${queue.core.usage-stats-topic}") + @Value("${queue.core.usage-stats-topic:tb_usage_stats}") private String usageStatsTopic; @Value("${queue.core.partitions}") diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index 8e1e62b90f..e863de1edc 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -446,10 +446,10 @@ public class ModelConstants { public static final String API_USAGE_STATE_TENANT_ID_COLUMN = TENANT_ID_PROPERTY; public static final String API_USAGE_STATE_ENTITY_TYPE_COLUMN = ENTITY_TYPE_COLUMN; public static final String API_USAGE_STATE_ENTITY_ID_COLUMN = ENTITY_ID_COLUMN; - public static final String API_USAGE_STATE_TRANSPORT_ENABLED_COLUMN = "transport_enabled"; - public static final String API_USAGE_STATE_DB_STORAGE_ENABLED_COLUMN = "db_storage_enabled"; - public static final String API_USAGE_STATE_RE_EXEC_ENABLED_COLUMN = "re_exec_enabled"; - public static final String API_USAGE_STATE_JS_EXEC_ENABLED_COLUMN = "js_exec_enabled"; + public static final String API_USAGE_STATE_TRANSPORT_COLUMN = "transport"; + public static final String API_USAGE_STATE_DB_STORAGE_COLUMN = "db_storage"; + public static final String API_USAGE_STATE_RE_EXEC_COLUMN = "re_exec"; + public static final String API_USAGE_STATE_JS_EXEC_COLUMN = "js_exec"; /** * Cassandra attributes and timeseries constants. diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java index 262252517a..bc4aed6398 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java @@ -17,10 +17,9 @@ package org.thingsboard.server.dao.model.sql; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.ApiUsageState; +import org.thingsboard.server.common.data.ApiUsageStateValue; import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.ApiUsageStateId; @@ -31,6 +30,8 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; import javax.persistence.Table; import java.util.UUID; @@ -46,21 +47,22 @@ public class ApiUsageStateEntity extends BaseSqlEntity implements @Column(name = ModelConstants.API_USAGE_STATE_TENANT_ID_COLUMN) private UUID tenantId; - @Column(name = ModelConstants.API_USAGE_STATE_ENTITY_TYPE_COLUMN) private String entityType; - @Column(name = ModelConstants.API_USAGE_STATE_ENTITY_ID_COLUMN) private UUID entityId; - - @Column(name = ModelConstants.API_USAGE_STATE_TRANSPORT_ENABLED_COLUMN) - private boolean transportEnabled = true; - @Column(name = ModelConstants.API_USAGE_STATE_DB_STORAGE_ENABLED_COLUMN) - private boolean dbStorageEnabled = true; - @Column(name = ModelConstants.API_USAGE_STATE_RE_EXEC_ENABLED_COLUMN) - private boolean reExecEnabled = true; - @Column(name = ModelConstants.API_USAGE_STATE_JS_EXEC_ENABLED_COLUMN) - private boolean jsExecEnabled = true; + @Enumerated(EnumType.STRING) + @Column(name = ModelConstants.API_USAGE_STATE_TRANSPORT_COLUMN) + private ApiUsageStateValue transportState = ApiUsageStateValue.ENABLED; + @Enumerated(EnumType.STRING) + @Column(name = ModelConstants.API_USAGE_STATE_DB_STORAGE_COLUMN) + private ApiUsageStateValue dbStorageState = ApiUsageStateValue.ENABLED; + @Enumerated(EnumType.STRING) + @Column(name = ModelConstants.API_USAGE_STATE_RE_EXEC_COLUMN) + private ApiUsageStateValue reExecState = ApiUsageStateValue.ENABLED; + @Enumerated(EnumType.STRING) + @Column(name = ModelConstants.API_USAGE_STATE_JS_EXEC_COLUMN) + private ApiUsageStateValue jsExecState = ApiUsageStateValue.ENABLED; public ApiUsageStateEntity() { } @@ -77,10 +79,10 @@ public class ApiUsageStateEntity extends BaseSqlEntity implements this.entityType = ur.getEntityId().getEntityType().name(); this.entityId = ur.getEntityId().getId(); } - this.transportEnabled = ur.isTransportEnabled(); - this.dbStorageEnabled = ur.isDbStorageEnabled(); - this.reExecEnabled = ur.isReExecEnabled(); - this.jsExecEnabled = ur.isJsExecEnabled(); + this.transportState = ur.getTransportState(); + this.dbStorageState = ur.getDbStorageState(); + this.reExecState = ur.getReExecState(); + this.jsExecState = ur.getJsExecState(); } @Override @@ -93,10 +95,10 @@ public class ApiUsageStateEntity extends BaseSqlEntity implements if (entityId != null) { ur.setEntityId(EntityIdFactory.getByTypeAndUuid(entityType, entityId)); } - ur.setTransportEnabled(transportEnabled); - ur.setDbStorageEnabled(dbStorageEnabled); - ur.setReExecEnabled(reExecEnabled); - ur.setJsExecEnabled(jsExecEnabled); + ur.setTransportState(transportState); + ur.setDbStorageState(dbStorageState); + ur.setReExecState(reExecState); + ur.setJsExecState(jsExecState); return ur; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java index e1b494e2e8..ed02bf7726 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java @@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.ApiUsageRecordKey; import org.thingsboard.server.common.data.ApiUsageState; +import org.thingsboard.server.common.data.ApiUsageStateValue; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.TenantProfile; @@ -71,6 +72,10 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A ApiUsageState apiUsageState = new ApiUsageState(); apiUsageState.setTenantId(tenantId); apiUsageState.setEntityId(tenantId); + apiUsageState.setTransportState(ApiUsageStateValue.ENABLED); + apiUsageState.setReExecState(ApiUsageStateValue.ENABLED); + apiUsageState.setJsExecState(ApiUsageStateValue.ENABLED); + apiUsageState.setDbStorageState(ApiUsageStateValue.ENABLED); apiUsageStateValidator.validate(apiUsageState, ApiUsageState::getTenantId); ApiUsageState saved = apiUsageStateDao.save(apiUsageState.getTenantId(), apiUsageState); diff --git a/dao/src/main/resources/sql/schema-entities-hsql.sql b/dao/src/main/resources/sql/schema-entities-hsql.sql index b7c028d5d7..0e8f8a7791 100644 --- a/dao/src/main/resources/sql/schema-entities-hsql.sql +++ b/dao/src/main/resources/sql/schema-entities-hsql.sql @@ -412,9 +412,9 @@ CREATE TABLE IF NOT EXISTS api_usage_state ( tenant_id uuid, entity_type varchar(32), entity_id uuid, - transport_enabled boolean, - db_storage_enabled boolean, - re_exec_enabled boolean, - js_exec_enabled boolean, + transport varchar(32), + db_storage varchar(32), + re_exec varchar(32), + js_exec varchar(32), CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id) ); diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index 6fffea8fe9..db0362a877 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -438,10 +438,10 @@ CREATE TABLE IF NOT EXISTS api_usage_state ( tenant_id uuid, entity_type varchar(32), entity_id uuid, - transport_enabled boolean, - db_storage_enabled boolean, - re_exec_enabled boolean, - js_exec_enabled boolean, + transport varchar(32), + db_storage varchar(32), + re_exec varchar(32), + js_exec varchar(32), CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id) ); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseApiUsageStateServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseApiUsageStateServiceTest.java index a33e190a03..024d3dd5c3 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseApiUsageStateServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseApiUsageStateServiceTest.java @@ -19,6 +19,7 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.thingsboard.server.common.data.ApiUsageStateValue; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.ApiUsageState; import org.thingsboard.server.common.data.id.TenantId; @@ -53,7 +54,7 @@ public abstract class BaseApiUsageStateServiceTest extends AbstractServiceTest { ApiUsageState apiUsageState = apiUsageStateService.findTenantApiUsageState(tenantId); Assert.assertNotNull(apiUsageState); Assert.assertTrue(apiUsageState.isTransportEnabled()); - apiUsageState.setTransportEnabled(false); + apiUsageState.setTransportState(ApiUsageStateValue.DISABLED); apiUsageState = apiUsageStateService.update(apiUsageState); Assert.assertNotNull(apiUsageState); apiUsageState = apiUsageStateService.findTenantApiUsageState(tenantId); diff --git a/transport/coap/src/main/resources/tb-coap-transport.yml b/transport/coap/src/main/resources/tb-coap-transport.yml index 229196d325..3a1d0e7414 100644 --- a/transport/coap/src/main/resources/tb-coap-transport.yml +++ b/transport/coap/src/main/resources/tb-coap-transport.yml @@ -145,6 +145,7 @@ queue: poll-interval: "${TB_QUEUE_CORE_POLL_INTERVAL_MS:25}" partitions: "${TB_QUEUE_CORE_PARTITIONS:10}" pack-processing-timeout: "${TB_QUEUE_CORE_PACK_PROCESSING_TIMEOUT_MS:60000}" + usage-stats-topic: "${TB_QUEUE_US_TOPIC:tb_usage_stats}" stats: enabled: "${TB_QUEUE_CORE_STATS_ENABLED:false}" print-interval-ms: "${TB_QUEUE_CORE_STATS_PRINT_INTERVAL_MS:10000}" diff --git a/transport/http/src/main/resources/tb-http-transport.yml b/transport/http/src/main/resources/tb-http-transport.yml index 6aaa42ca18..ef152bb47d 100644 --- a/transport/http/src/main/resources/tb-http-transport.yml +++ b/transport/http/src/main/resources/tb-http-transport.yml @@ -138,6 +138,7 @@ queue: poll-interval: "${TB_QUEUE_CORE_POLL_INTERVAL_MS:25}" partitions: "${TB_QUEUE_CORE_PARTITIONS:10}" pack-processing-timeout: "${TB_QUEUE_CORE_PACK_PROCESSING_TIMEOUT_MS:60000}" + usage-stats-topic: "${TB_QUEUE_US_TOPIC:tb_usage_stats}" stats: enabled: "${TB_QUEUE_CORE_STATS_ENABLED:false}" print-interval-ms: "${TB_QUEUE_CORE_STATS_PRINT_INTERVAL_MS:10000}" diff --git a/transport/mqtt/src/main/resources/tb-mqtt-transport.yml b/transport/mqtt/src/main/resources/tb-mqtt-transport.yml index f9341dfb86..fc8d970638 100644 --- a/transport/mqtt/src/main/resources/tb-mqtt-transport.yml +++ b/transport/mqtt/src/main/resources/tb-mqtt-transport.yml @@ -167,6 +167,7 @@ queue: poll-interval: "${TB_QUEUE_CORE_POLL_INTERVAL_MS:25}" partitions: "${TB_QUEUE_CORE_PARTITIONS:10}" pack-processing-timeout: "${TB_QUEUE_CORE_PACK_PROCESSING_TIMEOUT_MS:60000}" + usage-stats-topic: "${TB_QUEUE_US_TOPIC:tb_usage_stats}" stats: enabled: "${TB_QUEUE_CORE_STATS_ENABLED:false}" print-interval-ms: "${TB_QUEUE_CORE_STATS_PRINT_INTERVAL_MS:10000}"