Search in sources :

Example 6 with ApiUsageRecordKey

use of org.thingsboard.server.common.data.ApiUsageRecordKey in project thingsboard by thingsboard.

the class DefaultTbApiUsageStateService method createStateMailMessage.

private ApiUsageStateMailMessage createStateMailMessage(TenantApiUsageState state, ApiFeature apiFeature, ApiUsageStateValue stateValue) {
    StateChecker checker = getStateChecker(stateValue);
    for (ApiUsageRecordKey apiUsageRecordKey : ApiUsageRecordKey.getKeys(apiFeature)) {
        long threshold = state.getProfileThreshold(apiUsageRecordKey);
        long warnThreshold = state.getProfileWarnThreshold(apiUsageRecordKey);
        long value = state.get(apiUsageRecordKey);
        if (checker.check(threshold, warnThreshold, value)) {
            return new ApiUsageStateMailMessage(apiUsageRecordKey, threshold, value);
        }
    }
    return null;
}
Also used : ApiUsageStateMailMessage(org.thingsboard.server.common.data.ApiUsageStateMailMessage) ApiUsageRecordKey(org.thingsboard.server.common.data.ApiUsageRecordKey)

Example 7 with ApiUsageRecordKey

use of org.thingsboard.server.common.data.ApiUsageRecordKey in project thingsboard by thingsboard.

the class DefaultTbApiUsageStateService method getOrFetchState.

BaseApiUsageState getOrFetchState(TenantId tenantId, EntityId entityId) {
    if (entityId == null || entityId.isNullUid()) {
        entityId = tenantId;
    }
    BaseApiUsageState state = myUsageStates.get(entityId);
    if (state != null) {
        return state;
    }
    ApiUsageState storedState = apiUsageStateService.findApiUsageStateByEntityId(entityId);
    if (storedState == null) {
        try {
            storedState = apiUsageStateService.createDefaultApiUsageState(tenantId, entityId);
        } catch (Exception e) {
            storedState = apiUsageStateService.findApiUsageStateByEntityId(entityId);
        }
    }
    if (entityId.getEntityType() == EntityType.TENANT) {
        if (!entityId.equals(TenantId.SYS_TENANT_ID)) {
            state = new TenantApiUsageState(tenantProfileCache.get((TenantId) entityId), storedState);
        } else {
            state = new TenantApiUsageState(storedState);
        }
    } else {
        state = new CustomerApiUsageState(storedState);
    }
    List<ApiUsageRecordKey> newCounts = new ArrayList<>();
    try {
        List<TsKvEntry> dbValues = tsService.findAllLatest(tenantId, storedState.getId()).get();
        for (ApiUsageRecordKey key : ApiUsageRecordKey.values()) {
            boolean cycleEntryFound = false;
            boolean hourlyEntryFound = false;
            for (TsKvEntry tsKvEntry : dbValues) {
                if (tsKvEntry.getKey().equals(key.getApiCountKey())) {
                    cycleEntryFound = true;
                    boolean oldCount = tsKvEntry.getTs() == state.getCurrentCycleTs();
                    state.put(key, oldCount ? tsKvEntry.getLongValue().get() : 0L);
                    if (!oldCount) {
                        newCounts.add(key);
                    }
                } else if (tsKvEntry.getKey().equals(key.getApiCountKey() + HOURLY)) {
                    hourlyEntryFound = true;
                    state.putHourly(key, tsKvEntry.getTs() == state.getCurrentHourTs() ? tsKvEntry.getLongValue().get() : 0L);
                }
                if (cycleEntryFound && hourlyEntryFound) {
                    break;
                }
            }
        }
        log.debug("[{}] Initialized state: {}", entityId, storedState);
        TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, tenantId, entityId);
        if (tpi.isMyPartition()) {
            addEntityState(tpi, state);
        } else {
            otherUsageStates.put(entityId, state.getApiUsageState());
        }
        saveNewCounts(state, newCounts);
    } catch (InterruptedException | ExecutionException e) {
        log.warn("[{}] Failed to fetch api usage state from db.", tenantId, e);
    }
    return state;
}
Also used : BasicTsKvEntry(org.thingsboard.server.common.data.kv.BasicTsKvEntry) TsKvEntry(org.thingsboard.server.common.data.kv.TsKvEntry) ArrayList(java.util.ArrayList) ThingsboardException(org.thingsboard.server.common.data.exception.ThingsboardException) ExecutionException(java.util.concurrent.ExecutionException) ApiUsageRecordKey(org.thingsboard.server.common.data.ApiUsageRecordKey) TopicPartitionInfo(org.thingsboard.server.common.msg.queue.TopicPartitionInfo) ApiUsageState(org.thingsboard.server.common.data.ApiUsageState) ExecutionException(java.util.concurrent.ExecutionException)

Example 8 with ApiUsageRecordKey

use of org.thingsboard.server.common.data.ApiUsageRecordKey in project thingsboard by thingsboard.

the class DefaultTbApiUsageClient method init.

@PostConstruct
private void init() {
    if (enabled) {
        msgProducer = this.producerProvider.getTbUsageStatsMsgProducer();
        for (ApiUsageRecordKey key : ApiUsageRecordKey.values()) {
            stats.put(key, new ConcurrentHashMap<>());
        }
        scheduler.scheduleWithFixedDelay(() -> {
            try {
                reportStats();
            } catch (Exception e) {
                log.warn("Failed to report statistics: ", e);
            }
        }, new Random().nextInt(interval), interval, TimeUnit.SECONDS);
    }
}
Also used : Random(java.util.Random) ApiUsageRecordKey(org.thingsboard.server.common.data.ApiUsageRecordKey) PostConstruct(javax.annotation.PostConstruct)

Example 9 with ApiUsageRecordKey

use of org.thingsboard.server.common.data.ApiUsageRecordKey in project thingsboard by thingsboard.

the class DefaultTbApiUsageClient method reportStats.

private void reportStats() {
    ConcurrentMap<OwnerId, ToUsageStatsServiceMsg.Builder> report = new ConcurrentHashMap<>();
    for (ApiUsageRecordKey key : ApiUsageRecordKey.values()) {
        ConcurrentMap<OwnerId, AtomicLong> statsForKey = stats.get(key);
        statsForKey.forEach((ownerId, statsValue) -> {
            long value = statsValue.get();
            if (value == 0)
                return;
            ToUsageStatsServiceMsg.Builder statsMsgBuilder = report.computeIfAbsent(ownerId, id -> {
                ToUsageStatsServiceMsg.Builder newStatsMsgBuilder = ToUsageStatsServiceMsg.newBuilder();
                TenantId tenantId = ownerId.getTenantId();
                newStatsMsgBuilder.setTenantIdMSB(tenantId.getId().getMostSignificantBits());
                newStatsMsgBuilder.setTenantIdLSB(tenantId.getId().getLeastSignificantBits());
                EntityId entityId = ownerId.getEntityId();
                if (entityId != null && entityId.getEntityType() == EntityType.CUSTOMER) {
                    newStatsMsgBuilder.setCustomerIdMSB(entityId.getId().getMostSignificantBits());
                    newStatsMsgBuilder.setCustomerIdLSB(entityId.getId().getLeastSignificantBits());
                }
                return newStatsMsgBuilder;
            });
            statsMsgBuilder.addValues(UsageStatsKVProto.newBuilder().setKey(key.name()).setValue(value).build());
        });
        statsForKey.clear();
    }
    report.forEach(((ownerId, statsMsg) -> {
        // TODO: figure out how to minimize messages into the queue. Maybe group by 100s of messages?
        TenantId tenantId = ownerId.getTenantId();
        EntityId entityId = Optional.ofNullable(ownerId.getEntityId()).orElse(tenantId);
        TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, tenantId, entityId).newByTopic(msgProducer.getDefaultTopic());
        msgProducer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), statsMsg.build()), null);
    }));
    if (!report.isEmpty()) {
        log.debug("Reporting API usage statistics for {} tenants and customers", report.size());
    }
}
Also used : UsageStatsKVProto(org.thingsboard.server.gen.transport.TransportProtos.UsageStatsKVProto) PartitionService(org.thingsboard.server.queue.discovery.PartitionService) ApiUsageRecordKey(org.thingsboard.server.common.data.ApiUsageRecordKey) Random(java.util.Random) TenantId(org.thingsboard.server.common.data.id.TenantId) ConcurrentMap(java.util.concurrent.ConcurrentMap) Value(org.springframework.beans.factory.annotation.Value) ToUsageStatsServiceMsg(org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg) ServiceType(org.thingsboard.server.common.msg.queue.ServiceType) EntityId(org.thingsboard.server.common.data.id.EntityId) EntityType(org.thingsboard.server.common.data.EntityType) TbQueueProducer(org.thingsboard.server.queue.TbQueueProducer) SchedulerComponent(org.thingsboard.server.queue.scheduler.SchedulerComponent) EnumMap(java.util.EnumMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) UUID(java.util.UUID) TbQueueProducerProvider(org.thingsboard.server.queue.provider.TbQueueProducerProvider) TimeUnit(java.util.concurrent.TimeUnit) AtomicLong(java.util.concurrent.atomic.AtomicLong) Slf4j(lombok.extern.slf4j.Slf4j) Component(org.springframework.stereotype.Component) Data(lombok.Data) PostConstruct(javax.annotation.PostConstruct) Optional(java.util.Optional) TbProtoQueueMsg(org.thingsboard.server.queue.common.TbProtoQueueMsg) CustomerId(org.thingsboard.server.common.data.id.CustomerId) TopicPartitionInfo(org.thingsboard.server.common.msg.queue.TopicPartitionInfo) TbProtoQueueMsg(org.thingsboard.server.queue.common.TbProtoQueueMsg) ToUsageStatsServiceMsg(org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg) ApiUsageRecordKey(org.thingsboard.server.common.data.ApiUsageRecordKey) EntityId(org.thingsboard.server.common.data.id.EntityId) AtomicLong(java.util.concurrent.atomic.AtomicLong) TenantId(org.thingsboard.server.common.data.id.TenantId) TopicPartitionInfo(org.thingsboard.server.common.msg.queue.TopicPartitionInfo) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 10 with ApiUsageRecordKey

use of org.thingsboard.server.common.data.ApiUsageRecordKey in project thingsboard by thingsboard.

the class ApiUsageStateServiceImpl method createDefaultApiUsageState.

@Override
public ApiUsageState createDefaultApiUsageState(TenantId tenantId, EntityId entityId) {
    entityId = Objects.requireNonNullElse(entityId, tenantId);
    log.trace("Executing createDefaultUsageRecord [{}]", entityId);
    validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
    ApiUsageState apiUsageState = new ApiUsageState();
    apiUsageState.setTenantId(tenantId);
    apiUsageState.setEntityId(entityId);
    apiUsageState.setTransportState(ApiUsageStateValue.ENABLED);
    apiUsageState.setReExecState(ApiUsageStateValue.ENABLED);
    apiUsageState.setJsExecState(ApiUsageStateValue.ENABLED);
    apiUsageState.setDbStorageState(ApiUsageStateValue.ENABLED);
    apiUsageState.setSmsExecState(ApiUsageStateValue.ENABLED);
    apiUsageState.setEmailExecState(ApiUsageStateValue.ENABLED);
    apiUsageState.setAlarmExecState(ApiUsageStateValue.ENABLED);
    apiUsageStateValidator.validate(apiUsageState, ApiUsageState::getTenantId);
    ApiUsageState saved = apiUsageStateDao.save(apiUsageState.getTenantId(), apiUsageState);
    List<TsKvEntry> apiUsageStates = new ArrayList<>();
    apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), new StringDataEntry(ApiFeature.TRANSPORT.getApiStateKey(), ApiUsageStateValue.ENABLED.name())));
    apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), new StringDataEntry(ApiFeature.DB.getApiStateKey(), ApiUsageStateValue.ENABLED.name())));
    apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), new StringDataEntry(ApiFeature.RE.getApiStateKey(), ApiUsageStateValue.ENABLED.name())));
    apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), new StringDataEntry(ApiFeature.JS.getApiStateKey(), ApiUsageStateValue.ENABLED.name())));
    apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), new StringDataEntry(ApiFeature.EMAIL.getApiStateKey(), ApiUsageStateValue.ENABLED.name())));
    apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), new StringDataEntry(ApiFeature.SMS.getApiStateKey(), ApiUsageStateValue.ENABLED.name())));
    apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), new StringDataEntry(ApiFeature.ALARM.getApiStateKey(), ApiUsageStateValue.ENABLED.name())));
    tsService.save(tenantId, saved.getId(), apiUsageStates, 0L);
    if (entityId.getEntityType() == EntityType.TENANT && !entityId.equals(TenantId.SYS_TENANT_ID)) {
        tenantId = (TenantId) entityId;
        Tenant tenant = tenantDao.findById(tenantId, tenantId.getId());
        TenantProfile tenantProfile = tenantProfileDao.findById(tenantId, tenant.getTenantProfileId().getId());
        TenantProfileConfiguration configuration = tenantProfile.getProfileData().getConfiguration();
        List<TsKvEntry> profileThresholds = new ArrayList<>();
        for (ApiUsageRecordKey key : ApiUsageRecordKey.values()) {
            profileThresholds.add(new BasicTsKvEntry(saved.getCreatedTime(), new LongDataEntry(key.getApiLimitKey(), configuration.getProfileThreshold(key))));
        }
        tsService.save(tenantId, saved.getId(), profileThresholds, 0L);
    }
    return saved;
}
Also used : BasicTsKvEntry(org.thingsboard.server.common.data.kv.BasicTsKvEntry) TsKvEntry(org.thingsboard.server.common.data.kv.TsKvEntry) Tenant(org.thingsboard.server.common.data.Tenant) TenantProfileConfiguration(org.thingsboard.server.common.data.tenant.profile.TenantProfileConfiguration) ApiUsageState(org.thingsboard.server.common.data.ApiUsageState) BasicTsKvEntry(org.thingsboard.server.common.data.kv.BasicTsKvEntry) StringDataEntry(org.thingsboard.server.common.data.kv.StringDataEntry) ArrayList(java.util.ArrayList) LongDataEntry(org.thingsboard.server.common.data.kv.LongDataEntry) TenantProfile(org.thingsboard.server.common.data.TenantProfile) ApiUsageRecordKey(org.thingsboard.server.common.data.ApiUsageRecordKey)

Aggregations

ApiUsageRecordKey (org.thingsboard.server.common.data.ApiUsageRecordKey)10 BasicTsKvEntry (org.thingsboard.server.common.data.kv.BasicTsKvEntry)5 TsKvEntry (org.thingsboard.server.common.data.kv.TsKvEntry)5 ArrayList (java.util.ArrayList)4 LongDataEntry (org.thingsboard.server.common.data.kv.LongDataEntry)4 PostConstruct (javax.annotation.PostConstruct)3 ApiUsageState (org.thingsboard.server.common.data.ApiUsageState)3 ApiUsageStateValue (org.thingsboard.server.common.data.ApiUsageStateValue)3 TopicPartitionInfo (org.thingsboard.server.common.msg.queue.TopicPartitionInfo)3 UsageStatsKVProto (org.thingsboard.server.gen.transport.TransportProtos.UsageStatsKVProto)3 HashSet (java.util.HashSet)2 Random (java.util.Random)2 UUID (java.util.UUID)2 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)2 ExecutionException (java.util.concurrent.ExecutionException)2 TimeUnit (java.util.concurrent.TimeUnit)2 Slf4j (lombok.extern.slf4j.Slf4j)2 Value (org.springframework.beans.factory.annotation.Value)2 ApiFeature (org.thingsboard.server.common.data.ApiFeature)2 ApiUsageStateMailMessage (org.thingsboard.server.common.data.ApiUsageStateMailMessage)2