Merge branch 'master' of github.com:thingsboard/thingsboard
This commit is contained in:
commit
52d23ac224
@ -273,7 +273,8 @@ sql:
|
||||
# Specify whether to remove null characters from strValue of attributes and timeseries before insert
|
||||
remove_null_chars: "${SQL_REMOVE_NULL_CHARS:true}"
|
||||
# Specify whether to log database queries and their parameters generated by entity query repository
|
||||
log_entity_queries: "${SQL_LOG_ENTITY_QUERIES:false}"
|
||||
log_queries: "${SQL_LOG_QUERIES:false}"
|
||||
log_queries_threshold: "${SQL_LOG_QUERIES_THRESHOLD:5000}"
|
||||
postgres:
|
||||
# Specify partitioning size for timestamp key-value storage. Example: DAYS, MONTHS, YEARS, INDEFINITE.
|
||||
ts_key_value_partitioning: "${SQL_POSTGRES_TS_KV_PARTITIONING:MONTHS}"
|
||||
|
||||
@ -43,6 +43,7 @@ import org.thingsboard.server.dao.model.ModelConstants;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@ -114,12 +115,12 @@ public class DefaultAlarmQueryRepository implements AlarmQueryRepository {
|
||||
protected final NamedParameterJdbcTemplate jdbcTemplate;
|
||||
private final TransactionTemplate transactionTemplate;
|
||||
|
||||
@Value("${sql.log_entity_queries:false}")
|
||||
private boolean logSqlQueries;
|
||||
private final DefaultQueryLogComponent queryLog;
|
||||
|
||||
public DefaultAlarmQueryRepository(NamedParameterJdbcTemplate jdbcTemplate, TransactionTemplate transactionTemplate) {
|
||||
public DefaultAlarmQueryRepository(NamedParameterJdbcTemplate jdbcTemplate, TransactionTemplate transactionTemplate, DefaultQueryLogComponent queryLog) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
this.transactionTemplate = transactionTemplate;
|
||||
this.queryLog = queryLog;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -230,8 +231,17 @@ public class DefaultAlarmQueryRepository implements AlarmQueryRepository {
|
||||
if (!textSearchQuery.isEmpty()) {
|
||||
mainQuery = String.format("select * from (%s) a WHERE %s", mainQuery, textSearchQuery);
|
||||
}
|
||||
String countQuery = mainQuery;
|
||||
int totalElements = jdbcTemplate.queryForObject(String.format("select count(*) from (%s) result", countQuery), ctx, Integer.class);
|
||||
String countQuery = String.format("select count(*) from (%s) result", mainQuery);
|
||||
long queryTs = System.currentTimeMillis();
|
||||
int totalElements;
|
||||
try {
|
||||
totalElements = jdbcTemplate.queryForObject(countQuery, ctx, Integer.class);
|
||||
} finally {
|
||||
queryLog.logQuery(ctx, countQuery, System.currentTimeMillis() - queryTs);
|
||||
}
|
||||
if (totalElements == 0) {
|
||||
return AlarmDataAdapter.createAlarmData(pageLink, Collections.emptyList(), totalElements, orderedEntityIds);
|
||||
}
|
||||
|
||||
String dataQuery = mainQuery + sortPart;
|
||||
|
||||
@ -239,10 +249,12 @@ public class DefaultAlarmQueryRepository implements AlarmQueryRepository {
|
||||
if (pageLink.getPageSize() > 0) {
|
||||
dataQuery = String.format("%s limit %s offset %s", dataQuery, pageLink.getPageSize(), startIndex);
|
||||
}
|
||||
List<Map<String, Object>> rows = jdbcTemplate.queryForList(dataQuery, ctx);
|
||||
if (logSqlQueries) {
|
||||
log.info("QUERY: {}", dataQuery);
|
||||
Arrays.asList(ctx.getParameterNames()).forEach(param -> log.info("QUERY PARAM: {}->{}", param, ctx.getValue(param)));
|
||||
queryTs = System.currentTimeMillis();
|
||||
List<Map<String, Object>> rows;
|
||||
try {
|
||||
rows = jdbcTemplate.queryForList(dataQuery, ctx);
|
||||
} finally {
|
||||
queryLog.logQuery(ctx, dataQuery, System.currentTimeMillis() - queryTs);
|
||||
}
|
||||
return AlarmDataAdapter.createAlarmData(pageLink, rows, totalElements, orderedEntityIds);
|
||||
});
|
||||
|
||||
@ -17,12 +17,8 @@ package org.thingsboard.server.dao.sql.query;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
import org.thingsboard.server.common.data.id.CustomerId;
|
||||
@ -237,13 +233,12 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
|
||||
|
||||
private final NamedParameterJdbcTemplate jdbcTemplate;
|
||||
private final TransactionTemplate transactionTemplate;
|
||||
private final DefaultQueryLogComponent queryLog;
|
||||
|
||||
@Value("${sql.log_entity_queries:false}")
|
||||
private boolean logSqlQueries;
|
||||
|
||||
public DefaultEntityQueryRepository(NamedParameterJdbcTemplate jdbcTemplate, TransactionTemplate transactionTemplate) {
|
||||
public DefaultEntityQueryRepository(NamedParameterJdbcTemplate jdbcTemplate, TransactionTemplate transactionTemplate, DefaultQueryLogComponent queryLog) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
this.transactionTemplate = transactionTemplate;
|
||||
this.queryLog = queryLog;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -254,11 +249,14 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
|
||||
ctx.append(addEntityTableQuery(ctx, query.getEntityFilter()));
|
||||
ctx.append(" e where ");
|
||||
ctx.append(buildEntityWhere(ctx, query.getEntityFilter(), Collections.emptyList()));
|
||||
if (logSqlQueries) {
|
||||
log.info("QUERY: {}", ctx.getQuery());
|
||||
Arrays.asList(ctx.getParameterNames()).forEach(param -> log.info("QUERY PARAM: {}->{}", param, ctx.getValue(param)));
|
||||
}
|
||||
return transactionTemplate.execute(status -> jdbcTemplate.queryForObject(ctx.getQuery(), ctx, Long.class));
|
||||
return transactionTemplate.execute(status -> {
|
||||
long startTs = System.currentTimeMillis();
|
||||
try {
|
||||
return jdbcTemplate.queryForObject(ctx.getQuery(), ctx, Long.class);
|
||||
} finally {
|
||||
queryLog.logQuery(ctx, ctx.getQuery(), System.currentTimeMillis() - startTs);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -329,7 +327,14 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
|
||||
fromClauseCount = fromClauseData;
|
||||
}
|
||||
String countQuery = String.format("select count(id) %s", fromClauseCount);
|
||||
int totalElements = jdbcTemplate.queryForObject(countQuery, ctx, Integer.class);
|
||||
|
||||
long startTs = System.currentTimeMillis();
|
||||
int totalElements;
|
||||
try {
|
||||
totalElements = jdbcTemplate.queryForObject(countQuery, ctx, Integer.class);
|
||||
} finally {
|
||||
queryLog.logQuery(ctx, countQuery, System.currentTimeMillis() - startTs);
|
||||
}
|
||||
|
||||
if (totalElements == 0) {
|
||||
return new PageData<>();
|
||||
@ -354,11 +359,13 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
|
||||
if (pageLink.getPageSize() > 0) {
|
||||
dataQuery = String.format("%s limit %s offset %s", dataQuery, pageLink.getPageSize(), startIndex);
|
||||
}
|
||||
if (logSqlQueries) {
|
||||
log.info("QUERY: {}", dataQuery);
|
||||
Arrays.asList(ctx.getParameterNames()).forEach(param -> log.info("QUERY PARAM: {}->{}", param, ctx.getValue(param)));
|
||||
startTs = System.currentTimeMillis();
|
||||
List<Map<String, Object>> rows;
|
||||
try {
|
||||
rows = jdbcTemplate.queryForList(dataQuery, ctx);
|
||||
} finally {
|
||||
queryLog.logQuery(ctx, countQuery, System.currentTimeMillis() - startTs);
|
||||
}
|
||||
List<Map<String, Object>> rows = jdbcTemplate.queryForList(dataQuery, ctx);
|
||||
return EntityDataAdapter.createEntityData(pageLink, selectionMapping, rows, totalElements);
|
||||
});
|
||||
}
|
||||
@ -486,7 +493,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
|
||||
+ SELECT_TYPE + ", " + SELECT_NAME + ", " + SELECT_LABEL + ", " +
|
||||
SELECT_FIRST_NAME + ", " + SELECT_LAST_NAME + ", " + SELECT_EMAIL + ", " + SELECT_REGION + ", " +
|
||||
SELECT_TITLE + ", " + SELECT_COUNTRY + ", " + SELECT_STATE + ", " + SELECT_CITY + ", " +
|
||||
SELECT_ADDRESS + ", " + SELECT_ADDRESS_2 + ", " + SELECT_ZIP + ", " + SELECT_PHONE + ", " + SELECT_ADDITIONAL_INFO +
|
||||
SELECT_ADDRESS + ", " + SELECT_ADDRESS_2 + ", " + SELECT_ZIP + ", " + SELECT_PHONE + ", " + SELECT_ADDITIONAL_INFO +
|
||||
", entity.entity_type as entity_type";
|
||||
String from = getQueryTemplate(entityFilter.getDirection());
|
||||
ctx.addUuidParameter("relation_root_id", rootId.getId());
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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.dao.sql.query;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class DefaultQueryLogComponent implements QueryLogComponent {
|
||||
|
||||
@Value("${sql.log_queries:false}")
|
||||
private boolean logSqlQueries;
|
||||
@Value("${sql.log_queries_threshold:5000}")
|
||||
private long logQueriesThreshold;
|
||||
|
||||
@Override
|
||||
public void logQuery(QueryContext ctx, String query, long duration) {
|
||||
if (logSqlQueries && duration > logQueriesThreshold) {
|
||||
log.info("QUERY: {} took {}ms", query, duration);
|
||||
Arrays.asList(ctx.getParameterNames()).forEach(param -> log.info("QUERY PARAM: {} -> {}", param, ctx.getValue(param)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 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.dao.sql.query;
|
||||
|
||||
public interface QueryLogComponent {
|
||||
|
||||
void logQuery(QueryContext ctx, String query, long duration);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user