Jackie-Jiang commented on code in PR #14961: URL: https://github.com/apache/pinot/pull/14961#discussion_r1943593468
########## pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotRealtimeTableResource.java: ########## @@ -301,6 +309,74 @@ public ConsumingSegmentInfoReader.ConsumingSegmentsInfoMap getConsumingSegmentsI } } + @GET + @Path("/tables/{tableName}/pauselessDebugInfo") + @Authorize(targetType = TargetType.TABLE, paramName = "tableName", action = Actions.Table.GET_DEBUG_INFO) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Returns state of pauseless table", notes = + "Gets the segments that are in error state and optionally gets COMMITTING segments based on the " + + "includeCommittingSegments parameter") + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Success"), + @ApiResponse(code = 404, message = "Table not found"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public String getPauslessTableDebugInfo( + @ApiParam(value = "Realtime table name with or without type", required = true, example = "myTable | " + + "myTable_REALTIME") @PathParam("tableName") String realtimeTableName, + @ApiParam(value = "Flag to include committing segment info") @QueryParam("includeCommittingSegments") + @DefaultValue("false") boolean includeCommittingSegments, + @Context HttpHeaders headers) { + realtimeTableName = DatabaseUtils.translateTableName(realtimeTableName, headers); + try { + TableType tableType = TableNameBuilder.getTableTypeFromTableName(realtimeTableName); + if (TableType.OFFLINE == tableType) { + throw new IllegalStateException("Cannot get consuming segments info for OFFLINE table: " + realtimeTableName); + } + String tableNameWithType = TableNameBuilder.forType(TableType.REALTIME).tableNameWithType(realtimeTableName); + + Map<String, Object> result = new HashMap<>(); + result.put("instanceToErrorSegmentsMap", getInstanceToErrorSegmentsMap(tableNameWithType)); + + if (includeCommittingSegments) { + result.put("committingSegments", getCommittingSegments(tableNameWithType)); + } + return JsonUtils.objectToPrettyString(result); + } catch (Exception e) { + throw new ControllerApplicationException(LOGGER, + String.format("Failed to get pauseless debug info for table %s. %s", realtimeTableName, e.getMessage()), + Response.Status.INTERNAL_SERVER_ERROR, e); + } + } + + public Set<String> getCommittingSegments(String tableNameWithType) { + List<SegmentZKMetadata> segmentZKMetadataList = + ZKMetadataProvider.getSegmentsZKMetadata(_pinotHelixResourceManager.getPropertyStore(), tableNameWithType); + return segmentZKMetadataList.stream() + .filter( + segmentZKMetadata -> segmentZKMetadata.getStatus() == CommonConstants.Segment.Realtime.Status.COMMITTING) + .map(SegmentZKMetadata::getSegmentName) + .collect(Collectors.toSet()); + } + + private Map<String, Set<String>> getInstanceToErrorSegmentsMap(String tableNameWithType) { Review Comment: Should we exclude segments not in the IS? ########## pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotRealtimeTableResource.java: ########## @@ -301,6 +309,74 @@ public ConsumingSegmentInfoReader.ConsumingSegmentsInfoMap getConsumingSegmentsI } } + @GET + @Path("/tables/{tableName}/pauselessDebugInfo") + @Authorize(targetType = TargetType.TABLE, paramName = "tableName", action = Actions.Table.GET_DEBUG_INFO) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Returns state of pauseless table", notes = + "Gets the segments that are in error state and optionally gets COMMITTING segments based on the " + + "includeCommittingSegments parameter") + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Success"), + @ApiResponse(code = 404, message = "Table not found"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public String getPauslessTableDebugInfo( + @ApiParam(value = "Realtime table name with or without type", required = true, example = "myTable | " + + "myTable_REALTIME") @PathParam("tableName") String realtimeTableName, + @ApiParam(value = "Flag to include committing segment info") @QueryParam("includeCommittingSegments") + @DefaultValue("false") boolean includeCommittingSegments, + @Context HttpHeaders headers) { + realtimeTableName = DatabaseUtils.translateTableName(realtimeTableName, headers); + try { + TableType tableType = TableNameBuilder.getTableTypeFromTableName(realtimeTableName); + if (TableType.OFFLINE == tableType) { + throw new IllegalStateException("Cannot get consuming segments info for OFFLINE table: " + realtimeTableName); + } + String tableNameWithType = TableNameBuilder.forType(TableType.REALTIME).tableNameWithType(realtimeTableName); + + Map<String, Object> result = new HashMap<>(); + result.put("instanceToErrorSegmentsMap", getInstanceToErrorSegmentsMap(tableNameWithType)); + + if (includeCommittingSegments) { + result.put("committingSegments", getCommittingSegments(tableNameWithType)); + } + return JsonUtils.objectToPrettyString(result); + } catch (Exception e) { + throw new ControllerApplicationException(LOGGER, + String.format("Failed to get pauseless debug info for table %s. %s", realtimeTableName, e.getMessage()), + Response.Status.INTERNAL_SERVER_ERROR, e); + } + } + + public Set<String> getCommittingSegments(String tableNameWithType) { Review Comment: This is super expensive. Is it possible to only check metadata for segments that are `ONLINE` in IS but not `ONLINE` in EV? -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For additional commands, e-mail: commits-h...@pinot.apache.org