6 changed files with 331 additions and 0 deletions
@ -0,0 +1,45 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2023 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.controller; |
||||
|
|
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.security.access.prepost.PreAuthorize; |
||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestMethod; |
||||
|
import org.springframework.web.bind.annotation.ResponseBody; |
||||
|
import org.springframework.web.bind.annotation.RestController; |
||||
|
import org.thingsboard.server.common.data.UsageInfo; |
||||
|
import org.thingsboard.server.common.data.exception.ThingsboardException; |
||||
|
import org.thingsboard.server.dao.usage.UsageInfoService; |
||||
|
import org.thingsboard.server.queue.util.TbCoreComponent; |
||||
|
|
||||
|
@RestController |
||||
|
@TbCoreComponent |
||||
|
@RequestMapping("/api") |
||||
|
@Slf4j |
||||
|
public class UsageInfoController extends BaseController { |
||||
|
|
||||
|
@Autowired |
||||
|
private UsageInfoService usageInfoService; |
||||
|
|
||||
|
@PreAuthorize("hasAuthority('TENANT_ADMIN')") |
||||
|
@RequestMapping(value = "/tenant/usageInfo", method = RequestMethod.GET) |
||||
|
@ResponseBody |
||||
|
public UsageInfo getTenantUsageInfo() throws ThingsboardException { |
||||
|
return checkNotNull(usageInfoService.getUsageInfo(getCurrentUser().getTenantId())); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2023 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.dao.usage; |
||||
|
|
||||
|
import org.thingsboard.server.common.data.UsageInfo; |
||||
|
import org.thingsboard.server.common.data.id.TenantId; |
||||
|
|
||||
|
public interface UsageInfoService { |
||||
|
|
||||
|
UsageInfo getUsageInfo(TenantId tenantId); |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,43 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2023 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; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
|
||||
|
@Data |
||||
|
public class UsageInfo { |
||||
|
private long devices; |
||||
|
private long maxDevices; |
||||
|
private long assets; |
||||
|
private long maxAssets; |
||||
|
private long customers; |
||||
|
private long maxCustomers; |
||||
|
private long users; |
||||
|
private long maxUsers; |
||||
|
private long dashboards; |
||||
|
private long maxDashboards; |
||||
|
|
||||
|
private long transportMessages; |
||||
|
private long maxTransportMessages; |
||||
|
private long jsExecutions; |
||||
|
private long maxJsExecutions; |
||||
|
private long emails; |
||||
|
private long maxEmails; |
||||
|
private long sms; |
||||
|
private long maxSms; |
||||
|
private long alarms; |
||||
|
private long maxAlarms; |
||||
|
} |
||||
@ -0,0 +1,109 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2023 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.dao.usage; |
||||
|
|
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.context.annotation.Lazy; |
||||
|
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.UsageInfo; |
||||
|
import org.thingsboard.server.common.data.id.TenantId; |
||||
|
import org.thingsboard.server.common.data.kv.TsKvEntry; |
||||
|
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; |
||||
|
import org.thingsboard.server.dao.asset.AssetDao; |
||||
|
import org.thingsboard.server.dao.customer.CustomerDao; |
||||
|
import org.thingsboard.server.dao.dashboard.DashboardDao; |
||||
|
import org.thingsboard.server.dao.device.DeviceDao; |
||||
|
import org.thingsboard.server.dao.tenant.TbTenantProfileCache; |
||||
|
import org.thingsboard.server.dao.timeseries.TimeseriesService; |
||||
|
import org.thingsboard.server.dao.usagerecord.ApiUsageStateService; |
||||
|
import org.thingsboard.server.dao.user.UserDao; |
||||
|
|
||||
|
import java.util.Arrays; |
||||
|
import java.util.Collection; |
||||
|
import java.util.List; |
||||
|
import java.util.Optional; |
||||
|
import java.util.concurrent.ExecutionException; |
||||
|
|
||||
|
@Service |
||||
|
@Slf4j |
||||
|
@RequiredArgsConstructor |
||||
|
public class BasicUsageInfoService implements UsageInfoService { |
||||
|
|
||||
|
private final DeviceDao deviceDao; |
||||
|
private final AssetDao assetDao; |
||||
|
private final CustomerDao customerDao; |
||||
|
private final UserDao userDao; |
||||
|
private final DashboardDao dashboardDao; |
||||
|
private final ApiUsageStateService apiUsageStateService; |
||||
|
private final TimeseriesService tsService; |
||||
|
@Lazy |
||||
|
private final TbTenantProfileCache tenantProfileCache; |
||||
|
|
||||
|
@Override |
||||
|
public UsageInfo getUsageInfo(TenantId tenantId) { |
||||
|
DefaultTenantProfileConfiguration profileConfiguration = |
||||
|
(DefaultTenantProfileConfiguration) tenantProfileCache.get(tenantId).getProfileData().getConfiguration(); |
||||
|
UsageInfo usageInfo = new UsageInfo(); |
||||
|
usageInfo.setDevices(deviceDao.countByTenantId(tenantId)); |
||||
|
usageInfo.setMaxDevices(profileConfiguration.getMaxDevices()); |
||||
|
usageInfo.setAssets(assetDao.countByTenantId(tenantId)); |
||||
|
usageInfo.setMaxAssets(profileConfiguration.getMaxAssets()); |
||||
|
usageInfo.setCustomers(customerDao.countByTenantId(tenantId)); |
||||
|
usageInfo.setMaxCustomers(profileConfiguration.getMaxCustomers()); |
||||
|
usageInfo.setUsers(userDao.countByTenantId(tenantId)); |
||||
|
usageInfo.setMaxUsers(profileConfiguration.getMaxUsers()); |
||||
|
usageInfo.setDashboards(dashboardDao.countByTenantId(tenantId)); |
||||
|
usageInfo.setMaxDashboards(profileConfiguration.getMaxDashboards()); |
||||
|
|
||||
|
usageInfo.setMaxAlarms(profileConfiguration.getMaxCreatedAlarms()); |
||||
|
usageInfo.setMaxTransportMessages(profileConfiguration.getMaxTransportMessages()); |
||||
|
usageInfo.setMaxJsExecutions(profileConfiguration.getMaxJSExecutions()); |
||||
|
usageInfo.setMaxEmails(profileConfiguration.getMaxEmails()); |
||||
|
usageInfo.setMaxSms(profileConfiguration.getMaxSms()); |
||||
|
ApiUsageState apiUsageState = apiUsageStateService.findTenantApiUsageState(tenantId); |
||||
|
if (apiUsageState != null) { |
||||
|
Collection<String> keys = Arrays.asList( |
||||
|
ApiUsageRecordKey.TRANSPORT_MSG_COUNT.getApiCountKey(), |
||||
|
ApiUsageRecordKey.JS_EXEC_COUNT.getApiCountKey(), |
||||
|
ApiUsageRecordKey.EMAIL_EXEC_COUNT.getApiCountKey(), |
||||
|
ApiUsageRecordKey.SMS_EXEC_COUNT.getApiCountKey(), |
||||
|
ApiUsageRecordKey.CREATED_ALARMS_COUNT.getApiCountKey()); |
||||
|
try { |
||||
|
List<TsKvEntry> entries = tsService.findLatest(tenantId, apiUsageState.getId(), keys).get(); |
||||
|
usageInfo.setTransportMessages(getLongValueFromTsEntries(entries, ApiUsageRecordKey.TRANSPORT_MSG_COUNT.getApiCountKey())); |
||||
|
usageInfo.setJsExecutions(getLongValueFromTsEntries(entries, ApiUsageRecordKey.JS_EXEC_COUNT.getApiCountKey())); |
||||
|
usageInfo.setEmails(getLongValueFromTsEntries(entries, ApiUsageRecordKey.EMAIL_EXEC_COUNT.getApiCountKey())); |
||||
|
usageInfo.setSms(getLongValueFromTsEntries(entries, ApiUsageRecordKey.SMS_EXEC_COUNT.getApiCountKey())); |
||||
|
usageInfo.setAlarms(getLongValueFromTsEntries(entries, ApiUsageRecordKey.CREATED_ALARMS_COUNT.getApiCountKey())); |
||||
|
} catch (ExecutionException | InterruptedException e) { |
||||
|
throw new RuntimeException("Failed to fetch api usage values from timeseries!"); |
||||
|
} |
||||
|
} |
||||
|
return usageInfo; |
||||
|
} |
||||
|
|
||||
|
private long getLongValueFromTsEntries(List<TsKvEntry> entries, String key) { |
||||
|
Optional<TsKvEntry> entryOpt = entries.stream().filter(e -> e.getKey().equals(key)).findFirst(); |
||||
|
if (entryOpt.isPresent() && entryOpt.get().getLongValue().isPresent()) { |
||||
|
return entryOpt.get().getLongValue().get(); |
||||
|
} else { |
||||
|
return 0; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue