17 changed files with 570 additions and 13 deletions
@ -0,0 +1,95 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.event; |
|||
|
|||
import com.fasterxml.jackson.databind.node.ObjectNode; |
|||
import lombok.Builder; |
|||
import lombok.EqualsAndHashCode; |
|||
import lombok.Getter; |
|||
import lombok.Setter; |
|||
import lombok.ToString; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
import org.thingsboard.server.common.data.EventInfo; |
|||
import org.thingsboard.server.common.data.id.CalculatedFieldId; |
|||
import org.thingsboard.server.common.data.id.EntityId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
|
|||
import java.util.UUID; |
|||
|
|||
@ToString |
|||
@EqualsAndHashCode(callSuper = true) |
|||
public class CalculatedFieldDebugEvent extends Event { |
|||
|
|||
private static final long serialVersionUID = -7091690784759639853L; |
|||
|
|||
@Builder |
|||
private CalculatedFieldDebugEvent(TenantId tenantId, UUID entityId, String serviceId, UUID id, long ts, |
|||
CalculatedFieldId calculatedFieldId, EntityId eventEntity, UUID msgId, |
|||
String msgType, String arguments, String result, String error) { |
|||
super(tenantId, entityId, serviceId, id, ts); |
|||
this.calculatedFieldId = calculatedFieldId; |
|||
this.eventEntity = eventEntity; |
|||
this.msgId = msgId; |
|||
this.msgType = msgType; |
|||
this.arguments = arguments; |
|||
this.result = result; |
|||
this.error = error; |
|||
} |
|||
|
|||
@Getter |
|||
private final CalculatedFieldId calculatedFieldId; |
|||
@Getter |
|||
private final EntityId eventEntity; |
|||
@Getter |
|||
private final UUID msgId; |
|||
@Getter |
|||
private final String msgType; |
|||
@Getter |
|||
@Setter |
|||
private String arguments; |
|||
@Getter |
|||
@Setter |
|||
private String result; |
|||
@Getter |
|||
@Setter |
|||
private String error; |
|||
|
|||
@Override |
|||
public EventType getType() { |
|||
return EventType.DEBUG_CALCULATED_FIELD; |
|||
} |
|||
|
|||
@Override |
|||
public EventInfo toInfo(EntityType entityType) { |
|||
EventInfo eventInfo = super.toInfo(entityType); |
|||
var json = (ObjectNode) eventInfo.getBody(); |
|||
json.put("calculatedFieldId", calculatedFieldId.toString()); |
|||
if (eventEntity != null) { |
|||
json.put("entityId", eventEntity.getId().toString()) |
|||
.put("entityType", eventEntity.getEntityType().name()); |
|||
} |
|||
if (msgId != null) { |
|||
json.put("msgId", msgId.toString()); |
|||
} |
|||
putNotNull(json, "msgType", msgType); |
|||
putNotNull(json, "arguments", arguments); |
|||
putNotNull(json, "result", result); |
|||
putNotNull(json, "error", error); |
|||
return eventInfo; |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.event; |
|||
|
|||
import io.swagger.v3.oas.annotations.media.Schema; |
|||
import lombok.Data; |
|||
import lombok.EqualsAndHashCode; |
|||
import org.thingsboard.server.common.data.StringUtils; |
|||
|
|||
@Data |
|||
@EqualsAndHashCode(callSuper = true) |
|||
@Schema |
|||
public class CalculatedFieldDebugEventFilter extends DebugEventFilter { |
|||
|
|||
@Schema(description = "String value representing the calculated field id in the event body", example = "ccbfa2fe-c8f5-45d8-bb37-6b61a6e02833") |
|||
protected String calculatedFieldId; |
|||
@Schema(description = "String value representing the entity id in the event body", example = "57b6bafe-d600-423c-9267-fe31e5218986") |
|||
protected String entityId; |
|||
@Schema(description = "String value representing the entity type", allowableValues = "DEVICE") |
|||
protected String entityType; |
|||
@Schema(description = "String value representing the message id in the rule engine", example = "dcf44612-2ce4-4e5d-b462-ebb9c5628228") |
|||
protected String msgId; |
|||
@Schema(description = "String value representing the message type", example = "POST_TELEMETRY_REQUEST") |
|||
protected String msgType; |
|||
|
|||
@Override |
|||
public EventType getEventType() { |
|||
return EventType.DEBUG_CALCULATED_FIELD; |
|||
} |
|||
|
|||
@Override |
|||
public boolean isNotEmpty() { |
|||
return super.isNotEmpty() || !StringUtils.isEmpty(calculatedFieldId) || !StringUtils.isEmpty(entityId) |
|||
|| !StringUtils.isEmpty(entityType) || !StringUtils.isEmpty(msgId) || !StringUtils.isEmpty(msgType); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,104 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.model.sql; |
|||
|
|||
import jakarta.persistence.Column; |
|||
import jakarta.persistence.Entity; |
|||
import jakarta.persistence.Table; |
|||
import lombok.Data; |
|||
import lombok.EqualsAndHashCode; |
|||
import lombok.NoArgsConstructor; |
|||
import org.thingsboard.server.common.data.event.CalculatedFieldDebugEvent; |
|||
import org.thingsboard.server.common.data.id.CalculatedFieldId; |
|||
import org.thingsboard.server.common.data.id.EntityIdFactory; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.dao.model.BaseEntity; |
|||
|
|||
import java.util.UUID; |
|||
|
|||
import static org.thingsboard.server.dao.model.ModelConstants.CALCULATED_FIELD_DEBUG_EVENT_TABLE_NAME; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.EVENT_CALCULATED_FIELD_ARGUMENTS_COLUMN_NAME; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.EVENT_CALCULATED_FIELD_ID_COLUMN_NAME; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.EVENT_CALCULATED_FIELD_RESULT_COLUMN_NAME; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.EVENT_ENTITY_ID_COLUMN_NAME; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.EVENT_ENTITY_TYPE_COLUMN_NAME; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.EVENT_ERROR_COLUMN_NAME; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.EVENT_MSG_ID_COLUMN_NAME; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.EVENT_MSG_TYPE_COLUMN_NAME; |
|||
|
|||
@Data |
|||
@EqualsAndHashCode(callSuper = true) |
|||
@Entity |
|||
@Table(name = CALCULATED_FIELD_DEBUG_EVENT_TABLE_NAME) |
|||
@NoArgsConstructor |
|||
public class CalculatedFieldDebugEventEntity extends EventEntity<CalculatedFieldDebugEvent> implements BaseEntity<CalculatedFieldDebugEvent> { |
|||
|
|||
@Column(name = EVENT_CALCULATED_FIELD_ID_COLUMN_NAME) |
|||
private UUID calculatedFieldId; |
|||
@Column(name = EVENT_ENTITY_ID_COLUMN_NAME) |
|||
private UUID eventEntityId; |
|||
@Column(name = EVENT_ENTITY_TYPE_COLUMN_NAME) |
|||
private String eventEntityType; |
|||
@Column(name = EVENT_MSG_ID_COLUMN_NAME) |
|||
private UUID msgId; |
|||
@Column(name = EVENT_MSG_TYPE_COLUMN_NAME) |
|||
private String msgType; |
|||
@Column(name = EVENT_CALCULATED_FIELD_ARGUMENTS_COLUMN_NAME) |
|||
private String arguments; |
|||
@Column(name = EVENT_CALCULATED_FIELD_RESULT_COLUMN_NAME) |
|||
private String result; |
|||
@Column(name = EVENT_ERROR_COLUMN_NAME) |
|||
private String error; |
|||
|
|||
public CalculatedFieldDebugEventEntity(CalculatedFieldDebugEvent event) { |
|||
super(event); |
|||
if (event.getCalculatedFieldId() != null) { |
|||
this.calculatedFieldId = event.getCalculatedFieldId().getId(); |
|||
} |
|||
if (event.getEventEntity() != null) { |
|||
this.eventEntityId = event.getEventEntity().getId(); |
|||
this.eventEntityType = event.getEventEntity().getEntityType().name(); |
|||
} |
|||
this.msgId = event.getMsgId(); |
|||
this.msgType = event.getMsgType(); |
|||
this.arguments = event.getArguments(); |
|||
this.result = event.getResult(); |
|||
this.error = event.getError(); |
|||
} |
|||
|
|||
@Override |
|||
public CalculatedFieldDebugEvent toData() { |
|||
var builder = CalculatedFieldDebugEvent.builder() |
|||
.id(id) |
|||
.tenantId(TenantId.fromUUID(tenantId)) |
|||
.ts(ts) |
|||
.serviceId(serviceId) |
|||
.entityId(entityId) |
|||
.msgId(msgId) |
|||
.msgType(msgType) |
|||
.arguments(arguments) |
|||
.result(result) |
|||
.error(error); |
|||
if (calculatedFieldId != null) { |
|||
builder.calculatedFieldId(new CalculatedFieldId(calculatedFieldId)); |
|||
} |
|||
if (eventEntityId != null) { |
|||
builder.eventEntity(EntityIdFactory.getByTypeAndUuid(eventEntityType, eventEntityId)); |
|||
} |
|||
return builder.build(); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,135 @@ |
|||
/** |
|||
* Copyright © 2016-2024 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.event; |
|||
|
|||
import org.springframework.data.domain.Page; |
|||
import org.springframework.data.domain.Pageable; |
|||
import org.springframework.data.jpa.repository.JpaRepository; |
|||
import org.springframework.data.jpa.repository.Modifying; |
|||
import org.springframework.data.jpa.repository.Query; |
|||
import org.springframework.data.repository.query.Param; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
import org.thingsboard.server.common.data.event.CalculatedFieldDebugEvent; |
|||
import org.thingsboard.server.dao.model.sql.CalculatedFieldDebugEventEntity; |
|||
|
|||
import java.util.List; |
|||
import java.util.UUID; |
|||
|
|||
public interface CalculatedFieldDebugEventRepository extends EventRepository<CalculatedFieldDebugEventEntity, CalculatedFieldDebugEvent>, JpaRepository<CalculatedFieldDebugEventEntity, UUID> { |
|||
|
|||
@Override |
|||
@Query(nativeQuery = true, value = "SELECT * FROM cf_debug_event e WHERE e.tenant_id = :tenantId AND e.entity_id = :entityId ORDER BY e.ts DESC LIMIT :limit") |
|||
List<CalculatedFieldDebugEventEntity> findLatestEvents(@Param("tenantId") UUID tenantId, @Param("entityId") UUID entityId, @Param("limit") int limit); |
|||
|
|||
@Override |
|||
@Query("SELECT e FROM RuleNodeDebugEventEntity e WHERE " + |
|||
"e.tenantId = :tenantId " + |
|||
"AND e.entityId = :entityId " + |
|||
"AND (:startTime IS NULL OR e.ts >= :startTime) " + |
|||
"AND (:endTime IS NULL OR e.ts <= :endTime)" |
|||
) |
|||
Page<CalculatedFieldDebugEventEntity> findEvents(@Param("tenantId") UUID tenantId, |
|||
@Param("entityId") UUID entityId, |
|||
@Param("startTime") Long startTime, |
|||
@Param("endTime") Long endTime, |
|||
Pageable pageable); |
|||
|
|||
@Query(nativeQuery = true, |
|||
value = "SELECT * FROM cf_debug_event e WHERE " + |
|||
"e.tenant_id = :tenantId " + |
|||
"AND e.entity_id = :entityId " + |
|||
"AND (:startTime IS NULL OR e.ts >= :startTime) " + |
|||
"AND (:endTime IS NULL OR e.ts <= :endTime) " + |
|||
"AND (:serviceId IS NULL OR e.service_id ILIKE concat('%', :serviceId, '%')) " + |
|||
"AND (:calculatedFieldId IS NULL OR e.cf_id = uuid(:calculatedFieldId)) " + |
|||
"AND (:eventEntityId IS NULL OR e.e_entity_id = uuid(:eventEntityId)) " + |
|||
"AND (:eventEntityType IS NULL OR e.e_entity_type ILIKE concat('%', :eventEntityType, '%')) " + |
|||
"AND (:msgId IS NULL OR e.e_msg_id = uuid(:msgId)) " + |
|||
"AND (:msgType IS NULL OR e.e_msg_type ILIKE concat('%', :msgType, '%')) " + |
|||
"AND ((:isError = FALSE) OR e.e_error IS NOT NULL) " + |
|||
"AND (:error IS NULL OR e.e_error ILIKE concat('%', :error, '%'))" |
|||
, |
|||
countQuery = "SELECT count(*) FROM rule_node_debug_event e WHERE " + |
|||
"e.tenant_id = :tenantId " + |
|||
"AND e.entity_id = :entityId " + |
|||
"AND (:startTime IS NULL OR e.ts >= :startTime) " + |
|||
"AND (:endTime IS NULL OR e.ts <= :endTime) " + |
|||
"AND (:serviceId IS NULL OR e.service_id ILIKE concat('%', :serviceId, '%')) " + |
|||
"AND (:calculatedFieldId IS NULL OR e.cf_id = uuid(:calculatedFieldId)) " + |
|||
"AND (:eventEntityId IS NULL OR e.e_entity_id = uuid(:eventEntityId)) " + |
|||
"AND (:eventEntityType IS NULL OR e.e_entity_type ILIKE concat('%', :eventEntityType, '%')) " + |
|||
"AND (:msgId IS NULL OR e.e_msg_id = uuid(:msgId)) " + |
|||
"AND (:msgType IS NULL OR e.e_msg_type ILIKE concat('%', :msgType, '%')) " + |
|||
"AND ((:isError = FALSE) OR e.e_error IS NOT NULL) " + |
|||
"AND (:error IS NULL OR e.e_error ILIKE concat('%', :error, '%'))" |
|||
) |
|||
Page<CalculatedFieldDebugEventEntity> findEvents(@Param("tenantId") UUID tenantId, |
|||
@Param("entityId") UUID entityId, |
|||
@Param("startTime") Long startTime, |
|||
@Param("endTime") Long endTime, |
|||
@Param("serviceId") String server, |
|||
@Param("calculatedFieldId") UUID calculatedFieldId, |
|||
@Param("eventEntityId") String eventEntityId, |
|||
@Param("eventEntityType") String eventEntityType, |
|||
@Param("msgId") String eventMsgId, |
|||
@Param("msgType") String eventMsgType, |
|||
@Param("isError") boolean isError, |
|||
@Param("error") String error, |
|||
Pageable pageable); |
|||
|
|||
@Transactional |
|||
@Modifying |
|||
@Query("DELETE FROM CalculatedFieldDebugEventEntity e WHERE " + |
|||
"e.tenantId = :tenantId " + |
|||
"AND e.entityId = :entityId " + |
|||
"AND (:startTime IS NULL OR e.ts >= :startTime) " + |
|||
"AND (:endTime IS NULL OR e.ts <= :endTime)" |
|||
) |
|||
void removeEvents(@Param("tenantId") UUID tenantId, |
|||
@Param("entityId") UUID entityId, |
|||
@Param("startTime") Long startTime, |
|||
@Param("endTime") Long endTime); |
|||
|
|||
@Transactional |
|||
@Modifying |
|||
@Query(nativeQuery = true, |
|||
value = "DELETE FROM cf_debug_event e WHERE " + |
|||
"e.tenant_id = :tenantId " + |
|||
"AND e.entity_id = :entityId " + |
|||
"AND (:startTime IS NULL OR e.ts >= :startTime) " + |
|||
"AND (:endTime IS NULL OR e.ts <= :endTime) " + |
|||
"AND (:serviceId IS NULL OR e.service_id ILIKE concat('%', :serviceId, '%')) " + |
|||
"AND (:calculatedFieldId IS NULL OR e.cf_id = uuid(:calculatedFieldId)) " + |
|||
"AND (:eventEntityId IS NULL OR e.e_entity_id = uuid(:eventEntityId)) " + |
|||
"AND (:eventEntityType IS NULL OR e.e_entity_type ILIKE concat('%', :eventEntityType, '%')) " + |
|||
"AND (:msgId IS NULL OR e.e_msg_id = uuid(:msgId)) " + |
|||
"AND (:msgType IS NULL OR e.e_msg_type ILIKE concat('%', :msgType, '%')) " + |
|||
"AND ((:isError = FALSE) OR e.e_error IS NOT NULL) " + |
|||
"AND (:error IS NULL OR e.e_error ILIKE concat('%', :error, '%'))") |
|||
void removeEvents(@Param("tenantId") UUID tenantId, |
|||
@Param("entityId") UUID entityId, |
|||
@Param("startTime") Long startTime, |
|||
@Param("endTime") Long endTime, |
|||
@Param("serviceId") String server, |
|||
@Param("calculatedFieldId") UUID calculatedFieldId, |
|||
@Param("eventEntityId") String eventEntityId, |
|||
@Param("eventEntityType") String eventEntityType, |
|||
@Param("msgId") String eventMsgId, |
|||
@Param("msgType") String eventMsgType, |
|||
@Param("isError") boolean isError, |
|||
@Param("error") String error); |
|||
|
|||
} |
|||
Loading…
Reference in new issue