code: private String constructMetricQueryKey(Long startTimeStampBoundary, MetricQuery query) {
          StringBuilder sb = new StringBuilder();
  
          sb.append(startTimeStampBoundary).append(":");
          sb.append(query.getNamespace()).append(":");
          sb.append(query.getScope()).append(":");
          sb.append(query.getMetric()).append(":");
  
          // sort the tag key and values within each tag key alphabetically
          Map<String, String> treeMap = new TreeMap<String, String>();
  
          for (Map.Entry<String, String> tag : query.getTags().entrySet()) {
              String[] tagValues = tag.getValue().split("\\|");
  
              Arrays.sort(tagValues);
  
              StringBuilder sbTag = new StringBuilder();
              String separator = "";
  
              for (String tagValue : tagValues) {
                  sbTag.append(separator);
                  separator = "|";
                  sbTag.append(tagValue);
              }
              treeMap.put(tag.getKey(), sbTag.toString());
          }
          sb.append(treeMap).append(":");
          sb.append(query.getAggregator()).append(":");
          sb.append(query.getDownsampler()).append(":");
          sb.append(query.getDownsamplingPeriod());
          return sb.toString();
      }
docs: Constructs a cache key from start time stamp boundary, and tags in metric query.
  
  @param   startTimeStampBoundary  The start time stamp boundary.
  @param   query                   The query to use to construct the cache key.
  
  @return  The cache key.