{"action":"created","comment":{"url":"https://api.github.com/repos/hawkular/hawkular-metrics/pulls/comments/28892621","id":28892621,"diff_hunk":"@@ -89,752 +58,11 @@\n @Produces(APPLICATION_JSON)\n @Api(value = \"/\", description = \"Metrics related REST interface\")\n public class MetricHandler {\n-    private static final long EIGHT_HOURS = MILLISECONDS.convert(8, HOURS);\n-\n     @Inject\n     private MetricsService metricsService;\n \n-    @POST\n-    @Path(\"/{tenantId}/metrics/numeric\")\n-    @ApiOperation(value = \"Create numeric metric definition.\", notes = \"Clients are not required to explicitly create \"\n-            + \"a metric before storing data. Doing so however allows clients to prevent naming collisions and to \"\n-            + \"specify tags and data retention.\")\n-    @ApiResponses(value = {\n-            @ApiResponse(code = 201, message = \"Metric definition created successfully\"),\n-            @ApiResponse(code = 400, message = \"Missing or invalid payload\", response = ApiError.class),\n-            @ApiResponse(code = 409, message = \"Numeric metric with given id already exists\",\n-                         response = ApiError.class),\n-            @ApiResponse(code = 500, message = \"Metric definition creation failed due to an unexpected error\",\n-                         response = ApiError.class)\n-    })\n-    public void createNumericMetric(@Suspended final AsyncResponse asyncResponse,\n-                                    @PathParam(\"tenantId\") String tenantId,\n-                                    @ApiParam(required = true) NumericMetric metric,\n-                                    @Context UriInfo uriInfo\n-    ) {\n-        if (metric == null) {\n-            Response response = Response.status(Status.BAD_REQUEST).entity(new ApiError(\"Payload is empty\")).build();\n-            asyncResponse.resume(response);\n-            return;\n-        }\n-        metric.setTenantId(tenantId);\n-        ListenableFuture<Void> future = metricsService.createMetric(metric);\n-        URI created = uriInfo.getBaseUriBuilder()\n-                             .path(\"/{tenantId}/metrics/numeric/{id}\")\n-                             .build(tenantId, metric.getId().getName());\n-        MetricCreatedCallback metricCreatedCallback = new MetricCreatedCallback(asyncResponse, created);\n-        Futures.addCallback(future, metricCreatedCallback);\n-    }\n-\n-    @POST\n-    @Path(\"/{tenantId}/metrics/availability\")\n-    @ApiOperation(value = \"Create availability metric definition. Same notes as creating numeric metric apply.\")\n-    @ApiResponses(value = {\n-            @ApiResponse(code = 201, message = \"Metric definition created successfully\"),\n-            @ApiResponse(code = 400, message = \"Missing or invalid payload\", response = ApiError.class),\n-            @ApiResponse(code = 409, message = \"Numeric metric with given id already exists\",\n-                         response = ApiError.class),\n-            @ApiResponse(code = 500, message = \"Metric definition creation failed due to an unexpected error\",\n-                         response = ApiError.class)\n-    })\n-    public void createAvailabilityMetric(@Suspended final AsyncResponse asyncResponse,\n-                                         @PathParam(\"tenantId\") String tenantId,\n-                                         @ApiParam(required = true) AvailabilityMetric metric,\n-                                         @Context UriInfo uriInfo) {\n-        if (metric == null) {\n-            Response response = Response.status(Status.BAD_REQUEST).entity(new ApiError(\"Payload is empty\")).build();\n-            asyncResponse.resume(response);\n-            return;\n-        }\n-        metric.setTenantId(tenantId);\n-        ListenableFuture<Void> future = metricsService.createMetric(metric);\n-        URI created = uriInfo.getBaseUriBuilder()\n-                             .path(\"/{tenantId}/metrics/availability/{id}\")\n-                             .build(tenantId, metric.getId().getName());\n-        MetricCreatedCallback metricCreatedCallback = new MetricCreatedCallback(asyncResponse, created);\n-        Futures.addCallback(future, metricCreatedCallback);\n-    }\n-\n     @GET\n-    @Path(\"/{tenantId}/metrics/numeric/{id}/tags\")\n-    @ApiOperation(value = \"Retrieve tags associated with the metric definition.\", response = Metric.class)\n-    @ApiResponses(value = { @ApiResponse(code = 200, message = \"Metric's tags were successfully retrieved.\"),\n-            @ApiResponse(code = 204, message = \"Query was successful, but no metrics were found.\"),\n-            @ApiResponse(code = 500, message = \"Unexpected error occurred while fetching metric's tags.\",\n-                         response = ApiError.class)\n-    })\n-    public void getNumericMetricTags(@Suspended final AsyncResponse asyncResponse,\n-            @PathParam(\"tenantId\") String tenantId, @PathParam(\"id\") String id) {\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    ListenableFuture<Optional<Metric<?>>> future = metricsService.findMetric(\n-                            tenantId, MetricType.NUMERIC,\n-                            new MetricId(id)\n-                    );\n-                    return Futures.transform(future, ApiUtils.MAP_VALUE);\n-                }\n-        );\n-    }\n-\n-    @PUT\n-    @Path(\"/{tenantId}/metrics/numeric/{id}/tags\")\n-    @ApiOperation(value = \"Update tags associated with the metric definition.\")\n-    @ApiResponses(value = { @ApiResponse(code = 200, message = \"Metric's tags were successfully updated.\"),\n-            @ApiResponse(code = 500, message = \"Unexpected error occurred while updating metric's tags.\",\n-                         response = ApiError.class)\n-    })\n-    public void updateNumericMetricTags(@Suspended final AsyncResponse asyncResponse,\n-                                        @PathParam(\"tenantId\") String tenantId, @PathParam(\"id\") String id,\n-                                        @ApiParam(required = true) Map<String, String> tags) {\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    NumericMetric metric = new NumericMetric(tenantId, new MetricId(id));\n-                    ListenableFuture<Void> future = metricsService.addTags(metric, tags);\n-                    return Futures.transform(future, ApiUtils.MAP_VOID);\n-                }\n-        );\n-    }\n-\n-    @DELETE\n-    @Path(\"/{tenantId}/metrics/numeric/{id}/tags/{tags}\")\n-    @ApiOperation(value = \"Delete tags associated with the metric definition.\")\n-    @ApiResponses(value = {\n-            @ApiResponse(code = 200, message = \"Metric's tags were successfully deleted.\"),\n-            @ApiResponse(code = 400, message = \"Invalid tags\", response = ApiError.class),\n-            @ApiResponse(code = 500, message = \"Unexpected error occurred while trying to delete metric's tags.\",\n-                         response = ApiError.class)\n-    })\n-    public void deleteNumericMetricTags(\n-            @Suspended final AsyncResponse asyncResponse,\n-            @PathParam(\"tenantId\") String tenantId,\n-            @PathParam(\"id\") String id,\n-            @ApiParam(\"Tag list\") @PathParam(\"tags\") Tags tags\n-    ) {\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    NumericMetric metric = new NumericMetric(tenantId, new MetricId(id));\n-                    ListenableFuture<Void> future = metricsService.deleteTags(metric, tags.getTags());\n-                    return Futures.transform(future, ApiUtils.MAP_VOID);\n-                }\n-        );\n-    }\n-\n-    @GET\n-    @Path(\"/{tenantId}/metrics/availability/{id}/tags\")\n-    @ApiOperation(value = \"Retrieve tags associated with the metric definition.\", response = Map.class)\n-    @ApiResponses(value = { @ApiResponse(code = 200, message = \"Metric's tags were successfully retrieved.\"),\n-            @ApiResponse(code = 204, message = \"Query was successful, but no metrics were found.\"),\n-            @ApiResponse(code = 500, message = \"Unexpected error occurred while fetching metric's tags.\",\n-                         response = ApiError.class)\n-    })\n-    public void getAvailabilityMetricTags(@Suspended final AsyncResponse asyncResponse,\n-        @PathParam(\"tenantId\") String tenantId, @PathParam(\"id\") String id) {\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    ListenableFuture<Optional<Metric<?>>> future = metricsService.findMetric(\n-                            tenantId, MetricType.AVAILABILITY,\n-                            new MetricId(id)\n-                    );\n-                    return Futures.transform(future, ApiUtils.MAP_VALUE);\n-                }\n-        );\n-    }\n-\n-    @PUT\n-    @Path(\"/{tenantId}/metrics/availability/{id}/tags\")\n-    @ApiOperation(value = \"Update tags associated with the metric definition.\")\n-    @ApiResponses(value = { @ApiResponse(code = 200, message = \"Metric's tags were successfully updated.\"),\n-            @ApiResponse(code = 500, message = \"Unexpected error occurred while updating metric's tags.\",\n-                         response = ApiError.class)\n-    })\n-    public void updateAvailabilityMetricTags(@Suspended final AsyncResponse asyncResponse,\n-        @PathParam(\"tenantId\") String tenantId, @PathParam(\"id\") String id,\n-        @ApiParam(required = true) Map<String, String> tags) {\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    AvailabilityMetric metric = new AvailabilityMetric(tenantId, new MetricId(id));\n-                    ListenableFuture<Void> future = metricsService.addTags(metric, tags);\n-                    return Futures.transform(future, ApiUtils.MAP_VOID);\n-                }\n-        );\n-    }\n-\n-    @DELETE\n-    @Path(\"/{tenantId}/metrics/availability/{id}/tags/{tags}\")\n-    @ApiOperation(value = \"Delete tags associated with the metric definition.\")\n-    @ApiResponses(value = {\n-            @ApiResponse(code = 200, message = \"Metric's tags were successfully deleted.\"),\n-            @ApiResponse(code = 400, message = \"Invalid tags\", response = ApiError.class),\n-            @ApiResponse(code = 500, message = \"Unexpected error occurred while trying to delete metric's tags.\",\n-                         response = ApiError.class)\n-    })\n-    public void deleteAvailabilityMetricTags(\n-            @Suspended final AsyncResponse asyncResponse,\n-            @PathParam(\"tenantId\") String tenantId, @PathParam(\"id\") String id,\n-            @ApiParam(\"Tag list\") @PathParam(\"tags\") Tags tags\n-    ) {\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    AvailabilityMetric metric = new AvailabilityMetric(tenantId, new MetricId(id));\n-                    ListenableFuture<Void> future = metricsService.deleteTags(metric, tags.getTags());\n-                    return Futures.transform(future, ApiUtils.MAP_VOID);\n-                }\n-        );\n-    }\n-\n-    @POST\n-    @Path(\"/{tenantId}/metrics/numeric/{id}/data\")\n-    @ApiOperation(value = \"Add data for a single numeric metric.\")\n-    @ApiResponses(value = {\n-            @ApiResponse(code = 200, message = \"Adding data succeeded.\"),\n-            @ApiResponse(code = 400, message = \"Missing or invalid payload\",\n-                         response = ApiError.class),\n-            @ApiResponse(code = 500, message = \"Unexpected error happened while storing the data\",\n-                         response = ApiError.class),\n-    })\n-    public void addDataForMetric(\n-            @Suspended final AsyncResponse asyncResponse,\n-            @PathParam(\"tenantId\") final String tenantId, @PathParam(\"id\") String id,\n-            @ApiParam(value = \"List of datapoints containing timestamp and value\", required = true)\n-            List<NumericData> data\n-    ) {\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    if (data == null) {\n-                        return ApiUtils.emptyPayload();\n-                    }\n-                    NumericMetric metric = new NumericMetric(tenantId, new MetricId(id));\n-                    metric.getData().addAll(data);\n-                    ListenableFuture<Void> future = metricsService.addNumericData(Collections.singletonList(metric));\n-                    return Futures.transform(future, ApiUtils.MAP_VOID);\n-                }\n-        );\n-    }\n-\n-    @POST\n-    @Path(\"/{tenantId}/metrics/availability/{id}/data\")\n-    @ApiOperation(value = \"Add data for a single availability metric.\")\n-    @ApiResponses(value = {\n-            @ApiResponse(code = 200, message = \"Adding data succeeded.\"),\n-            @ApiResponse(code = 400, message = \"Missing or invalid payload\",\n-                         response = ApiError.class),\n-            @ApiResponse(code = 500, message = \"Unexpected error happened while storing the data\",\n-                         response = ApiError.class)\n-    })\n-    public void addAvailabilityForMetric(\n-            @Suspended final AsyncResponse asyncResponse,\n-            @PathParam(\"tenantId\") final String tenantId, @PathParam(\"id\") String id,\n-            @ApiParam(value = \"List of availability datapoints\", required = true) List<Availability> data\n-    ) {\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    if (data == null) {\n-                        return ApiUtils.emptyPayload();\n-                    }\n-                    AvailabilityMetric metric = new AvailabilityMetric(tenantId, new MetricId(id));\n-                    metric.getData().addAll(data);\n-                    ListenableFuture<Void>\n-                            future\n-                            = metricsService.addAvailabilityData(Collections.singletonList(metric));\n-                    return Futures.transform(future, ApiUtils.MAP_VOID);\n-                }\n-        );\n-    }\n-\n-    @POST\n-    @Path(\"/{tenantId}/metrics/numeric/data\")\n-    @ApiOperation(value = \"Add metric data for multiple numeric metrics in a single call.\")\n-    @ApiResponses(value = { @ApiResponse(code = 200, message = \"Adding data succeeded.\"),\n-            @ApiResponse(code = 500, message = \"Unexpected error happened while storing the data\",\n-                         response = ApiError.class)\n-    })\n-    public void addNumericData(@Suspended final AsyncResponse asyncResponse,\n-                               @PathParam(\"tenantId\") String tenantId,\n-                               @ApiParam(value = \"List of metrics\", required = true)\n-                               List<NumericMetric> metrics) {\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    if (metrics.isEmpty()) {\n-                        return Futures.immediateFuture(Response.ok().build());\n-                    }\n-                    metrics.forEach(m -> m.setTenantId(tenantId));\n-                    ListenableFuture<Void> future = metricsService.addNumericData(metrics);\n-                    return Futures.transform(future, ApiUtils.MAP_VOID);\n-                }\n-        );\n-    }\n-\n-    @POST\n-    @Path(\"/{tenantId}/metrics/availability/data\")\n-    @ApiOperation(value = \"Add metric data for multiple availability metrics in a single call.\")\n-    @ApiResponses(value = { @ApiResponse(code = 200, message = \"Adding data succeeded.\"),\n-            @ApiResponse(code = 500, message = \"Unexpected error happened while storing the data\",\n-                         response = ApiError.class)\n-    })\n-    public void addAvailabilityData(@Suspended final AsyncResponse asyncResponse,\n-        @PathParam(\"tenantId\") String tenantId, @ApiParam(value = \"List of availability metrics\", required = true)\n-        List<AvailabilityMetric> metrics) {\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    if (metrics.isEmpty()) {\n-                        return Futures.immediateFuture(Response.ok().build());\n-                    }\n-                    metrics.forEach(m -> m.setTenantId(tenantId));\n-                    ListenableFuture<Void> future = metricsService.addAvailabilityData(metrics);\n-                    return Futures.transform(future, ApiUtils.MAP_VOID);\n-                }\n-        );\n-    }\n-\n-    @GET\n-    @Path(\"/{tenantId}/numeric\")\n-    @ApiOperation(value = \"Find numeric metrics data by their tags.\", response = Map.class,\n-                  responseContainer = \"List\")\n-    @ApiResponses(value = {\n-            @ApiResponse(code = 200, message = \"Successfully fetched data.\"),\n-            @ApiResponse(code = 204, message = \"No matching data found.\"),\n-            @ApiResponse(code = 400, message = \"Missing or invalid tags query\", response = ApiError.class),\n-            @ApiResponse(code = 500, message = \"Any error in the query.\", response = ApiError.class),\n-    })\n-    public void findNumericDataByTags(\n-            @Suspended final AsyncResponse asyncResponse,\n-            @PathParam(\"tenantId\") String tenantId,\n-            @ApiParam(value = \"Tag list\", required = true) @QueryParam(\"tags\") Tags tags\n-    ) {\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    if (tags == null) {\n-                        return badRequest(new ApiError(\"Missing tags query\"));\n-                    }\n-                    ListenableFuture<Map<MetricId, Set<NumericData>>> future;\n-                    future = metricsService.findNumericDataByTags(tenantId, tags.getTags());\n-                    return Futures.transform(future, ApiUtils.MAP_MAP);\n-                }\n-        );\n-    }\n-\n-    @GET\n-    @Path(\"/{tenantId}/availability\")\n-    @ApiOperation(value = \"Find availabilities metrics data by their tags.\", response = Map.class,\n-                  responseContainer = \"List\")\n-    @ApiResponses(value = {\n-            @ApiResponse(code = 200, message = \"Successfully fetched data.\"),\n-            @ApiResponse(code = 204, message = \"No matching data found.\"),\n-            @ApiResponse(code = 400, message = \"Missing or invalid tags query\", response = ApiError.class),\n-            @ApiResponse(code = 500, message = \"Any error in the query.\", response = ApiError.class),\n-    })\n-    public void findAvailabilityDataByTags(\n-            @Suspended final AsyncResponse asyncResponse,\n-            @PathParam(\"tenantId\") String tenantId,\n-            @ApiParam(value = \"Tag list\", required = true) @QueryParam(\"tags\") Tags tags\n-    ) {\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    if (tags == null) {\n-                        return badRequest(new ApiError(\"Missing tags query\"));\n-                    }\n-                    ListenableFuture<Map<MetricId, Set<Availability>>> future;\n-                    future = metricsService.findAvailabilityByTags(tenantId, tags.getTags());\n-                    return Futures.transform(future, ApiUtils.MAP_MAP);\n-                }\n-        );\n-    }\n-\n-    @GET\n-    @Path(\"/{tenantId}/metrics/numeric/{id}/data\")\n-    @ApiOperation(value = \"Retrieve numeric data. When buckets or bucketDuration query parameter is used, the time \"\n-                          + \"range between start and end will be divided in buckets of equal duration, and metric \"\n-                          + \"statistics will be computed for each bucket.\", response = List.class)\n-    @ApiResponses(value = {\n-            @ApiResponse(code = 200, message = \"Successfully fetched numeric data.\"),\n-            @ApiResponse(code = 204, message = \"No numeric data was found.\"),\n-            @ApiResponse(code = 400, message = \"buckets or bucketDuration parameter is invalid, or both are used.\",\n-                         response = ApiError.class),\n-            @ApiResponse(code = 500, message = \"Unexpected error occurred while fetching numeric data.\",\n-                         response = ApiError.class)\n-    })\n-    public void findNumericData(\n-            @Suspended AsyncResponse asyncResponse,\n-            @PathParam(\"tenantId\") String tenantId,\n-            @PathParam(\"id\") String id,\n-            @ApiParam(value = \"Defaults to now - 8 hours\") @QueryParam(\"start\") final Long start,\n-            @ApiParam(value = \"Defaults to now\") @QueryParam(\"end\") final Long end,\n-            @ApiParam(value = \"Total number of buckets\") @QueryParam(\"buckets\") Integer bucketsCount,\n-            @ApiParam(value = \"Bucket duration\") @QueryParam(\"bucketDuration\") Duration bucketDuration\n-    ) {\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    long now = System.currentTimeMillis();\n-                    long startTime = start == null ? now - EIGHT_HOURS : start;\n-                    long endTime = end == null ? now : end;\n-\n-                    NumericMetric metric = new NumericMetric(tenantId, new MetricId(id));\n-\n-                    if (bucketsCount == null && bucketDuration == null) {\n-                        ListenableFuture<List<NumericData>> dataFuture = metricsService.findNumericData(\n-                                tenantId,\n-                                new MetricId(id), startTime, endTime\n-                        );\n-                        return Futures.transform(dataFuture, ApiUtils.MAP_COLLECTION);\n-                    }\n-\n-                    if (bucketsCount != null && bucketDuration != null) {\n-                        return badRequest(new ApiError(\"Both buckets and bucketDuration parameters are used\"));\n-                    }\n-\n-                    Buckets buckets;\n-                    try {\n-                        if (bucketsCount != null) {\n-                            buckets = Buckets.fromCount(startTime, endTime, bucketsCount);\n-                        } else {\n-                            buckets = Buckets.fromStep(startTime, endTime, bucketDuration.toMillis());\n-                        }\n-                    } catch (IllegalArgumentException e) {\n-                        return badRequest(new ApiError(\"Bucket: \" + e.getMessage()));\n-                    }\n-\n-                    ListenableFuture<BucketedOutput<NumericBucketDataPoint>> dataFuture;\n-                    dataFuture = metricsService.findNumericStats(metric, startTime, endTime, buckets);\n-\n-                    ListenableFuture<List<NumericBucketDataPoint>> outputFuture;\n-                    outputFuture = Futures.transform(dataFuture, BucketedOutput<NumericBucketDataPoint>::getData);\n-\n-                    return Futures.transform(outputFuture, ApiUtils.MAP_COLLECTION);\n-                }\n-        );\n-    }\n-\n-    @GET\n-    @Path(\"/{tenantId}/metrics/numeric/{id}/periods\")\n-    @ApiOperation(value = \"Retrieve periods for which the condition holds true for each consecutive data point.\",\n-        response = List.class)\n-    @ApiResponses(value = {\n-        @ApiResponse(code = 200, message = \"Successfully fetched periods.\"),\n-        @ApiResponse(code = 204, message = \"No numeric data was found.\"),\n-        @ApiResponse(code = 400, message = \"Missing or invalid query parameters\")})\n-    public void findPeriods(\n-        @Suspended final AsyncResponse asyncResponse, @PathParam(\"tenantId\") String tenantId,\n-        @PathParam(\"id\") String id,\n-        @ApiParam(value = \"Defaults to now - 8 hours\", required = false) @QueryParam(\"start\") final Long start,\n-        @ApiParam(value = \"Defaults to now\", required = false) @QueryParam(\"end\") final Long end,\n-        @ApiParam(value = \"A threshold against which values are compared\", required = true) @QueryParam(\"threshold\")\n-            double threshold,\n-        @ApiParam(value = \"A comparison operation to perform between values and the threshold. Supported operations \" +\n-            \"include ge, gte, lt, lte, and eq\", required = true) @QueryParam(\"op\") String operator) {\n-\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    long now = System.currentTimeMillis();\n-                    Long startTime = start;\n-                    Long endTime = end;\n-                    if (start == null) {\n-                        startTime = now - EIGHT_HOURS;\n-                    }\n-                    if (end == null) {\n-                        endTime = now;\n-                    }\n-\n-                    Predicate<Double> predicate;\n-                    switch (operator) {\n-                        case \"lt\":\n-                            predicate = d -> d < threshold;\n-                            break;\n-                        case \"lte\":\n-                            predicate = d -> d <= threshold;\n-                            break;\n-                        case \"eq\":\n-                            predicate = d -> d == threshold;\n-                            break;\n-                        case \"neq\":\n-                            predicate = d -> d != threshold;\n-                            break;\n-                        case \"gt\":\n-                            predicate = d -> d > threshold;\n-                            break;\n-                        case \"gte\":\n-                            predicate = d -> d >= threshold;\n-                            break;\n-                        default:\n-                            predicate = null;\n-                    }\n-\n-                    if (predicate == null) {\n-                        return badRequest(\n-                                new ApiError(\n-                                        \"Invalid value for op parameter. Supported values are lt, \" +\n-                                        \"lte, eq, gt, gte.\"\n-                                )\n-                        );\n-                    } else {\n-                        ListenableFuture<List<long[]>> future = metricsService.getPeriods(\n-                                tenantId, new MetricId(id), predicate,\n-                                startTime, endTime\n-                        );\n-                        return Futures.transform(future, ApiUtils.MAP_COLLECTION);\n-                    }\n-                }\n-        );\n-    }\n-\n-    @GET\n-    @Path(\"/{tenantId}/metrics/availability/{id}/data\")\n-    @ApiOperation(\n-            value = \"Retrieve availability data. When buckets or bucketDuration query parameter is used, the time \"\n-                    + \"range between start and end will be divided in buckets of equal duration, and availability \"\n-                    + \"statistics will be computed for each bucket.\", response = List.class)\n-    @ApiResponses(value = {\n-            @ApiResponse(code = 200, message = \"Successfully fetched availability data.\"),\n-            @ApiResponse(code = 204, message = \"No availability data was found.\"),\n-            @ApiResponse(code = 400, message = \"buckets or bucketDuration parameter is invalid, or both are used.\",\n-                         response = ApiError.class),\n-            @ApiResponse(code = 500, message = \"Unexpected error occurred while fetching availability data.\",\n-                         response = ApiError.class),\n-    })\n-    public void findAvailabilityData(\n-            @Suspended AsyncResponse asyncResponse,\n-            @PathParam(\"tenantId\") String tenantId,\n-            @PathParam(\"id\") String id,\n-            @ApiParam(value = \"Defaults to now - 8 hours\") @QueryParam(\"start\") final Long start,\n-            @ApiParam(value = \"Defaults to now\") @QueryParam(\"end\") final Long end,\n-            @ApiParam(value = \"Total number of buckets\") @QueryParam(\"buckets\") Integer bucketsCount,\n-            @ApiParam(value = \"Bucket duration\") @QueryParam(\"bucketDuration\") Duration bucketDuration,\n-            @ApiParam(value = \"Set to true to return only distinct, contiguous values\")\n-                @QueryParam(\"distinct\") Boolean distinct\n-    ) {\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    long now = System.currentTimeMillis();\n-                    Long startTime = start == null ? now - EIGHT_HOURS : start;\n-                    Long endTime = end == null ? now : end;\n-\n-                    AvailabilityMetric metric = new AvailabilityMetric(tenantId, new MetricId(id));\n-                    ListenableFuture<List<Availability>> queryFuture;\n-\n-                    if (distinct != null && distinct.equals(Boolean.TRUE)) {\n-                        queryFuture = metricsService.findAvailabilityData(tenantId, metric.getId(), startTime,\n-                                endTime, distinct);\n-                        return Futures.transform(queryFuture, ApiUtils.MAP_COLLECTION);\n-                    }\n-\n-                    if (bucketsCount == null && bucketDuration == null) {\n-                        queryFuture = metricsService.findAvailabilityData(tenantId, metric.getId(), startTime, endTime);\n-                        return Futures.transform(queryFuture, ApiUtils.MAP_COLLECTION);\n-                    }\n-\n-                    if (bucketsCount != null && bucketDuration != null) {\n-                        return badRequest(new ApiError(\"Both buckets and bucketDuration parameters are used\"));\n-                    }\n-\n-                    Buckets buckets;\n-                    try {\n-                        if (bucketsCount != null) {\n-                            buckets = Buckets.fromCount(startTime, endTime, bucketsCount);\n-                        } else {\n-                            buckets = Buckets.fromStep(startTime, endTime, bucketDuration.toMillis());\n-                        }\n-                    } catch (IllegalArgumentException e) {\n-                        return badRequest(new ApiError(\"Bucket: \" + e.getMessage()));\n-                    }\n-                    ListenableFuture<BucketedOutput<AvailabilityBucketDataPoint>> dataFuture;\n-                    dataFuture = metricsService.findAvailabilityStats(metric, startTime, endTime, buckets);\n-\n-                    ListenableFuture<List<AvailabilityBucketDataPoint>> outputFuture;\n-                    outputFuture = Futures.transform(dataFuture, BucketedOutput<AvailabilityBucketDataPoint>::getData);\n-                    return Futures.transform(outputFuture, ApiUtils.MAP_COLLECTION);\n-                }\n-        );\n-    }\n-\n-    @POST\n-    @Path(\"/{tenantId}/metrics/numeric/{id}/tag\")\n-    @ApiOperation(value = \"Add or update numeric metric's tags.\")\n-    @ApiResponses(value = { @ApiResponse(code = 200, message = \"Tags were modified successfully.\")})\n-    public void tagNumericData(@Suspended final AsyncResponse asyncResponse, @PathParam(\"tenantId\") String tenantId,\n-            @PathParam(\"id\") final String id, @ApiParam(required = true) TagRequest params) {\n-\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    ListenableFuture<List<NumericData>> future;\n-                    NumericMetric metric = new NumericMetric(tenantId, new MetricId(id));\n-                    if (params.getTimestamp() != null) {\n-                        future = metricsService.tagNumericData(metric, params.getTags(), params.getTimestamp());\n-                    } else {\n-                        future = metricsService.tagNumericData(\n-                                metric,\n-                                params.getTags(),\n-                                params.getStart(),\n-                                params.getEnd()\n-                        );\n-                    }\n-                    return Futures.transform(future, (List<NumericData> data) -> Response.ok().build());\n-                }\n-        );\n-    }\n-\n-    @POST\n-    @Path(\"/{tenantId}/metrics/availability/{id}/tag\")\n-    @ApiOperation(value = \"Add or update availability metric's tags.\")\n-    @ApiResponses(value = { @ApiResponse(code = 200, message = \"Tags were modified successfully.\")})\n-    public void tagAvailabilityData(@Suspended final AsyncResponse asyncResponse,\n-            @PathParam(\"tenantId\") String tenantId, @PathParam(\"id\") final String id,\n-            @ApiParam(required = true) TagRequest params) {\n-\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    ListenableFuture<List<Availability>> future;\n-                    AvailabilityMetric metric = new AvailabilityMetric(tenantId, new MetricId(id));\n-                    if (params.getTimestamp() != null) {\n-                        future = metricsService.tagAvailabilityData(metric, params.getTags(), params.getTimestamp());\n-                    } else {\n-                        future = metricsService.tagAvailabilityData(\n-                                metric, params.getTags(), params.getStart(),\n-                                params.getEnd()\n-                        );\n-                    }\n-                    return Futures.transform(future, (List<Availability> data) -> Response.ok().build());\n-                }\n-        );\n-    }\n-\n-    @GET\n-    @Path(\"/{tenantId}/tags/numeric/{tags}\")\n-    @ApiOperation(value = \"Find numeric metric data with given tags.\", response = Map.class,\n-                  responseContainer = \"List\")\n-    @ApiResponses(value = {\n-            @ApiResponse(code = 200, message = \"Numeric values fetched successfully\"),\n-            @ApiResponse(code = 204, message = \"No matching data found.\"),\n-            @ApiResponse(code = 400, message = \"Invalid tags\", response = ApiError.class),\n-            @ApiResponse(code = 500, message = \"Any error while fetching data.\", response = ApiError.class),\n-    })\n-    public void findTaggedNumericData(\n-            @Suspended final AsyncResponse asyncResponse,\n-            @PathParam(\"tenantId\") String tenantId,\n-            @ApiParam(\"Tag list\") @PathParam(\"tags\") Tags tags\n-    ) {\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    ListenableFuture<Map<MetricId, Set<NumericData>>> queryFuture;\n-                    queryFuture = metricsService.findNumericDataByTags(tenantId, tags.getTags());\n-                    ListenableFuture<Map<String, Set<NumericData>>> resultFuture = Futures.transform(\n-                            queryFuture,\n-                            new Function<Map<MetricId, Set<NumericData>>, Map<String, Set<NumericData>>>() {\n-                                @Override\n-                                public Map<String, Set<NumericData>> apply(Map<MetricId, Set<NumericData>> input) {\n-                                    Map<String, Set<NumericData>> result = new HashMap<>(input.size());\n-                                    for (Map.Entry<MetricId, Set<NumericData>> entry : input.entrySet()) {\n-                                        result.put(entry.getKey().getName(), entry.getValue());\n-                                    }\n-                                    return result;\n-                                }\n-                            }\n-                    );\n-                    return Futures.transform(resultFuture, ApiUtils.MAP_MAP);\n-                }\n-        );\n-    }\n-\n-    @GET\n-    @Path(\"/{tenantId}/tags/availability/{tags}\")\n-    @ApiOperation(value = \"Find availability metric data with given tags.\", response = Map.class,\n-                  responseContainer = \"List\")\n-    @ApiResponses(value = {\n-            @ApiResponse(code = 200, message = \"Availability values fetched successfully\"),\n-            @ApiResponse(code = 204, message = \"No matching data found.\"),\n-            @ApiResponse(code = 400, message = \"Invalid tags\", response = ApiError.class),\n-            @ApiResponse(code = 500, message = \"Any error while fetching data.\", response = ApiError.class),\n-    })\n-    public void findTaggedAvailabilityData(\n-            @Suspended final AsyncResponse asyncResponse,\n-            @PathParam(\"tenantId\") String tenantId,\n-            @ApiParam(\"Tag list\") @PathParam(\"tags\") Tags tags\n-    ) {\n-        executeAsync(\n-                asyncResponse, () -> {\n-                    ListenableFuture<Map<MetricId, Set<Availability>>> future;\n-                    future = metricsService.findAvailabilityByTags(tenantId, tags.getTags());\n-                    return Futures.transform(future, ApiUtils.MAP_MAP);\n-                }\n-        );\n-    }\n-\n-    @POST\n-    @Path(\"/counters\")\n-    @ApiOperation(value = \"List of counter definitions\", hidden = true)\n-    public void updateCountersForGroups(@Suspended final AsyncResponse asyncResponse, Collection<Counter> counters) {\n-        ListenableFuture<Void> future = metricsService.updateCounters(counters);\n-        Futures.addCallback(future, new NoDataCallback<>(asyncResponse));\n-    }\n-\n-    @POST\n-    @Path(\"/counters/{group}\")\n-    @ApiOperation(value = \"Update multiple counters in a single counter group\", hidden = true)\n-    public void updateCounterForGroup(@Suspended final AsyncResponse asyncResponse, @PathParam(\"group\") String group,\n-        Collection<Counter> counters) {\n-        for (Counter counter : counters) {\n-            counter.setGroup(group);\n-        }\n-        ListenableFuture<Void> future = metricsService.updateCounters(counters);\n-        Futures.addCallback(future, new NoDataCallback<>(asyncResponse));\n-    }\n-\n-    @POST\n-    @Path(\"/counters/{group}/{counter}\")\n-    @ApiOperation(value = \"Increase value of a counter\", hidden = true)\n-    public void updateCounter(@Suspended final AsyncResponse asyncResponse, @PathParam(\"group\") String group,\n-        @PathParam(\"counter\") String counter) {\n-        ListenableFuture<Void> future = metricsService\n-                .updateCounter(new Counter(DEFAULT_TENANT_ID, group, counter, 1L));\n-        Futures.addCallback(future, new NoDataCallback<>(asyncResponse));\n-    }\n-\n-    @POST\n-    @Path(\"/counters/{group}/{counter}/{value}\")\n-    @ApiOperation(value = \"Update value of a counter\", hidden = true)\n-    public void updateCounter(@Suspended final AsyncResponse asyncResponse, @PathParam(\"group\") String group,\n-        @PathParam(\"counter\") String counter, @PathParam(\"value\") Long value) {\n-        ListenableFuture<Void> future = metricsService.updateCounter(new Counter(DEFAULT_TENANT_ID, group, counter,\n-                value));\n-        Futures.addCallback(future, new NoDataCallback<>(asyncResponse));\n-    }\n-\n-    @GET\n-    @Path(\"/counters/{group}\")\n-    @ApiOperation(value = \"Retrieve a list of counter values in this group\", hidden = true, response = Counter.class,\n-            responseContainer = \"List\")\n-    @Produces({ APPLICATION_JSON })\n-    public void getCountersForGroup(@Suspended final AsyncResponse asyncResponse, @PathParam(\"group\") String group) {\n-        ListenableFuture<List<Counter>> future = metricsService.findCounters(group);\n-        Futures.addCallback(future, new SimpleDataCallback<>(asyncResponse));\n-    }\n-\n-    @GET\n-    @Path(\"/counters/{group}/{counter}\")\n-    @ApiOperation(value = \"Retrieve value of a counter\", hidden = true, response = Counter.class,\n-            responseContainer = \"List\")\n-    public void getCounter(@Suspended final AsyncResponse asyncResponse, @PathParam(\"group\") final String group,\n-        @PathParam(\"counter\") final String counter) {\n-        ListenableFuture<List<Counter>> future = metricsService.findCounters(group, Collections.singletonList(counter));\n-        Futures.addCallback(future, new FutureCallback<List<Counter>>() {\n-            @Override\n-            public void onSuccess(List<Counter> counters) {\n-                if (counters.isEmpty()) {\n-                    asyncResponse.resume(Response.status(404).entity(\"Counter[group: \" + group + \", name: \" +\n-                            counter + \"] not found\").build());\n-                } else {\n-                    Response jaxrs = Response.ok(counters.get(0)).build();\n-                    asyncResponse.resume(jaxrs);\n-                }\n-            }\n-\n-            @Override\n-            public void onFailure(Throwable t) {\n-                asyncResponse.resume(t);\n-            }\n-        });\n-    }\n-\n-    @GET\n-    @Path(\"/{tenantId}/metrics\")\n+    @Path(\"/{tenantId}\")","path":"api/metrics-api-jaxrs/src/main/java/org/hawkular/metrics/api/jaxrs/MetricHandler.java","position":827,"original_position":827,"commit_id":"810813cecc2dd76e3a0ce4092bebf0ebaa3444d7","original_commit_id":"e6a9be1f18685bf314da3999a94c8dec5f8a64b4","user":{"login":"tsegismont","id":1500598,"avatar_url":"https://avatars.githubusercontent.com/u/1500598?v=3","gravatar_id":"","url":"https://api.github.com/users/tsegismont","html_url":"https://github.com/tsegismont","followers_url":"https://api.github.com/users/tsegismont/followers","following_url":"https://api.github.com/users/tsegismont/following{/other_user}","gists_url":"https://api.github.com/users/tsegismont/gists{/gist_id}","starred_url":"https://api.github.com/users/tsegismont/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tsegismont/subscriptions","organizations_url":"https://api.github.com/users/tsegismont/orgs","repos_url":"https://api.github.com/users/tsegismont/repos","events_url":"https://api.github.com/users/tsegismont/events{/privacy}","received_events_url":"https://api.github.com/users/tsegismont/received_events","type":"User","site_admin":false},"body":"+1","created_at":"2015-04-22T16:58:35Z","updated_at":"2015-04-22T16:58:35Z","html_url":"https://github.com/hawkular/hawkular-metrics/pull/197#discussion_r28892621","pull_request_url":"https://api.github.com/repos/hawkular/hawkular-metrics/pulls/197","_links":{"self":{"href":"https://api.github.com/repos/hawkular/hawkular-metrics/pulls/comments/28892621"},"html":{"href":"https://github.com/hawkular/hawkular-metrics/pull/197#discussion_r28892621"},"pull_request":{"href":"https://api.github.com/repos/hawkular/hawkular-metrics/pulls/197"}}},"pull_request":{"url":"https://api.github.com/repos/hawkular/hawkular-metrics/pulls/197","id":33068787,"html_url":"https://github.com/hawkular/hawkular-metrics/pull/197","diff_url":"https://github.com/hawkular/hawkular-metrics/pull/197.diff","patch_url":"https://github.com/hawkular/hawkular-metrics/pull/197.patch","issue_url":"https://api.github.com/repos/hawkular/hawkular-metrics/issues/197","number":197,"state":"open","locked":false,"title":"REST API - remake","user":{"login":"stefannegrea","id":3912943,"avatar_url":"https://avatars.githubusercontent.com/u/3912943?v=3","gravatar_id":"","url":"https://api.github.com/users/stefannegrea","html_url":"https://github.com/stefannegrea","followers_url":"https://api.github.com/users/stefannegrea/followers","following_url":"https://api.github.com/users/stefannegrea/following{/other_user}","gists_url":"https://api.github.com/users/stefannegrea/gists{/gist_id}","starred_url":"https://api.github.com/users/stefannegrea/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stefannegrea/subscriptions","organizations_url":"https://api.github.com/users/stefannegrea/orgs","repos_url":"https://api.github.com/users/stefannegrea/repos","events_url":"https://api.github.com/users/stefannegrea/events{/privacy}","received_events_url":"https://api.github.com/users/stefannegrea/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-04-10T17:57:52Z","updated_at":"2015-04-22T16:58:35Z","closed_at":null,"merged_at":null,"merge_commit_sha":"9543baf4b7278073a0b33b543c41181519dd812d","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/hawkular/hawkular-metrics/pulls/197/commits","review_comments_url":"https://api.github.com/repos/hawkular/hawkular-metrics/pulls/197/comments","review_comment_url":"https://api.github.com/repos/hawkular/hawkular-metrics/pulls/comments{/number}","comments_url":"https://api.github.com/repos/hawkular/hawkular-metrics/issues/197/comments","statuses_url":"https://api.github.com/repos/hawkular/hawkular-metrics/statuses/810813cecc2dd76e3a0ce4092bebf0ebaa3444d7","head":{"label":"hawkular:restremake","ref":"restremake","sha":"810813cecc2dd76e3a0ce4092bebf0ebaa3444d7","user":{"login":"hawkular","id":10179627,"avatar_url":"https://avatars.githubusercontent.com/u/10179627?v=3","gravatar_id":"","url":"https://api.github.com/users/hawkular","html_url":"https://github.com/hawkular","followers_url":"https://api.github.com/users/hawkular/followers","following_url":"https://api.github.com/users/hawkular/following{/other_user}","gists_url":"https://api.github.com/users/hawkular/gists{/gist_id}","starred_url":"https://api.github.com/users/hawkular/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hawkular/subscriptions","organizations_url":"https://api.github.com/users/hawkular/orgs","repos_url":"https://api.github.com/users/hawkular/repos","events_url":"https://api.github.com/users/hawkular/events{/privacy}","received_events_url":"https://api.github.com/users/hawkular/received_events","type":"Organization","site_admin":false},"repo":{"id":17705626,"name":"hawkular-metrics","full_name":"hawkular/hawkular-metrics","owner":{"login":"hawkular","id":10179627,"avatar_url":"https://avatars.githubusercontent.com/u/10179627?v=3","gravatar_id":"","url":"https://api.github.com/users/hawkular","html_url":"https://github.com/hawkular","followers_url":"https://api.github.com/users/hawkular/followers","following_url":"https://api.github.com/users/hawkular/following{/other_user}","gists_url":"https://api.github.com/users/hawkular/gists{/gist_id}","starred_url":"https://api.github.com/users/hawkular/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hawkular/subscriptions","organizations_url":"https://api.github.com/users/hawkular/orgs","repos_url":"https://api.github.com/users/hawkular/repos","events_url":"https://api.github.com/users/hawkular/events{/privacy}","received_events_url":"https://api.github.com/users/hawkular/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hawkular/hawkular-metrics","description":"Time Series Metrics Engine based on Cassandra","fork":false,"url":"https://api.github.com/repos/hawkular/hawkular-metrics","forks_url":"https://api.github.com/repos/hawkular/hawkular-metrics/forks","keys_url":"https://api.github.com/repos/hawkular/hawkular-metrics/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hawkular/hawkular-metrics/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hawkular/hawkular-metrics/teams","hooks_url":"https://api.github.com/repos/hawkular/hawkular-metrics/hooks","issue_events_url":"https://api.github.com/repos/hawkular/hawkular-metrics/issues/events{/number}","events_url":"https://api.github.com/repos/hawkular/hawkular-metrics/events","assignees_url":"https://api.github.com/repos/hawkular/hawkular-metrics/assignees{/user}","branches_url":"https://api.github.com/repos/hawkular/hawkular-metrics/branches{/branch}","tags_url":"https://api.github.com/repos/hawkular/hawkular-metrics/tags","blobs_url":"https://api.github.com/repos/hawkular/hawkular-metrics/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hawkular/hawkular-metrics/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hawkular/hawkular-metrics/git/refs{/sha}","trees_url":"https://api.github.com/repos/hawkular/hawkular-metrics/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hawkular/hawkular-metrics/statuses/{sha}","languages_url":"https://api.github.com/repos/hawkular/hawkular-metrics/languages","stargazers_url":"https://api.github.com/repos/hawkular/hawkular-metrics/stargazers","contributors_url":"https://api.github.com/repos/hawkular/hawkular-metrics/contributors","subscribers_url":"https://api.github.com/repos/hawkular/hawkular-metrics/subscribers","subscription_url":"https://api.github.com/repos/hawkular/hawkular-metrics/subscription","commits_url":"https://api.github.com/repos/hawkular/hawkular-metrics/commits{/sha}","git_commits_url":"https://api.github.com/repos/hawkular/hawkular-metrics/git/commits{/sha}","comments_url":"https://api.github.com/repos/hawkular/hawkular-metrics/comments{/number}","issue_comment_url":"https://api.github.com/repos/hawkular/hawkular-metrics/issues/comments{/number}","contents_url":"https://api.github.com/repos/hawkular/hawkular-metrics/contents/{+path}","compare_url":"https://api.github.com/repos/hawkular/hawkular-metrics/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hawkular/hawkular-metrics/merges","archive_url":"https://api.github.com/repos/hawkular/hawkular-metrics/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hawkular/hawkular-metrics/downloads","issues_url":"https://api.github.com/repos/hawkular/hawkular-metrics/issues{/number}","pulls_url":"https://api.github.com/repos/hawkular/hawkular-metrics/pulls{/number}","milestones_url":"https://api.github.com/repos/hawkular/hawkular-metrics/milestones{/number}","notifications_url":"https://api.github.com/repos/hawkular/hawkular-metrics/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hawkular/hawkular-metrics/labels{/name}","releases_url":"https://api.github.com/repos/hawkular/hawkular-metrics/releases{/id}","created_at":"2014-03-13T10:07:30Z","updated_at":"2015-04-20T20:52:12Z","pushed_at":"2015-04-22T16:56:01Z","git_url":"git://github.com/hawkular/hawkular-metrics.git","ssh_url":"git@github.com:hawkular/hawkular-metrics.git","clone_url":"https://github.com/hawkular/hawkular-metrics.git","svn_url":"https://github.com/hawkular/hawkular-metrics","homepage":"","size":16168,"stargazers_count":36,"watchers_count":36,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":29,"mirror_url":null,"open_issues_count":14,"forks":29,"open_issues":14,"watchers":36,"default_branch":"master"}},"base":{"label":"hawkular:master","ref":"master","sha":"5ce9f15cfa6ef827bcd65e5c5ecff6137c5f1677","user":{"login":"hawkular","id":10179627,"avatar_url":"https://avatars.githubusercontent.com/u/10179627?v=3","gravatar_id":"","url":"https://api.github.com/users/hawkular","html_url":"https://github.com/hawkular","followers_url":"https://api.github.com/users/hawkular/followers","following_url":"https://api.github.com/users/hawkular/following{/other_user}","gists_url":"https://api.github.com/users/hawkular/gists{/gist_id}","starred_url":"https://api.github.com/users/hawkular/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hawkular/subscriptions","organizations_url":"https://api.github.com/users/hawkular/orgs","repos_url":"https://api.github.com/users/hawkular/repos","events_url":"https://api.github.com/users/hawkular/events{/privacy}","received_events_url":"https://api.github.com/users/hawkular/received_events","type":"Organization","site_admin":false},"repo":{"id":17705626,"name":"hawkular-metrics","full_name":"hawkular/hawkular-metrics","owner":{"login":"hawkular","id":10179627,"avatar_url":"https://avatars.githubusercontent.com/u/10179627?v=3","gravatar_id":"","url":"https://api.github.com/users/hawkular","html_url":"https://github.com/hawkular","followers_url":"https://api.github.com/users/hawkular/followers","following_url":"https://api.github.com/users/hawkular/following{/other_user}","gists_url":"https://api.github.com/users/hawkular/gists{/gist_id}","starred_url":"https://api.github.com/users/hawkular/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hawkular/subscriptions","organizations_url":"https://api.github.com/users/hawkular/orgs","repos_url":"https://api.github.com/users/hawkular/repos","events_url":"https://api.github.com/users/hawkular/events{/privacy}","received_events_url":"https://api.github.com/users/hawkular/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hawkular/hawkular-metrics","description":"Time Series Metrics Engine based on Cassandra","fork":false,"url":"https://api.github.com/repos/hawkular/hawkular-metrics","forks_url":"https://api.github.com/repos/hawkular/hawkular-metrics/forks","keys_url":"https://api.github.com/repos/hawkular/hawkular-metrics/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hawkular/hawkular-metrics/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hawkular/hawkular-metrics/teams","hooks_url":"https://api.github.com/repos/hawkular/hawkular-metrics/hooks","issue_events_url":"https://api.github.com/repos/hawkular/hawkular-metrics/issues/events{/number}","events_url":"https://api.github.com/repos/hawkular/hawkular-metrics/events","assignees_url":"https://api.github.com/repos/hawkular/hawkular-metrics/assignees{/user}","branches_url":"https://api.github.com/repos/hawkular/hawkular-metrics/branches{/branch}","tags_url":"https://api.github.com/repos/hawkular/hawkular-metrics/tags","blobs_url":"https://api.github.com/repos/hawkular/hawkular-metrics/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hawkular/hawkular-metrics/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hawkular/hawkular-metrics/git/refs{/sha}","trees_url":"https://api.github.com/repos/hawkular/hawkular-metrics/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hawkular/hawkular-metrics/statuses/{sha}","languages_url":"https://api.github.com/repos/hawkular/hawkular-metrics/languages","stargazers_url":"https://api.github.com/repos/hawkular/hawkular-metrics/stargazers","contributors_url":"https://api.github.com/repos/hawkular/hawkular-metrics/contributors","subscribers_url":"https://api.github.com/repos/hawkular/hawkular-metrics/subscribers","subscription_url":"https://api.github.com/repos/hawkular/hawkular-metrics/subscription","commits_url":"https://api.github.com/repos/hawkular/hawkular-metrics/commits{/sha}","git_commits_url":"https://api.github.com/repos/hawkular/hawkular-metrics/git/commits{/sha}","comments_url":"https://api.github.com/repos/hawkular/hawkular-metrics/comments{/number}","issue_comment_url":"https://api.github.com/repos/hawkular/hawkular-metrics/issues/comments{/number}","contents_url":"https://api.github.com/repos/hawkular/hawkular-metrics/contents/{+path}","compare_url":"https://api.github.com/repos/hawkular/hawkular-metrics/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hawkular/hawkular-metrics/merges","archive_url":"https://api.github.com/repos/hawkular/hawkular-metrics/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hawkular/hawkular-metrics/downloads","issues_url":"https://api.github.com/repos/hawkular/hawkular-metrics/issues{/number}","pulls_url":"https://api.github.com/repos/hawkular/hawkular-metrics/pulls{/number}","milestones_url":"https://api.github.com/repos/hawkular/hawkular-metrics/milestones{/number}","notifications_url":"https://api.github.com/repos/hawkular/hawkular-metrics/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hawkular/hawkular-metrics/labels{/name}","releases_url":"https://api.github.com/repos/hawkular/hawkular-metrics/releases{/id}","created_at":"2014-03-13T10:07:30Z","updated_at":"2015-04-20T20:52:12Z","pushed_at":"2015-04-22T16:56:01Z","git_url":"git://github.com/hawkular/hawkular-metrics.git","ssh_url":"git@github.com:hawkular/hawkular-metrics.git","clone_url":"https://github.com/hawkular/hawkular-metrics.git","svn_url":"https://github.com/hawkular/hawkular-metrics","homepage":"","size":16168,"stargazers_count":36,"watchers_count":36,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":29,"mirror_url":null,"open_issues_count":14,"forks":29,"open_issues":14,"watchers":36,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/hawkular/hawkular-metrics/pulls/197"},"html":{"href":"https://github.com/hawkular/hawkular-metrics/pull/197"},"issue":{"href":"https://api.github.com/repos/hawkular/hawkular-metrics/issues/197"},"comments":{"href":"https://api.github.com/repos/hawkular/hawkular-metrics/issues/197/comments"},"review_comments":{"href":"https://api.github.com/repos/hawkular/hawkular-metrics/pulls/197/comments"},"review_comment":{"href":"https://api.github.com/repos/hawkular/hawkular-metrics/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/hawkular/hawkular-metrics/pulls/197/commits"},"statuses":{"href":"https://api.github.com/repos/hawkular/hawkular-metrics/statuses/810813cecc2dd76e3a0ce4092bebf0ebaa3444d7"}}}}