This is an automated email from the ASF dual-hosted git repository.

jackie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new 7de438e434 Add segment level debug API (#9609)
7de438e434 is described below

commit 7de438e434f84da094554fec8922bd7d8b23faac
Author: Saurabh Dubey <[email protected]>
AuthorDate: Thu Oct 20 23:14:58 2022 +0530

    Add segment level debug API (#9609)
---
 ...{TableDebugResource.java => DebugResource.java} | 84 ++++++++++++++++++++--
 .../pinot/server/api/resources/DebugResource.java  | 34 ++++++++-
 2 files changed, 112 insertions(+), 6 deletions(-)

diff --git 
a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/TableDebugResource.java
 
b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/DebugResource.java
similarity index 83%
rename from 
pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/TableDebugResource.java
rename to 
pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/DebugResource.java
index d10c29f1e6..badd427bcc 100644
--- 
a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/TableDebugResource.java
+++ 
b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/DebugResource.java
@@ -36,6 +36,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.function.Function;
 import java.util.stream.Collectors;
@@ -89,9 +90,9 @@ import static 
org.apache.pinot.spi.utils.CommonConstants.SWAGGER_AUTHORIZATION_K
 @Api(tags = Constants.CLUSTER_TAG, authorizations = {@Authorization(value = 
SWAGGER_AUTHORIZATION_KEY)})
 @SwaggerDefinition(securityDefinition = 
@SecurityDefinition(apiKeyAuthDefinitions = @ApiKeyAuthDefinition(name =
     HttpHeaders.AUTHORIZATION, in = 
ApiKeyAuthDefinition.ApiKeyLocation.HEADER, key = SWAGGER_AUTHORIZATION_KEY)))
-@Path("/")
-public class TableDebugResource {
-  private static final Logger LOGGER = 
LoggerFactory.getLogger(TableDebugResource.class);
+@Path("/debug/")
+public class DebugResource {
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(DebugResource.class);
 
   @Inject
   PinotHelixResourceManager _pinotHelixResourceManager;
@@ -112,7 +113,7 @@ public class TableDebugResource {
   ControllerConf _controllerConf;
 
   @GET
-  @Path("/debug/tables/{tableName}")
+  @Path("tables/{tableName}")
   @Produces(MediaType.APPLICATION_JSON)
   @ApiOperation(value = "Get debug information for table.", notes = "Debug 
information for table.")
   @ApiResponses(value = {
@@ -142,6 +143,22 @@ public class TableDebugResource {
     return JsonUtils.objectToPrettyString(tableDebugInfos);
   }
 
+  @GET
+  @Path("segments/{tableName}/{segmentName}")
+  @Produces(MediaType.APPLICATION_JSON)
+  @ApiOperation(value = "Get debug information for segment.", notes = "Debug 
information for segment.")
+  @ApiResponses(value = {
+      @ApiResponse(code = 200, message = "Success"), @ApiResponse(code = 404, 
message = "Segment not found"),
+      @ApiResponse(code = 500, message = "Internal server error")
+  })
+  public TableDebugInfo.SegmentDebugInfo getSegmentDebugInfo(
+      @ApiParam(value = "Name of the table (with type)", required = true) 
@PathParam("tableName")
+          String tableNameWithType,
+      @ApiParam(value = "Name of the segment", required = true) 
@PathParam("segmentName") String segmentName)
+      throws Exception {
+    return debugSegment(tableNameWithType, segmentName);
+  }
+
   /**
    * Helper method to collect debug information about the table.
    *
@@ -217,6 +234,65 @@ public class TableDebugResource {
         tableSizeDetails._estimatedSizeInBytes) : new 
TableDebugInfo.TableSizeSummary(-1, -1);
   }
 
+  private TableDebugInfo.SegmentDebugInfo debugSegment(String 
tableNameWithType, String segmentName)
+      throws IOException {
+    IdealState idealState = 
_pinotHelixResourceManager.getTableIdealState(tableNameWithType);
+    if (idealState == null) {
+      return null;
+    }
+
+    ExternalView externalView = 
_pinotHelixResourceManager.getTableExternalView(tableNameWithType);
+    Map<String, String> evStateMap = (externalView != null) ? 
externalView.getStateMap(segmentName) : null;
+
+    Map<String, String> isServerToStateMap = 
idealState.getRecord().getMapFields().get(segmentName);
+    Set<String> serversHostingSegment = 
_pinotHelixResourceManager.getServers(tableNameWithType, segmentName);
+
+    int serverRequestTimeoutMs = 
_controllerConf.getServerAdminRequestTimeoutSeconds() * 1000;
+    BiMap<String, String> serverToEndpoints;
+    try {
+      serverToEndpoints = 
_pinotHelixResourceManager.getDataInstanceAdminEndpoints(serversHostingSegment);
+    } catch (InvalidConfigException e) {
+      throw new WebApplicationException(
+          "Caught exception when getting segment debug info for table: " + 
tableNameWithType);
+    }
+
+    List<String> serverUrls = new ArrayList<>(serverToEndpoints.size());
+    BiMap<String, String> endpointsToServers = serverToEndpoints.inverse();
+    for (String endpoint : endpointsToServers.keySet()) {
+      String segmentDebugInfoURI = String.format("%s/debug/segments/%s/%s", 
endpoint, tableNameWithType, segmentName);
+      serverUrls.add(segmentDebugInfoURI);
+    }
+
+    CompletionServiceHelper completionServiceHelper =
+        new CompletionServiceHelper(_executor, _connectionManager, 
endpointsToServers);
+    CompletionServiceHelper.CompletionServiceResponse serviceResponse =
+        completionServiceHelper.doMultiGetRequest(serverUrls, 
tableNameWithType, false, serverRequestTimeoutMs);
+
+    Map<String, SegmentServerDebugInfo> serverToSegmentDebugInfo = new 
HashMap<>();
+    for (Map.Entry<String, String> streamResponse : 
serviceResponse._httpResponses.entrySet()) {
+      SegmentServerDebugInfo segmentDebugInfo =
+          JsonUtils.stringToObject(streamResponse.getValue(), 
SegmentServerDebugInfo.class);
+      serverToSegmentDebugInfo.put(streamResponse.getKey(), segmentDebugInfo);
+    }
+
+    Map<String, TableDebugInfo.SegmentState> segmentServerState = new 
HashMap<>();
+    for (String instanceName : isServerToStateMap.keySet()) {
+      String isState = isServerToStateMap.get(instanceName);
+      String evState = (evStateMap != null) ? evStateMap.get(instanceName) : 
null;
+      SegmentServerDebugInfo segmentServerDebugInfo = 
serverToSegmentDebugInfo.get(instanceName);
+
+      if (segmentServerDebugInfo != null) {
+        segmentServerState.put(instanceName,
+            new TableDebugInfo.SegmentState(isState, evState, 
segmentServerDebugInfo.getSegmentSize(),
+                segmentServerDebugInfo.getConsumerInfo(), 
segmentServerDebugInfo.getErrorInfo()));
+      } else {
+        segmentServerState.put(instanceName, new 
TableDebugInfo.SegmentState(isState, evState, null, null, null));
+      }
+    }
+
+    return new TableDebugInfo.SegmentDebugInfo(segmentName, 
segmentServerState);
+  }
+
   /**
    * Helper method to debug segments. Computes differences between ideal state 
and external view for each segment.
    *
diff --git 
a/pinot-server/src/main/java/org/apache/pinot/server/api/resources/DebugResource.java
 
b/pinot-server/src/main/java/org/apache/pinot/server/api/resources/DebugResource.java
index 9d0a1976fc..9132f28556 100644
--- 
a/pinot-server/src/main/java/org/apache/pinot/server/api/resources/DebugResource.java
+++ 
b/pinot-server/src/main/java/org/apache/pinot/server/api/resources/DebugResource.java
@@ -75,12 +75,42 @@ public class DebugResource {
   @ApiOperation(value = "Get segments debug info for this table",
       notes = "This is a debug endpoint, and won't maintain backward 
compatibility")
   public List<SegmentServerDebugInfo> getSegmentsDebugInfo(
-      @ApiParam(value = "Name of the table", required = true) 
@PathParam("tableName") String tableNameWithType) {
-
+      @ApiParam(value = "Name of the table (with type)", required = true) 
@PathParam("tableName")
+          String tableNameWithType) {
     TableType tableType = 
TableNameBuilder.getTableTypeFromTableName(tableNameWithType);
     return getSegmentServerDebugInfo(tableNameWithType, tableType);
   }
 
+  @GET
+  @Path("segments/{tableName}/{segmentName}")
+  @Produces(MediaType.APPLICATION_JSON)
+  @ApiOperation(value = "Get segment debug info",
+      notes = "This is a debug endpoint, and won't maintain backward 
compatibility")
+  public SegmentServerDebugInfo getSegmentDebugInfo(
+      @ApiParam(value = "Name of the table (with type)", required = true) 
@PathParam("tableName")
+          String tableNameWithType,
+      @ApiParam(value = "Name of the segment", required = true) 
@PathParam("segmentName") String segmentName) {
+    TableType tableType = 
TableNameBuilder.getTableTypeFromTableName(tableNameWithType);
+    TableDataManager tableDataManager =
+        ServerResourceUtils.checkGetTableDataManager(_serverInstance, 
tableNameWithType);
+    Map<String, SegmentErrorInfo> segmentErrorsMap = 
tableDataManager.getSegmentErrors();
+    SegmentDataManager segmentDataManager = 
tableDataManager.acquireSegment(segmentName);
+    try {
+      SegmentConsumerInfo segmentConsumerInfo = 
getSegmentConsumerInfo(segmentDataManager, tableType);
+      long segmentSize = getSegmentSize(segmentDataManager);
+      SegmentErrorInfo segmentErrorInfo = segmentErrorsMap.get(segmentName);
+      return new SegmentServerDebugInfo(segmentName, 
FileUtils.byteCountToDisplaySize(segmentSize), segmentConsumerInfo,
+          segmentErrorInfo);
+    } catch (Exception e) {
+      throw new WebApplicationException(
+          "Caught exception when getting consumer info for table: " + 
tableNameWithType + " segment: " + segmentName);
+    } finally {
+      if (segmentDataManager != null) {
+        tableDataManager.releaseSegment(segmentDataManager);
+      }
+    }
+  }
+
   private List<SegmentServerDebugInfo> getSegmentServerDebugInfo(String 
tableNameWithType, TableType tableType) {
     List<SegmentServerDebugInfo> segmentServerDebugInfos = new ArrayList<>();
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to