diff --git a/monitoring/src/main/conf/logback.xml b/monitoring/src/main/conf/logback.xml index 53caafe8bb..43001ffd43 100644 --- a/monitoring/src/main/conf/logback.xml +++ b/monitoring/src/main/conf/logback.xml @@ -19,20 +19,6 @@ - - ${pkg.logFolder}/${pkg.name}.log - - ${pkg.logFolder}/${pkg.name}.%d{yyyy-MM-dd}.%i.log - 100MB - 30 - 3GB - - - %d{ISO8601} [%thread] %-5level %logger{36} - %msg%n - - %d{ISO8601} [%thread] %-5level %logger{36} - %msg%n @@ -40,11 +26,11 @@ - - + + + - diff --git a/monitoring/src/main/conf/tb-monitoring.conf b/monitoring/src/main/conf/tb-monitoring.conf index 493d498cd8..cd2947563f 100644 --- a/monitoring/src/main/conf/tb-monitoring.conf +++ b/monitoring/src/main/conf/tb-monitoring.conf @@ -14,9 +14,10 @@ # limitations under the License. # -export JAVA_OPTS="$JAVA_OPTS -Xlog:gc*,heap*,age*,safepoint=debug:file=/var/log/tb-monitoring/gc.log:time,uptime,level,tags:filecount=10,filesize=10M" +export JAVA_OPTS="$JAVA_OPTS -Xlog:gc*,heap*,age*,safepoint=debug:file=/var/log/tb-monitoring/gc.log:time,uptime,level,tags:filecount=3,filesize=10M" export JAVA_OPTS="$JAVA_OPTS -XX:+IgnoreUnrecognizedVMOptions -XX:+HeapDumpOnOutOfMemoryError" -export JAVA_OPTS="$JAVA_OPTS -XX:-UseBiasedLocking -XX:+UseTLAB -XX:+ResizeTLAB -XX:+PerfDisableSharedMem -XX:+UseCondCardMark" -export JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=500 -XX:+UseStringDeduplication -XX:+ParallelRefProcEnabled -XX:MaxTenuringThreshold=10" +export JAVA_OPTS="$JAVA_OPTS -XX:+UseTLAB -XX:+ResizeTLAB -XX:+PerfDisableSharedMem -XX:+UseCondCardMark" +export JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=50 -XX:+ParallelRefProcEnabled -XX:MaxTenuringThreshold=10" +export JAVA_OPTS="$JAVA_OPTS -XX:+ExitOnOutOfMemoryError" export LOG_FILENAME=tb-monitoring.out export LOADER_PATH=/usr/share/tb-monitoring/conf diff --git a/monitoring/src/main/java/org/thingsboard/monitoring/ThingsboardMonitoringApplication.java b/monitoring/src/main/java/org/thingsboard/monitoring/ThingsboardMonitoringApplication.java index c8e8d7070b..88e9ac1fa3 100644 --- a/monitoring/src/main/java/org/thingsboard/monitoring/ThingsboardMonitoringApplication.java +++ b/monitoring/src/main/java/org/thingsboard/monitoring/ThingsboardMonitoringApplication.java @@ -15,36 +15,43 @@ */ package org.thingsboard.monitoring; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.event.EventListener; +import org.springframework.context.event.ContextClosedEvent; import org.springframework.scheduling.annotation.EnableScheduling; import org.thingsboard.common.util.ThingsBoardExecutors; +import org.thingsboard.monitoring.data.notification.InfoNotification; +import org.thingsboard.monitoring.notification.NotificationService; import org.thingsboard.monitoring.service.BaseMonitoringService; import org.thingsboard.monitoring.service.MonitoringEntityService; +import jakarta.annotation.PreDestroy; import java.util.List; import java.util.Map; +import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @SpringBootApplication @EnableScheduling @Slf4j +@RequiredArgsConstructor public class ThingsboardMonitoringApplication { - @Autowired - private List> monitoringServices; - @Autowired - private MonitoringEntityService entityService; + private final List> monitoringServices; + private final MonitoringEntityService entityService; + private final NotificationService notificationService; @Value("${monitoring.monitoring_rate_ms}") private int monitoringRateMs; + ScheduledExecutorService scheduler = ThingsBoardExecutors.newSingleThreadScheduledExecutor("monitoring"); + public static void main(String[] args) { new SpringApplicationBuilder(ThingsboardMonitoringApplication.class) .properties(Map.of("spring.config.name", "tb-monitoring")) @@ -56,12 +63,33 @@ public class ThingsboardMonitoringApplication { entityService.checkEntities(); monitoringServices.forEach(BaseMonitoringService::init); - ScheduledExecutorService scheduler = ThingsBoardExecutors.newSingleThreadScheduledExecutor("monitoring-executor"); - scheduler.scheduleWithFixedDelay(() -> { - monitoringServices.forEach(monitoringService -> { - monitoringService.runChecks(); - }); - }, 0, monitoringRateMs, TimeUnit.MILLISECONDS); + for (int i = 0; i < monitoringServices.size(); i++) { + int initialDelay = (monitoringRateMs / monitoringServices.size()) * i; + BaseMonitoringService service = monitoringServices.get(i); + log.info("Scheduling initialDelay {}, fixedDelay {} for monitoring '{}' ", initialDelay, monitoringRateMs, service.getClass().getSimpleName()); + scheduler.scheduleWithFixedDelay(service::runChecks, initialDelay, monitoringRateMs, TimeUnit.MILLISECONDS); + } + + String publicDashboardUrl = entityService.getDashboardPublicLink(); + notificationService.sendNotification(new InfoNotification(":rocket: <"+publicDashboardUrl+"|Monitoring> started")); + } + + @EventListener(ContextClosedEvent.class) + public void onShutdown(ContextClosedEvent event) { + log.info("Shutting down monitoring service"); + try { + var futures = notificationService.sendNotification(new InfoNotification(":warning: Monitoring is shutting down")); + for (Future future : futures) { + future.get(5, TimeUnit.SECONDS); + } + } catch (Exception e) { + log.warn("Failed to send shutdown notification", e); + } + } + + @PreDestroy + public void shutdownScheduler() { + scheduler.shutdown(); } } diff --git a/monitoring/src/main/java/org/thingsboard/monitoring/data/notification/InfoNotification.java b/monitoring/src/main/java/org/thingsboard/monitoring/data/notification/InfoNotification.java new file mode 100644 index 0000000000..6aa42cbf2b --- /dev/null +++ b/monitoring/src/main/java/org/thingsboard/monitoring/data/notification/InfoNotification.java @@ -0,0 +1,27 @@ +/** + * Copyright © 2016-2025 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.monitoring.data.notification; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class InfoNotification implements Notification { + private final String message; + @Override + public String getText() { + return message; + } +} diff --git a/monitoring/src/main/java/org/thingsboard/monitoring/notification/NotificationService.java b/monitoring/src/main/java/org/thingsboard/monitoring/notification/NotificationService.java index 5e4dcb2f34..36529822b1 100644 --- a/monitoring/src/main/java/org/thingsboard/monitoring/notification/NotificationService.java +++ b/monitoring/src/main/java/org/thingsboard/monitoring/notification/NotificationService.java @@ -22,10 +22,13 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.thingsboard.monitoring.data.notification.Notification; import org.thingsboard.monitoring.notification.channels.NotificationChannel; +import jakarta.annotation.PreDestroy; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; @Component @RequiredArgsConstructor @@ -38,22 +41,38 @@ public class NotificationService { @Value("${monitoring.notifications.message_prefix}") private String messagePrefix; - public void sendNotification(Notification notification) { + public List> sendNotification(Notification notification) { String message; if (StringUtils.isEmpty(messagePrefix)) { message = notification.getText(); } else { - message = messagePrefix + System.lineSeparator() + notification.getText(); + message = messagePrefix + " " + notification.getText(); } - notificationChannels.forEach(notificationChannel -> { + return notificationChannels.stream().map(notificationChannel -> notificationExecutor.submit(() -> { try { notificationChannel.sendNotification(message); } catch (Exception e) { log.error("Failed to send notification to {}", notificationChannel.getClass().getSimpleName(), e); } - }); - }); + }) + ).toList(); } + @PreDestroy + public void shutdownExecutor() { + try { + notificationExecutor.shutdown(); + if (!notificationExecutor.awaitTermination(10, TimeUnit.SECONDS)) { + var dropped = notificationExecutor.shutdownNow(); + log.warn("Notification executor did not terminate in time. Forced shutdown; {} task(s) will not be executed.", dropped.size()); + } + } catch (InterruptedException e) { + var dropped = notificationExecutor.shutdownNow(); + Thread.currentThread().interrupt(); + log.warn("Interrupted during notification executor shutdown. Forced shutdown; {} task(s) will not be executed.", dropped.size()); + } catch (Exception e) { + log.warn("Unexpected error while shutting down notification executor", e); + } + } } diff --git a/monitoring/src/main/java/org/thingsboard/monitoring/service/MonitoringEntityService.java b/monitoring/src/main/java/org/thingsboard/monitoring/service/MonitoringEntityService.java index d2cf076516..f667192cf2 100644 --- a/monitoring/src/main/java/org/thingsboard/monitoring/service/MonitoringEntityService.java +++ b/monitoring/src/main/java/org/thingsboard/monitoring/service/MonitoringEntityService.java @@ -30,13 +30,19 @@ import org.thingsboard.monitoring.config.transport.TransportMonitoringTarget; import org.thingsboard.monitoring.config.transport.TransportType; import org.thingsboard.monitoring.util.ResourceUtils; import org.thingsboard.server.common.data.DataConstants; +import org.thingsboard.server.common.data.Dashboard; +import org.thingsboard.server.common.data.DashboardInfo; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfileType; import org.thingsboard.server.common.data.DeviceTransportType; +import org.thingsboard.server.common.data.ShortCustomerInfo; import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.cf.CalculatedField; +import org.thingsboard.server.common.data.id.DashboardId; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.cf.CalculatedFieldType; import org.thingsboard.server.common.data.cf.configuration.Argument; import org.thingsboard.server.common.data.cf.configuration.ArgumentType; @@ -56,7 +62,6 @@ import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTra import org.thingsboard.server.common.data.device.profile.DeviceProfileData; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.kv.KvEntry; -import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleChainType; @@ -65,6 +70,8 @@ import org.thingsboard.server.common.data.security.DeviceCredentialsType; import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; import static org.thingsboard.monitoring.service.BaseHealthChecker.TEST_CF_TELEMETRY_KEY; @@ -75,11 +82,16 @@ import static org.thingsboard.monitoring.service.BaseHealthChecker.TEST_TELEMETR @RequiredArgsConstructor public class MonitoringEntityService { + private static final String DASHBOARD_TITLE = "[Monitoring] Cloud monitoring"; + private static final String DASHBOARD_RESOURCE_PATH = "dashboard_cloud_monitoring.json"; + private final TbClient tbClient; @Value("${monitoring.calculated_fields.enabled:true}") private boolean calculatedFieldsMonitoringEnabled; + DashboardId dashboardId = null; + public void checkEntities() { RuleChain ruleChain = tbClient.getRuleChains(RuleChainType.CORE, new PageLink(10)).getData().stream() .filter(RuleChain::isRoot) @@ -94,27 +106,34 @@ public class MonitoringEntityService { int currentVersion = Integer.parseInt(attributes.getOrDefault("version", "0")); int newVersion = ruleChainDescriptor.get("version").asInt(); if (currentVersion == newVersion) { - log.info("Not updating rule chain, version is the same ({})", currentVersion); - return; + log.debug("Not updating rule chain, version is the same ({})", currentVersion); } else { log.info("Updating rule chain '{}' from version {} to {}", ruleChain.getName(), currentVersion, newVersion); + + String metadataJson = RegexUtils.replace(ruleChainDescriptor.get("metadata").toString(), + "\\$\\{MONITORING:(.+?)}", matchResult -> { + String key = matchResult.group(1); + String value = attributes.get(key); + if (value == null) { + throw new IllegalArgumentException("No attribute found for key " + key); + } + log.info("Using {}: {}", key, value); + return value; + }); + RuleChainMetaData metaData = JacksonUtil.fromString(metadataJson, RuleChainMetaData.class); + metaData.setRuleChainId(ruleChainId); + tbClient.saveRuleChainMetaData(metaData); + tbClient.saveEntityAttributesV2(ruleChainId, DataConstants.SERVER_SCOPE, JacksonUtil.newObjectNode() + .put("version", newVersion)); } - String metadataJson = RegexUtils.replace(ruleChainDescriptor.get("metadata").toString(), - "\\$\\{MONITORING:(.+?)}", matchResult -> { - String key = matchResult.group(1); - String value = attributes.get(key); - if (value == null) { - throw new IllegalArgumentException("No attribute found for key " + key); - } - log.info("Using {}: {}", key, value); - return value; - }); - RuleChainMetaData metaData = JacksonUtil.fromString(metadataJson, RuleChainMetaData.class); - metaData.setRuleChainId(ruleChainId); - tbClient.saveRuleChainMetaData(metaData); - tbClient.saveEntityAttributesV2(ruleChainId, DataConstants.SERVER_SCOPE, JacksonUtil.newObjectNode() - .put("version", newVersion)); + Asset asset = getOrCreateMonitoringAsset(); + Dashboard dashboard = getOrCreateMonitoringDashboard(); + + tbClient.assignAssetToPublicCustomer(asset.getId()); + tbClient.assignDashboardToPublicCustomer(dashboard.getId()); + + this.dashboardId = Optional.ofNullable(dashboard).map(Dashboard::getId).orElse(null); } public Asset getOrCreateMonitoringAsset() { @@ -246,4 +265,71 @@ public class MonitoringEntityService { tbClient.saveCalculatedField(calculatedField); } + public String getDashboardPublicLink() { + String link = ""; + try { + Optional infoOpt = tbClient.getDashboardInfoById(dashboardId); + if (infoOpt.isPresent()) { + String publicCustomerId = null; + Set customers = infoOpt.get().getAssignedCustomers(); + if (customers != null) { + publicCustomerId = customers.stream() + .filter(ShortCustomerInfo::isPublic) + .map(c -> c.getCustomerId().getId().toString()) + .findFirst().orElse(null); + } + if (publicCustomerId != null) { + link = buildPublicDashboardLink(dashboardId, publicCustomerId); + log.info("Public Monitoring dashboard link: {}", link); + } else { + log.warn("Dashboard is not assigned to public customer. Public link can't be generated."); + } + } + } catch (Exception e) { + log.error("Failed to get a public link to Monitoring dashboard ", e); + } + return link; + } + + private Dashboard getOrCreateMonitoringDashboard() { + Dashboard existing = findDashboardByTitle(DASHBOARD_TITLE).orElse(null); + if (existing != null) { + log.debug("Found Monitoring dashboard '{}' with id {}", existing.getTitle(), existing.getId()); + return existing; + } + + Dashboard dashboardFromResource = ResourceUtils.getResource(DASHBOARD_RESOURCE_PATH, Dashboard.class); + dashboardFromResource.setTitle(DASHBOARD_TITLE); + //Optional.ofNullable(existing).map(Dashboard::getId).ifPresent(dashboardFromResource::setId); + Dashboard saved = tbClient.saveDashboard(dashboardFromResource); + log.info("Created Monitoring dashboard '{}' with id {}", saved.getTitle(), saved.getId()); + return saved; + } + + private Optional findDashboardByTitle(String title) { + // Use text search first and then filter by exact title + PageData page = tbClient.getTenantDashboards(new PageLink(10, 0, title)); + return page.getData().stream() + .filter(info -> title.equals(info.getTitle())) + .findFirst() + .flatMap(info -> tbClient.getDashboardById(info.getId())); + } + + private String buildPublicDashboardLink(DashboardId dashboardId, String publicCustomerId) { + String base = getBaseUrl(); + return String.format("%s/dashboard/%s?publicId=%s", base, dashboardId.getId().toString(), publicCustomerId); + } + + private String getBaseUrl() { + // TbClient.baseURL contains the root url, without trailing slash + try { + var baseUrlField = tbClient.getClass().getSuperclass().getDeclaredField("baseURL"); + baseUrlField.setAccessible(true); + return (String) baseUrlField.get(tbClient); + } catch (Exception e) { + log.warn("Unable to access baseURL from RestClient. Falling back to http://localhost:8080"); + return "http://localhost:8080"; + } + } + } diff --git a/monitoring/src/main/resources/dashboard_cloud_monitoring.json b/monitoring/src/main/resources/dashboard_cloud_monitoring.json new file mode 100644 index 0000000000..8be9677c61 --- /dev/null +++ b/monitoring/src/main/resources/dashboard_cloud_monitoring.json @@ -0,0 +1,580 @@ +{ + "title": "Cloud - Monitoring", + "image": null, + "mobileHide": false, + "mobileOrder": null, + "configuration": { + "description": "", + "widgets": { + "7db7f580-2aac-d7ee-20f6-3d9315e7003f": { + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "6451461f-d748-9528-e3cd-64078c7fae05", + "filterId": null, + "dataKeys": [ + { + "name": "arrivalLatency", + "type": "timeseries", + "label": "Arrival latency", + "color": "#ffc107", + "settings": {}, + "_hash": 0.7424467450112592, + "aggregationType": null, + "units": "ms", + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "processingTime", + "type": "timeseries", + "label": "Processing time", + "color": "#607d8b", + "settings": {}, + "_hash": 0.6065128737901203, + "aggregationType": null, + "units": "ms", + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "mqttTransportWsUpdateLatency", + "type": "timeseries", + "label": "MQTT - overall", + "color": "#f44336", + "settings": {}, + "_hash": 0.19638031054010696, + "aggregationType": null, + "units": "ms", + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "coapTransportWsUpdateLatency", + "type": "timeseries", + "label": "CoAP - overall", + "color": "#9c27b0", + "settings": {}, + "_hash": 0.8167481665043521, + "aggregationType": null, + "units": "ms", + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "httpTransportWsUpdateLatency", + "type": "timeseries", + "label": "HTTP - overall", + "color": "#8bc34a", + "settings": {}, + "_hash": 0.45369210935861803, + "aggregationType": null, + "units": "ms", + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "lwm2mTransportWsUpdateLatency", + "type": "timeseries", + "label": "LwM2M - overall", + "color": "#3f51b5", + "settings": {}, + "_hash": 0.3477627917073993, + "aggregationType": null, + "units": "ms", + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "coapIntegrationWsUpdateLatency", + "type": "timeseries", + "label": "CoAP integration - overall", + "color": "#e91e63", + "settings": {}, + "_hash": 0.8332881819050183, + "aggregationType": null, + "units": "ms", + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "wsSubscribeLatency", + "type": "timeseries", + "label": "WS subscribe latency", + "color": "#03a9f4", + "settings": {}, + "_hash": 0.7843180730206556, + "aggregationType": null, + "units": "ms", + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "wsConnectLatency", + "type": "timeseries", + "label": "WS connect latency", + "color": "#4caf50", + "settings": { + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "excludeFromStacking": false, + "showLines": true, + "lineWidth": 1, + "fillLines": false, + "showPoints": false, + "tooltipValueFormatter": "", + "showSeparateAxis": false, + "axisTitle": "", + "axisMin": null, + "axisMax": null, + "axisPosition": "left", + "axisTickSize": null, + "axisTickDecimals": null, + "axisTicksFormatter": "", + "comparisonSettings": { + "showValuesForComparison": true, + "comparisonValuesLabel": "", + "color": "" + }, + "thresholds": [] + }, + "_hash": 0.23140687573220564, + "aggregationType": null, + "units": "ms", + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "logInLatency", + "type": "timeseries", + "label": "Log in latency", + "color": "#2196f3", + "settings": { + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "excludeFromStacking": false, + "showLines": true, + "lineWidth": 1, + "fillLines": false, + "showPoints": false, + "tooltipValueFormatter": "", + "showSeparateAxis": false, + "axisTitle": "", + "axisMin": null, + "axisMax": null, + "axisPosition": "left", + "axisTickSize": null, + "axisTickDecimals": null, + "axisTicksFormatter": "", + "comparisonSettings": { + "showValuesForComparison": true, + "comparisonValuesLabel": "", + "color": "" + }, + "thresholds": [] + }, + "_hash": 0.6130919996800452, + "aggregationType": null, + "units": "ms", + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + }, + "latestDataKeys": [] + } + ], + "timewindow": { + "realtime": { + "timewindowMs": 60000 + } + }, + "showTitle": true, + "backgroundColor": "#fff", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "8px", + "settings": { + "stack": false, + "fontSize": 10, + "fontColor": "#545454", + "showTooltip": true, + "tooltipIndividual": false, + "tooltipCumulative": false, + "hideZeros": false, + "grid": { + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1, + "color": "#545454", + "backgroundColor": null, + "tickColor": "#DDDDDD" + }, + "xaxis": { + "title": null, + "showLabels": true, + "color": "#545454" + }, + "yaxis": { + "min": null, + "max": null, + "title": null, + "showLabels": true, + "color": "#545454", + "tickSize": null, + "tickDecimals": 0, + "ticksFormatter": "" + }, + "shadowSize": 4, + "smoothLines": false, + "comparisonEnabled": false, + "timeForComparison": "previousInterval", + "comparisonCustomIntervalValue": 7200000, + "xaxisSecond": { + "axisPosition": "top", + "title": null, + "showLabels": true + }, + "customLegendEnabled": false, + "dataKeysListForLabels": [], + "showLegend": true, + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": true, + "showAvg": true, + "showTotal": false, + "showLatest": true + } + }, + "title": "General latencies", + "dropShadow": false, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "useDashboardTimewindow": true, + "showTitleIcon": false, + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "noDataDisplayMessage": "", + "enableDataExport": true, + "displayTimewindow": true + }, + "row": 0, + "col": 0, + "id": "7db7f580-2aac-d7ee-20f6-3d9315e7003f", + "typeFullFqn": "system.charts.basic_timeseries" + }, + "e0a2df43-2f9a-efcf-80f7-bf51b0a174e1": { + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "6451461f-d748-9528-e3cd-64078c7fae05", + "filterId": null, + "dataKeys": [ + { + "name": "mqttTransportRequestLatency", + "type": "timeseries", + "label": "MQTT transport request latency", + "color": "#2196f3", + "settings": {}, + "_hash": 0.8576659620523571, + "aggregationType": null, + "units": "ms", + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "httpTransportRequestLatency", + "type": "timeseries", + "label": "HTTP transport request latency", + "color": "#4caf50", + "settings": {}, + "_hash": 0.9749033105491403, + "aggregationType": null, + "units": "ms", + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "coapTransportRequestLatency", + "type": "timeseries", + "label": "CoAP transport request latency", + "color": "#f44336", + "settings": {}, + "_hash": 0.6977575200148037, + "aggregationType": null, + "units": "ms", + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "coapIntegrationRequestLatency", + "type": "timeseries", + "label": "CoAP integration request latency", + "color": "#9c27b0", + "settings": {}, + "_hash": 0.18839685494200875, + "aggregationType": null, + "units": "ms", + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "lwm2mTransportRequestLatency", + "type": "timeseries", + "label": "LwM2M transport request latency", + "color": "#ffc107", + "settings": { + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "excludeFromStacking": false, + "showLines": true, + "lineWidth": 1, + "fillLines": false, + "showPoints": false, + "tooltipValueFormatter": "", + "showSeparateAxis": false, + "axisTitle": "", + "axisMin": null, + "axisMax": null, + "axisPosition": "left", + "axisTickSize": null, + "axisTickDecimals": null, + "axisTicksFormatter": "", + "comparisonSettings": { + "showValuesForComparison": true, + "comparisonValuesLabel": "", + "color": "" + }, + "thresholds": [] + }, + "_hash": 0.85549409179514, + "aggregationType": null, + "units": "ms", + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + }, + "latestDataKeys": [] + } + ], + "timewindow": { + "realtime": { + "timewindowMs": 60000 + } + }, + "showTitle": true, + "backgroundColor": "#fff", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "8px", + "settings": { + "shadowSize": 4, + "fontColor": "#545454", + "fontSize": 10, + "xaxis": { + "showLabels": true, + "color": "#545454" + }, + "yaxis": { + "showLabels": true, + "color": "#545454" + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "legend": { + "show": true, + "position": "nw", + "backgroundColor": "#f0f0f0", + "backgroundOpacity": 0.85, + "labelBoxBorderColor": "rgba(1, 1, 1, 0.45)" + }, + "decimals": 1, + "stack": false, + "tooltipIndividual": false, + "showLegend": true, + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": true, + "showAvg": true, + "showTotal": false, + "showLatest": true + } + }, + "title": "Transport latencies", + "dropShadow": false, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "useDashboardTimewindow": true, + "showTitleIcon": false, + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "noDataDisplayMessage": "", + "enableDataExport": true, + "displayTimewindow": true + }, + "row": 0, + "col": 0, + "id": "e0a2df43-2f9a-efcf-80f7-bf51b0a174e1", + "typeFullFqn": "system.charts.basic_timeseries" + } + }, + "states": { + "default": { + "name": "Cloud - Monitoring", + "root": true, + "layouts": { + "main": { + "widgets": { + "7db7f580-2aac-d7ee-20f6-3d9315e7003f": { + "sizeX": 12, + "sizeY": 11, + "row": 0, + "col": 0 + }, + "e0a2df43-2f9a-efcf-80f7-bf51b0a174e1": { + "sizeX": 12, + "sizeY": 11, + "row": 0, + "col": 12 + } + }, + "gridSettings": { + "backgroundColor": "#eeeeee", + "columns": 24, + "margin": 10, + "backgroundSizeMode": "100%", + "outerMargin": true, + "layoutType": "default" + } + } + } + } + }, + "entityAliases": { + "6451461f-d748-9528-e3cd-64078c7fae05": { + "id": "6451461f-d748-9528-e3cd-64078c7fae05", + "alias": "Monitoring stats asset", + "filter": { + "type": "entityName", + "resolveMultiple": true, + "entityType": "ASSET", + "entityNameFilter": "[Monitoring] Latencies" + } + } + }, + "filters": {}, + "timewindow": { + "hideAggregation": false, + "hideAggInterval": false, + "hideTimezone": false, + "selectedTab": 0, + "realtime": { + "realtimeType": 0, + "interval": 120000, + "timewindowMs": 18000000, + "quickInterval": "CURRENT_DAY", + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false + }, + "history": { + "historyType": 0, + "interval": 600000, + "timewindowMs": 43200000, + "fixedTimewindow": null, + "quickInterval": "CURRENT_DAY", + "hideInterval": false, + "hideLastInterval": false, + "hideFixedInterval": false, + "hideQuickInterval": false + }, + "aggregation": { + "type": "AVG", + "limit": 2500 + }, + "timezone": null + }, + "settings": { + "stateControllerId": "entity", + "showTitle": false, + "showDashboardsSelect": true, + "showEntitiesSelect": true, + "showDashboardTimewindow": true, + "showDashboardExport": true, + "toolbarAlwaysOpen": true + } + }, + "name": "Cloud - Monitoring", + "resources": null +} \ No newline at end of file diff --git a/monitoring/src/main/resources/logback.xml b/monitoring/src/main/resources/logback.xml index df3a7224c6..43001ffd43 100644 --- a/monitoring/src/main/resources/logback.xml +++ b/monitoring/src/main/resources/logback.xml @@ -17,7 +17,7 @@ --> - + @@ -34,5 +34,4 @@ -