Commit 52d23ac224f43323e60e4cd2a87cf74597e5e3ba
Merge branch 'master' of github.com:thingsboard/thingsboard
Showing
5 changed files
with
110 additions
and
29 deletions
@@ -273,7 +273,8 @@ sql: | @@ -273,7 +273,8 @@ sql: | ||
273 | # Specify whether to remove null characters from strValue of attributes and timeseries before insert | 273 | # Specify whether to remove null characters from strValue of attributes and timeseries before insert |
274 | remove_null_chars: "${SQL_REMOVE_NULL_CHARS:true}" | 274 | remove_null_chars: "${SQL_REMOVE_NULL_CHARS:true}" |
275 | # Specify whether to log database queries and their parameters generated by entity query repository | 275 | # Specify whether to log database queries and their parameters generated by entity query repository |
276 | - log_entity_queries: "${SQL_LOG_ENTITY_QUERIES:false}" | 276 | + log_queries: "${SQL_LOG_QUERIES:false}" |
277 | + log_queries_threshold: "${SQL_LOG_QUERIES_THRESHOLD:5000}" | ||
277 | postgres: | 278 | postgres: |
278 | # Specify partitioning size for timestamp key-value storage. Example: DAYS, MONTHS, YEARS, INDEFINITE. | 279 | # Specify partitioning size for timestamp key-value storage. Example: DAYS, MONTHS, YEARS, INDEFINITE. |
279 | ts_key_value_partitioning: "${SQL_POSTGRES_TS_KV_PARTITIONING:MONTHS}" | 280 | ts_key_value_partitioning: "${SQL_POSTGRES_TS_KV_PARTITIONING:MONTHS}" |
@@ -43,6 +43,7 @@ import org.thingsboard.server.dao.model.ModelConstants; | @@ -43,6 +43,7 @@ import org.thingsboard.server.dao.model.ModelConstants; | ||
43 | import java.util.ArrayList; | 43 | import java.util.ArrayList; |
44 | import java.util.Arrays; | 44 | import java.util.Arrays; |
45 | import java.util.Collection; | 45 | import java.util.Collection; |
46 | +import java.util.Collections; | ||
46 | import java.util.HashMap; | 47 | import java.util.HashMap; |
47 | import java.util.HashSet; | 48 | import java.util.HashSet; |
48 | import java.util.List; | 49 | import java.util.List; |
@@ -114,12 +115,12 @@ public class DefaultAlarmQueryRepository implements AlarmQueryRepository { | @@ -114,12 +115,12 @@ public class DefaultAlarmQueryRepository implements AlarmQueryRepository { | ||
114 | protected final NamedParameterJdbcTemplate jdbcTemplate; | 115 | protected final NamedParameterJdbcTemplate jdbcTemplate; |
115 | private final TransactionTemplate transactionTemplate; | 116 | private final TransactionTemplate transactionTemplate; |
116 | 117 | ||
117 | - @Value("${sql.log_entity_queries:false}") | ||
118 | - private boolean logSqlQueries; | 118 | + private final DefaultQueryLogComponent queryLog; |
119 | 119 | ||
120 | - public DefaultAlarmQueryRepository(NamedParameterJdbcTemplate jdbcTemplate, TransactionTemplate transactionTemplate) { | 120 | + public DefaultAlarmQueryRepository(NamedParameterJdbcTemplate jdbcTemplate, TransactionTemplate transactionTemplate, DefaultQueryLogComponent queryLog) { |
121 | this.jdbcTemplate = jdbcTemplate; | 121 | this.jdbcTemplate = jdbcTemplate; |
122 | this.transactionTemplate = transactionTemplate; | 122 | this.transactionTemplate = transactionTemplate; |
123 | + this.queryLog = queryLog; | ||
123 | } | 124 | } |
124 | 125 | ||
125 | @Override | 126 | @Override |
@@ -230,8 +231,17 @@ public class DefaultAlarmQueryRepository implements AlarmQueryRepository { | @@ -230,8 +231,17 @@ public class DefaultAlarmQueryRepository implements AlarmQueryRepository { | ||
230 | if (!textSearchQuery.isEmpty()) { | 231 | if (!textSearchQuery.isEmpty()) { |
231 | mainQuery = String.format("select * from (%s) a WHERE %s", mainQuery, textSearchQuery); | 232 | mainQuery = String.format("select * from (%s) a WHERE %s", mainQuery, textSearchQuery); |
232 | } | 233 | } |
233 | - String countQuery = mainQuery; | ||
234 | - int totalElements = jdbcTemplate.queryForObject(String.format("select count(*) from (%s) result", countQuery), ctx, Integer.class); | 234 | + String countQuery = String.format("select count(*) from (%s) result", mainQuery); |
235 | + long queryTs = System.currentTimeMillis(); | ||
236 | + int totalElements; | ||
237 | + try { | ||
238 | + totalElements = jdbcTemplate.queryForObject(countQuery, ctx, Integer.class); | ||
239 | + } finally { | ||
240 | + queryLog.logQuery(ctx, countQuery, System.currentTimeMillis() - queryTs); | ||
241 | + } | ||
242 | + if (totalElements == 0) { | ||
243 | + return AlarmDataAdapter.createAlarmData(pageLink, Collections.emptyList(), totalElements, orderedEntityIds); | ||
244 | + } | ||
235 | 245 | ||
236 | String dataQuery = mainQuery + sortPart; | 246 | String dataQuery = mainQuery + sortPart; |
237 | 247 | ||
@@ -239,10 +249,12 @@ public class DefaultAlarmQueryRepository implements AlarmQueryRepository { | @@ -239,10 +249,12 @@ public class DefaultAlarmQueryRepository implements AlarmQueryRepository { | ||
239 | if (pageLink.getPageSize() > 0) { | 249 | if (pageLink.getPageSize() > 0) { |
240 | dataQuery = String.format("%s limit %s offset %s", dataQuery, pageLink.getPageSize(), startIndex); | 250 | dataQuery = String.format("%s limit %s offset %s", dataQuery, pageLink.getPageSize(), startIndex); |
241 | } | 251 | } |
242 | - List<Map<String, Object>> rows = jdbcTemplate.queryForList(dataQuery, ctx); | ||
243 | - if (logSqlQueries) { | ||
244 | - log.info("QUERY: {}", dataQuery); | ||
245 | - Arrays.asList(ctx.getParameterNames()).forEach(param -> log.info("QUERY PARAM: {}->{}", param, ctx.getValue(param))); | 252 | + queryTs = System.currentTimeMillis(); |
253 | + List<Map<String, Object>> rows; | ||
254 | + try { | ||
255 | + rows = jdbcTemplate.queryForList(dataQuery, ctx); | ||
256 | + } finally { | ||
257 | + queryLog.logQuery(ctx, dataQuery, System.currentTimeMillis() - queryTs); | ||
246 | } | 258 | } |
247 | return AlarmDataAdapter.createAlarmData(pageLink, rows, totalElements, orderedEntityIds); | 259 | return AlarmDataAdapter.createAlarmData(pageLink, rows, totalElements, orderedEntityIds); |
248 | }); | 260 | }); |
@@ -17,12 +17,8 @@ package org.thingsboard.server.dao.sql.query; | @@ -17,12 +17,8 @@ package org.thingsboard.server.dao.sql.query; | ||
17 | 17 | ||
18 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
19 | import org.apache.commons.lang3.StringUtils; | 19 | import org.apache.commons.lang3.StringUtils; |
20 | -import org.springframework.beans.factory.annotation.Autowired; | ||
21 | -import org.springframework.beans.factory.annotation.Value; | ||
22 | import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; | 20 | import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; |
23 | import org.springframework.stereotype.Repository; | 21 | import org.springframework.stereotype.Repository; |
24 | -import org.springframework.transaction.TransactionStatus; | ||
25 | -import org.springframework.transaction.support.TransactionCallback; | ||
26 | import org.springframework.transaction.support.TransactionTemplate; | 22 | import org.springframework.transaction.support.TransactionTemplate; |
27 | import org.thingsboard.server.common.data.EntityType; | 23 | import org.thingsboard.server.common.data.EntityType; |
28 | import org.thingsboard.server.common.data.id.CustomerId; | 24 | import org.thingsboard.server.common.data.id.CustomerId; |
@@ -237,13 +233,12 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { | @@ -237,13 +233,12 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { | ||
237 | 233 | ||
238 | private final NamedParameterJdbcTemplate jdbcTemplate; | 234 | private final NamedParameterJdbcTemplate jdbcTemplate; |
239 | private final TransactionTemplate transactionTemplate; | 235 | private final TransactionTemplate transactionTemplate; |
236 | + private final DefaultQueryLogComponent queryLog; | ||
240 | 237 | ||
241 | - @Value("${sql.log_entity_queries:false}") | ||
242 | - private boolean logSqlQueries; | ||
243 | - | ||
244 | - public DefaultEntityQueryRepository(NamedParameterJdbcTemplate jdbcTemplate, TransactionTemplate transactionTemplate) { | 238 | + public DefaultEntityQueryRepository(NamedParameterJdbcTemplate jdbcTemplate, TransactionTemplate transactionTemplate, DefaultQueryLogComponent queryLog) { |
245 | this.jdbcTemplate = jdbcTemplate; | 239 | this.jdbcTemplate = jdbcTemplate; |
246 | this.transactionTemplate = transactionTemplate; | 240 | this.transactionTemplate = transactionTemplate; |
241 | + this.queryLog = queryLog; | ||
247 | } | 242 | } |
248 | 243 | ||
249 | @Override | 244 | @Override |
@@ -254,11 +249,14 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { | @@ -254,11 +249,14 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { | ||
254 | ctx.append(addEntityTableQuery(ctx, query.getEntityFilter())); | 249 | ctx.append(addEntityTableQuery(ctx, query.getEntityFilter())); |
255 | ctx.append(" e where "); | 250 | ctx.append(" e where "); |
256 | ctx.append(buildEntityWhere(ctx, query.getEntityFilter(), Collections.emptyList())); | 251 | ctx.append(buildEntityWhere(ctx, query.getEntityFilter(), Collections.emptyList())); |
257 | - if (logSqlQueries) { | ||
258 | - log.info("QUERY: {}", ctx.getQuery()); | ||
259 | - Arrays.asList(ctx.getParameterNames()).forEach(param -> log.info("QUERY PARAM: {}->{}", param, ctx.getValue(param))); | ||
260 | - } | ||
261 | - return transactionTemplate.execute(status -> jdbcTemplate.queryForObject(ctx.getQuery(), ctx, Long.class)); | 252 | + return transactionTemplate.execute(status -> { |
253 | + long startTs = System.currentTimeMillis(); | ||
254 | + try { | ||
255 | + return jdbcTemplate.queryForObject(ctx.getQuery(), ctx, Long.class); | ||
256 | + } finally { | ||
257 | + queryLog.logQuery(ctx, ctx.getQuery(), System.currentTimeMillis() - startTs); | ||
258 | + } | ||
259 | + }); | ||
262 | } | 260 | } |
263 | 261 | ||
264 | @Override | 262 | @Override |
@@ -329,7 +327,14 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { | @@ -329,7 +327,14 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { | ||
329 | fromClauseCount = fromClauseData; | 327 | fromClauseCount = fromClauseData; |
330 | } | 328 | } |
331 | String countQuery = String.format("select count(id) %s", fromClauseCount); | 329 | String countQuery = String.format("select count(id) %s", fromClauseCount); |
332 | - int totalElements = jdbcTemplate.queryForObject(countQuery, ctx, Integer.class); | 330 | + |
331 | + long startTs = System.currentTimeMillis(); | ||
332 | + int totalElements; | ||
333 | + try { | ||
334 | + totalElements = jdbcTemplate.queryForObject(countQuery, ctx, Integer.class); | ||
335 | + } finally { | ||
336 | + queryLog.logQuery(ctx, countQuery, System.currentTimeMillis() - startTs); | ||
337 | + } | ||
333 | 338 | ||
334 | if (totalElements == 0) { | 339 | if (totalElements == 0) { |
335 | return new PageData<>(); | 340 | return new PageData<>(); |
@@ -354,11 +359,13 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { | @@ -354,11 +359,13 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { | ||
354 | if (pageLink.getPageSize() > 0) { | 359 | if (pageLink.getPageSize() > 0) { |
355 | dataQuery = String.format("%s limit %s offset %s", dataQuery, pageLink.getPageSize(), startIndex); | 360 | dataQuery = String.format("%s limit %s offset %s", dataQuery, pageLink.getPageSize(), startIndex); |
356 | } | 361 | } |
357 | - if (logSqlQueries) { | ||
358 | - log.info("QUERY: {}", dataQuery); | ||
359 | - Arrays.asList(ctx.getParameterNames()).forEach(param -> log.info("QUERY PARAM: {}->{}", param, ctx.getValue(param))); | 362 | + startTs = System.currentTimeMillis(); |
363 | + List<Map<String, Object>> rows; | ||
364 | + try { | ||
365 | + rows = jdbcTemplate.queryForList(dataQuery, ctx); | ||
366 | + } finally { | ||
367 | + queryLog.logQuery(ctx, countQuery, System.currentTimeMillis() - startTs); | ||
360 | } | 368 | } |
361 | - List<Map<String, Object>> rows = jdbcTemplate.queryForList(dataQuery, ctx); | ||
362 | return EntityDataAdapter.createEntityData(pageLink, selectionMapping, rows, totalElements); | 369 | return EntityDataAdapter.createEntityData(pageLink, selectionMapping, rows, totalElements); |
363 | }); | 370 | }); |
364 | } | 371 | } |
@@ -486,7 +493,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { | @@ -486,7 +493,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { | ||
486 | + SELECT_TYPE + ", " + SELECT_NAME + ", " + SELECT_LABEL + ", " + | 493 | + SELECT_TYPE + ", " + SELECT_NAME + ", " + SELECT_LABEL + ", " + |
487 | SELECT_FIRST_NAME + ", " + SELECT_LAST_NAME + ", " + SELECT_EMAIL + ", " + SELECT_REGION + ", " + | 494 | SELECT_FIRST_NAME + ", " + SELECT_LAST_NAME + ", " + SELECT_EMAIL + ", " + SELECT_REGION + ", " + |
488 | SELECT_TITLE + ", " + SELECT_COUNTRY + ", " + SELECT_STATE + ", " + SELECT_CITY + ", " + | 495 | SELECT_TITLE + ", " + SELECT_COUNTRY + ", " + SELECT_STATE + ", " + SELECT_CITY + ", " + |
489 | - SELECT_ADDRESS + ", " + SELECT_ADDRESS_2 + ", " + SELECT_ZIP + ", " + SELECT_PHONE + ", " + SELECT_ADDITIONAL_INFO + | 496 | + SELECT_ADDRESS + ", " + SELECT_ADDRESS_2 + ", " + SELECT_ZIP + ", " + SELECT_PHONE + ", " + SELECT_ADDITIONAL_INFO + |
490 | ", entity.entity_type as entity_type"; | 497 | ", entity.entity_type as entity_type"; |
491 | String from = getQueryTemplate(entityFilter.getDirection()); | 498 | String from = getQueryTemplate(entityFilter.getDirection()); |
492 | ctx.addUuidParameter("relation_root_id", rootId.getId()); | 499 | ctx.addUuidParameter("relation_root_id", rootId.getId()); |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.sql.query; | ||
17 | + | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
19 | +import org.springframework.beans.factory.annotation.Value; | ||
20 | +import org.springframework.stereotype.Component; | ||
21 | + | ||
22 | +import java.util.Arrays; | ||
23 | + | ||
24 | +@Component | ||
25 | +@Slf4j | ||
26 | +public class DefaultQueryLogComponent implements QueryLogComponent { | ||
27 | + | ||
28 | + @Value("${sql.log_queries:false}") | ||
29 | + private boolean logSqlQueries; | ||
30 | + @Value("${sql.log_queries_threshold:5000}") | ||
31 | + private long logQueriesThreshold; | ||
32 | + | ||
33 | + @Override | ||
34 | + public void logQuery(QueryContext ctx, String query, long duration) { | ||
35 | + if (logSqlQueries && duration > logQueriesThreshold) { | ||
36 | + log.info("QUERY: {} took {}ms", query, duration); | ||
37 | + Arrays.asList(ctx.getParameterNames()).forEach(param -> log.info("QUERY PARAM: {} -> {}", param, ctx.getValue(param))); | ||
38 | + } | ||
39 | + } | ||
40 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.sql.query; | ||
17 | + | ||
18 | +public interface QueryLogComponent { | ||
19 | + | ||
20 | + void logQuery(QueryContext ctx, String query, long duration); | ||
21 | +} |