Browse Source

Merge pull request #14605 from smatvienko-tb/monitoring-improvements

Monitoring improvements
pull/14642/head
Viacheslav Klimov 6 months ago
committed by GitHub
parent
commit
00abea92dd
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 20
      monitoring/src/main/conf/logback.xml
  2. 7
      monitoring/src/main/conf/tb-monitoring.conf
  3. 50
      monitoring/src/main/java/org/thingsboard/monitoring/ThingsboardMonitoringApplication.java
  4. 27
      monitoring/src/main/java/org/thingsboard/monitoring/data/notification/InfoNotification.java
  5. 29
      monitoring/src/main/java/org/thingsboard/monitoring/notification/NotificationService.java
  6. 122
      monitoring/src/main/java/org/thingsboard/monitoring/service/MonitoringEntityService.java
  7. 580
      monitoring/src/main/resources/dashboard_cloud_monitoring.json
  8. 3
      monitoring/src/main/resources/logback.xml

20
monitoring/src/main/conf/logback.xml

@ -19,20 +19,6 @@
<!DOCTYPE configuration>
<configuration scan="true" scanPeriod="30 seconds">
<appender name="fileLogAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${pkg.logFolder}/${pkg.name}.log</file>
<rollingPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${pkg.logFolder}/${pkg.name}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern>
@ -40,11 +26,11 @@
</appender>
<logger name="org" level="WARN"/>
<logger name="org.thingsboard.monitoring" level="DEBUG"/>
<logger name="org.thingsboard.monitoring.client" level="INFO"/>
<logger name="org.thingsboard.server" level="INFO"/>
<logger name="org.thingsboard.monitoring" level="INFO"/>
<logger name="org.thingsboard.monitoring.client" level="WARN"/>
<root level="INFO">
<appender-ref ref="fileLogAppender"/>
<appender-ref ref="STDOUT"/>
</root>

7
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

50
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<BaseMonitoringService<?, ?>> monitoringServices;
@Autowired
private MonitoringEntityService entityService;
private final List<BaseMonitoringService<?, ?>> 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();
}
}

27
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;
}
}

29
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<? extends Future<?>> 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);
}
}
}

122
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<DashboardInfo> infoOpt = tbClient.getDashboardInfoById(dashboardId);
if (infoOpt.isPresent()) {
String publicCustomerId = null;
Set<ShortCustomerInfo> 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<Dashboard> findDashboardByTitle(String title) {
// Use text search first and then filter by exact title
PageData<DashboardInfo> 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";
}
}
}

580
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
}

3
monitoring/src/main/resources/logback.xml

@ -17,7 +17,7 @@
-->
<!DOCTYPE configuration>
<configuration scan="true" scanPeriod="10 seconds">
<configuration scan="true" scanPeriod="30 seconds">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
@ -34,5 +34,4 @@
<appender-ref ref="STDOUT"/>
</root>
</configuration>

Loading…
Cancel
Save