{"action":"created","comment":{"url":"https://api.github.com/repos/rackerlabs/blueflood/pulls/comments/40032588","id":40032588,"diff_hunk":"@@ -0,0 +1,309 @@\n+/*\n+ * Copyright 2013 Rackspace\n+ *\n+ *    Licensed under the Apache License, Version 2.0 (the \"License\");\n+ *    you may not use this file except in compliance with the License.\n+ *    You may obtain a copy of the License at\n+ *\n+ *        http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ *    Unless required by applicable law or agreed to in writing, software\n+ *    distributed under the License is distributed on an \"AS IS\" BASIS,\n+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ *    See the License for the specific language governing permissions and\n+ *    limitations under the License.\n+ */\n+\n+package com.rackspacecloud.blueflood.io;\n+\n+import com.github.tlrx.elasticsearch.test.EsSetup;\n+import com.rackspacecloud.blueflood.service.ElasticClientManager;\n+import org.elasticsearch.action.ListenableActionFuture;\n+import org.elasticsearch.client.Client;\n+import org.elasticsearch.action.bulk.BulkRequestBuilder;\n+import com.rackspacecloud.blueflood.types.*;\n+import com.rackspacecloud.blueflood.utils.TimeValue;\n+import junit.framework.Assert;\n+import org.elasticsearch.action.index.IndexRequestBuilder;\n+import org.elasticsearch.common.xcontent.XContentBuilder;\n+import org.junit.After;\n+import org.junit.Before;\n+import org.junit.Test;\n+import static org.mockito.Mockito.*;\n+\n+import java.io.IOException;\n+import java.util.ArrayList;\n+import java.util.List;\n+import java.util.concurrent.TimeUnit;\n+\n+public class EnumElasticIOTest {\n+\n+    private EnumElasticIO enumElasticIO;\n+    private EsSetup esSetup;\n+    private Client esClientMock = mock(Client.class);\n+    private BulkRequestBuilder bulkRequestBuilderMock = mock(BulkRequestBuilder.class);\n+\n+    private static final String TENANT_1 = \"100000\";\n+    private static final String TENANT_2 = \"200000\";\n+\n+    private static final String METRIC_NAME_A1 = \"a.m1\";\n+    private static final String METRIC_NAME_A2 = \"a.m2\";\n+\n+    private static final String METRIC_NAME_B1 = \"b.m1\";\n+    private static final String METRIC_NAME_B2 = \"b.m2\";\n+    private static final String METRIC_NAME_B3 = \"b.m3\";\n+\n+    BluefloodEnumRollup rollupWithEnumValues = new BluefloodEnumRollup()\n+            .withEnumValue(\"v1\", 1L)\n+            .withEnumValue(\"v2\", 1L)\n+            .withEnumValue(\"v3\", 1L);\n+    ArrayList<String> enumValues = rollupWithEnumValues.getStringEnumValues();\n+\n+    @Before\n+    public void setup() throws IOException {\n+        esSetup = new EsSetup();\n+        esSetup.execute(EsSetup.deleteAll());\n+        esSetup.execute(EsSetup.createIndex(EnumElasticIO.ENUMS_INDEX_NAME_WRITE)\n+                .withSettings(EsSetup.fromClassPath(\"index_settings.json\"))\n+                .withMapping(EnumElasticIO.ENUMS_DOCUMENT_TYPE, EsSetup.fromClassPath(\"metrics_mapping_enums.json\")));\n+\n+        enumElasticIO = new EnumElasticIO(esSetup.client());\n+        enumElasticIO.setINDEX_NAME_READ(EnumElasticIO.ENUMS_INDEX_NAME_WRITE);\n+        enumElasticIO.setINDEX_NAME_WRITE(EnumElasticIO.ENUMS_INDEX_NAME_WRITE);\n+    }\n+\n+    @After\n+    public void tearDown() {\n+        esSetup.terminate();\n+    }\n+\n+    @Test\n+    public void testCreateEnumElasticIO() {\n+        EnumElasticIO enumElasticIO1 = new EnumElasticIO();\n+        Assert.assertNotNull(\"create EnumElasticIO() failed\", enumElasticIO1);\n+\n+        EnumElasticIO enumElasticIO2 = new EnumElasticIO(esClientMock);\n+        Assert.assertNotNull(\"create EnumElasticIO(client) failed\", enumElasticIO2);\n+\n+        ElasticClientManager managerMock = mock(ElasticClientManager.class);\n+        EnumElasticIO enumElasticIO3 = new EnumElasticIO(managerMock);\n+        Assert.assertNotNull(\"create EnumElasticIO(manager) failed\", enumElasticIO3);\n+        verify(managerMock, times(1)).getClient();\n+    }\n+\n+    @Test(expected=IllegalArgumentException.class)\n+    public void testCreateSingleRequest_WithNullMetricName() throws IOException {\n+        Discovery discovery = new Discovery(TENANT_1, null);\n+        enumElasticIO.createSingleRequest(discovery);\n+    }\n+\n+    @Test\n+    public void testCreateSingleRequest() throws IOException {\n+        Discovery discovery = new Discovery(TENANT_1, METRIC_NAME_A1);\n+        IndexRequestBuilder builder = enumElasticIO.createSingleRequest(discovery);\n+        Assert.assertNotNull(builder);\n+        Assert.assertEquals(TENANT_1 + \":\" + METRIC_NAME_A1, builder.request().id());\n+        final String expectedIndex =\n+                \"index {\" +\n+                    \"[\" + EnumElasticIO.ENUMS_INDEX_NAME_WRITE + \"]\" +\n+                    \"[\" + EnumElasticIO.ENUMS_DOCUMENT_TYPE + \"]\" +\n+                    \"[\"+ TENANT_1 + \":\" + METRIC_NAME_A1 + \"], \" +\n+                    \"source[{\" +\n+                        \"\\\"tenantId\\\":\\\"\" + TENANT_1 + \"\\\",\" +\n+                        \"\\\"metric_name\\\":\\\"\" + METRIC_NAME_A1 + \"\\\"\" +\n+                    \"}]}\";\n+        Assert.assertEquals(expectedIndex, builder.request().toString());\n+        Assert.assertEquals(builder.request().routing(), TENANT_1);\n+    }\n+\n+    @Test\n+    public void testInsertDiscoveryWithEmptyBatch() throws IOException {\n+        when(esClientMock.prepareBulk()).thenReturn(bulkRequestBuilderMock);\n+        enumElasticIO.setClient(esClientMock);\n+\n+        // create empty metrics list and call insertDiscovery with it\n+        List<IMetric> metrics = new ArrayList<IMetric>();\n+        enumElasticIO.insertDiscovery(metrics);\n+\n+        // verify nothing is executed\n+        verify(esClientMock, never()).prepareBulk();\n+        verify(bulkRequestBuilderMock, never()).execute();\n+    }\n+\n+    @Test\n+    public void testInsertDiscoveryWithInvalidMetricClass() throws IOException {\n+        ListenableActionFuture listenableActionFutureMock = mock(ListenableActionFuture.class);\n+        when(esClientMock.prepareBulk()).thenReturn(bulkRequestBuilderMock);\n+        when(bulkRequestBuilderMock.execute()).thenReturn(listenableActionFutureMock);\n+        enumElasticIO.setClient(esClientMock);\n+\n+        // create empty metrics list and call insertDiscovery with it\n+        List<IMetric> metrics = new ArrayList<IMetric>();\n+        Locator locator = Locator.createLocatorFromPathComponents(TENANT_1, METRIC_NAME_A1);\n+        metrics.add(new Metric(locator, \"\", 0L, new TimeValue(1, TimeUnit.DAYS), null));\n+        enumElasticIO.insertDiscovery(metrics);\n+\n+        // verify\n+        verify(bulkRequestBuilderMock, never()).add(any(IndexRequestBuilder.class));\n+    }\n+\n+    @Test\n+    public void testInsertDiscovery() throws IOException {\n+        // setup mock for BulkRequestBuilder\n+        ListenableActionFuture listenableActionFutureMock = mock(ListenableActionFuture.class);\n+        when(bulkRequestBuilderMock.execute()).thenReturn(listenableActionFutureMock);\n+\n+        // setup mock for ElasticSearch Client\n+        IndexRequestBuilder indexRequestBuilderMock = mock(IndexRequestBuilder.class);\n+        when(esClientMock.prepareBulk()).thenReturn(bulkRequestBuilderMock);\n+        when(esClientMock.prepareIndex(EnumElasticIO.ENUMS_INDEX_NAME_WRITE, EnumElasticIO.ENUMS_DOCUMENT_TYPE))\n+                .thenReturn(indexRequestBuilderMock);\n+        when(indexRequestBuilderMock.setId(anyString())).thenReturn(indexRequestBuilderMock);\n+        when(indexRequestBuilderMock.setSource(any(XContentBuilder.class))).thenReturn(indexRequestBuilderMock);\n+        when(indexRequestBuilderMock.setCreate(anyBoolean())).thenReturn(indexRequestBuilderMock);\n+        when(indexRequestBuilderMock.setRouting(anyString())).thenReturn(indexRequestBuilderMock);\n+        enumElasticIO.setClient(esClientMock);\n+\n+        // create PreaggregatedMetric metrics list and call insertDiscovery with it\n+        List<IMetric> metrics = new ArrayList<IMetric>();\n+        long collectionTime = 0;\n+        Locator locator1 = Locator.createLocatorFromPathComponents(TENANT_1, METRIC_NAME_A1);\n+        Locator locator2 = Locator.createLocatorFromPathComponents(TENANT_2, METRIC_NAME_B1);\n+        TimeValue ttl = new TimeValue(1, TimeUnit.DAYS);\n+        metrics.add(new PreaggregatedMetric(collectionTime, locator1, ttl, rollupWithEnumValues));\n+        metrics.add(new PreaggregatedMetric(collectionTime, locator2, ttl, rollupWithEnumValues));\n+        enumElasticIO.insertDiscovery(metrics);\n+\n+        // verify client and bulk\n+        verify(esClientMock, times(1)).prepareBulk();\n+        verify(bulkRequestBuilderMock, times(2)).add(any(IndexRequestBuilder.class));\n+        verify(esClientMock, times(2)).prepareIndex(EnumElasticIO.ENUMS_INDEX_NAME_WRITE, EnumElasticIO.ENUMS_DOCUMENT_TYPE);\n+        verify(bulkRequestBuilderMock, times(1)).execute();\n+\n+        // verify indexRequestBuilder\n+        verify(indexRequestBuilderMock, times(2)).setId(anyString());\n+        verify(indexRequestBuilderMock).setId(TENANT_1 + \":\" + METRIC_NAME_A1);\n+        verify(indexRequestBuilderMock).setId(TENANT_2 + \":\" + METRIC_NAME_B1);\n+        verify(indexRequestBuilderMock, times(2)).setSource(any(XContentBuilder.class));\n+        verify(indexRequestBuilderMock, times(2)).setCreate(true);\n+        verify(indexRequestBuilderMock, times(2)).setRouting(anyString());\n+        verify(indexRequestBuilderMock).setRouting(TENANT_1);\n+        verify(indexRequestBuilderMock).setRouting(TENANT_2);\n+    }\n+","path":"blueflood-elasticsearch/src/test/java/com/rackspacecloud/blueflood/io/EnumElasticIOTest.java","position":193,"original_position":193,"commit_id":"3d6d289712cfcfb84187a5a069632aad08ba8300","original_commit_id":"3d6d289712cfcfb84187a5a069632aad08ba8300","user":{"login":"VinnyQ","id":203223,"avatar_url":"https://avatars.githubusercontent.com/u/203223?v=3","gravatar_id":"","url":"https://api.github.com/users/VinnyQ","html_url":"https://github.com/VinnyQ","followers_url":"https://api.github.com/users/VinnyQ/followers","following_url":"https://api.github.com/users/VinnyQ/following{/other_user}","gists_url":"https://api.github.com/users/VinnyQ/gists{/gist_id}","starred_url":"https://api.github.com/users/VinnyQ/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VinnyQ/subscriptions","organizations_url":"https://api.github.com/users/VinnyQ/orgs","repos_url":"https://api.github.com/users/VinnyQ/repos","events_url":"https://api.github.com/users/VinnyQ/events{/privacy}","received_events_url":"https://api.github.com/users/VinnyQ/received_events","type":"User","site_admin":false},"body":"We might be.  If the tests started failing because of implementation changes and becoming tedious to maintain, we can just remove these routing and  create call and just assert the locator field.  Or do you want me to remove it now?","created_at":"2015-09-21T22:05:16Z","updated_at":"2015-09-21T22:05:16Z","html_url":"https://github.com/rackerlabs/blueflood/pull/521#discussion_r40032588","pull_request_url":"https://api.github.com/repos/rackerlabs/blueflood/pulls/521","_links":{"self":{"href":"https://api.github.com/repos/rackerlabs/blueflood/pulls/comments/40032588"},"html":{"href":"https://github.com/rackerlabs/blueflood/pull/521#discussion_r40032588"},"pull_request":{"href":"https://api.github.com/repos/rackerlabs/blueflood/pulls/521"}}},"pull_request":{"url":"https://api.github.com/repos/rackerlabs/blueflood/pulls/521","id":45234061,"html_url":"https://github.com/rackerlabs/blueflood/pull/521","diff_url":"https://github.com/rackerlabs/blueflood/pull/521.diff","patch_url":"https://github.com/rackerlabs/blueflood/pull/521.patch","issue_url":"https://api.github.com/repos/rackerlabs/blueflood/issues/521","number":521,"state":"open","locked":false,"title":"support enum values in ElasticSearch","user":{"login":"VinnyQ","id":203223,"avatar_url":"https://avatars.githubusercontent.com/u/203223?v=3","gravatar_id":"","url":"https://api.github.com/users/VinnyQ","html_url":"https://github.com/VinnyQ","followers_url":"https://api.github.com/users/VinnyQ/followers","following_url":"https://api.github.com/users/VinnyQ/following{/other_user}","gists_url":"https://api.github.com/users/VinnyQ/gists{/gist_id}","starred_url":"https://api.github.com/users/VinnyQ/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VinnyQ/subscriptions","organizations_url":"https://api.github.com/users/VinnyQ/orgs","repos_url":"https://api.github.com/users/VinnyQ/repos","events_url":"https://api.github.com/users/VinnyQ/events{/privacy}","received_events_url":"https://api.github.com/users/VinnyQ/received_events","type":"User","site_admin":false},"body":"WHAT:  Add search capability for blueflood so that users can pass in the param \"include_enum_values\" and be able to retrieve enum values along with the metric names in the result when hitting the /v2.0/:tenantId/metrics/search endpoint.\r\n(see story:  https://jira.rax.io/browse/CMD-741;  Note -- I do not think we should implement the enum version of the DiscoveryWriter class in this story, but should move the writing of that class to the rollup story where the new index will actually be created during rollup).\r\n\r\nHOW:\r\n- extract ElasticIO.Discovery inner class to standalone Discovery class\r\n- extract ElasticIO.ESFieldLabel enum to standalone enum class\r\n- add configs for enums elasticsearch module\r\n- add EnumElasticIO class with insertDiscovery() and search() methods.\r\n- modify SearchResult to store enum values field\r\n- modify HttpMetricsIndexHandler to check for include_enum_values\r\n- modify HttpMetricsIndexHandler to include enum values in json result\r\n\r\nPlease refer to the new \"enums\" index mapping for the index and its fields to be created by metrics rollup of enum values:  https://github.com/VinnyQ/blueflood-chef/blob/add_elasticsearch_mappings_for_enums/site-cookbooks/old-elasticsearch/files/default/enums.json\r\n\r\nNOTE:  This deploy will need changes to blueflood.conf (after the code is merged)\r\nTo add the following property:\r\n```\r\nENUMS_DISCOVERY_MODULES=com.rackspacecloud.blueflood.io.EnumElasticIO\r\n```\r\n(do this in https://github.com/rackerlabs/blueflood-chef).\r\n\r\nAnd also we will have to create another ElasticSearch alias \"metric_metadata_read\" that also points to the new \"enums\" index.  The code to do so is:\r\n\r\n```\r\ncurl -XPOST 'http://localhost:9200/_aliases' -d '\r\n{\r\n    \"actions\" : [\r\n        { \"add\" : { \"index\" : \"enums\", \"alias\" : \"metric_metadata_read\" } }\r\n    ]\r\n}'\r\n```","created_at":"2015-09-16T22:52:11Z","updated_at":"2015-09-21T22:05:16Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2441fd6f2bf875dc231bc23e1bfbc8eb66cf9a62","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/rackerlabs/blueflood/pulls/521/commits","review_comments_url":"https://api.github.com/repos/rackerlabs/blueflood/pulls/521/comments","review_comment_url":"https://api.github.com/repos/rackerlabs/blueflood/pulls/comments{/number}","comments_url":"https://api.github.com/repos/rackerlabs/blueflood/issues/521/comments","statuses_url":"https://api.github.com/repos/rackerlabs/blueflood/statuses/3d6d289712cfcfb84187a5a069632aad08ba8300","head":{"label":"VinnyQ:elasticsearch_changes_for_enums","ref":"elasticsearch_changes_for_enums","sha":"3d6d289712cfcfb84187a5a069632aad08ba8300","user":{"login":"VinnyQ","id":203223,"avatar_url":"https://avatars.githubusercontent.com/u/203223?v=3","gravatar_id":"","url":"https://api.github.com/users/VinnyQ","html_url":"https://github.com/VinnyQ","followers_url":"https://api.github.com/users/VinnyQ/followers","following_url":"https://api.github.com/users/VinnyQ/following{/other_user}","gists_url":"https://api.github.com/users/VinnyQ/gists{/gist_id}","starred_url":"https://api.github.com/users/VinnyQ/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VinnyQ/subscriptions","organizations_url":"https://api.github.com/users/VinnyQ/orgs","repos_url":"https://api.github.com/users/VinnyQ/repos","events_url":"https://api.github.com/users/VinnyQ/events{/privacy}","received_events_url":"https://api.github.com/users/VinnyQ/received_events","type":"User","site_admin":false},"repo":{"id":39083546,"name":"blueflood","full_name":"VinnyQ/blueflood","owner":{"login":"VinnyQ","id":203223,"avatar_url":"https://avatars.githubusercontent.com/u/203223?v=3","gravatar_id":"","url":"https://api.github.com/users/VinnyQ","html_url":"https://github.com/VinnyQ","followers_url":"https://api.github.com/users/VinnyQ/followers","following_url":"https://api.github.com/users/VinnyQ/following{/other_user}","gists_url":"https://api.github.com/users/VinnyQ/gists{/gist_id}","starred_url":"https://api.github.com/users/VinnyQ/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VinnyQ/subscriptions","organizations_url":"https://api.github.com/users/VinnyQ/orgs","repos_url":"https://api.github.com/users/VinnyQ/repos","events_url":"https://api.github.com/users/VinnyQ/events{/privacy}","received_events_url":"https://api.github.com/users/VinnyQ/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/VinnyQ/blueflood","description":"A distributed system designed to ingest and process time series data","fork":true,"url":"https://api.github.com/repos/VinnyQ/blueflood","forks_url":"https://api.github.com/repos/VinnyQ/blueflood/forks","keys_url":"https://api.github.com/repos/VinnyQ/blueflood/keys{/key_id}","collaborators_url":"https://api.github.com/repos/VinnyQ/blueflood/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/VinnyQ/blueflood/teams","hooks_url":"https://api.github.com/repos/VinnyQ/blueflood/hooks","issue_events_url":"https://api.github.com/repos/VinnyQ/blueflood/issues/events{/number}","events_url":"https://api.github.com/repos/VinnyQ/blueflood/events","assignees_url":"https://api.github.com/repos/VinnyQ/blueflood/assignees{/user}","branches_url":"https://api.github.com/repos/VinnyQ/blueflood/branches{/branch}","tags_url":"https://api.github.com/repos/VinnyQ/blueflood/tags","blobs_url":"https://api.github.com/repos/VinnyQ/blueflood/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/VinnyQ/blueflood/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/VinnyQ/blueflood/git/refs{/sha}","trees_url":"https://api.github.com/repos/VinnyQ/blueflood/git/trees{/sha}","statuses_url":"https://api.github.com/repos/VinnyQ/blueflood/statuses/{sha}","languages_url":"https://api.github.com/repos/VinnyQ/blueflood/languages","stargazers_url":"https://api.github.com/repos/VinnyQ/blueflood/stargazers","contributors_url":"https://api.github.com/repos/VinnyQ/blueflood/contributors","subscribers_url":"https://api.github.com/repos/VinnyQ/blueflood/subscribers","subscription_url":"https://api.github.com/repos/VinnyQ/blueflood/subscription","commits_url":"https://api.github.com/repos/VinnyQ/blueflood/commits{/sha}","git_commits_url":"https://api.github.com/repos/VinnyQ/blueflood/git/commits{/sha}","comments_url":"https://api.github.com/repos/VinnyQ/blueflood/comments{/number}","issue_comment_url":"https://api.github.com/repos/VinnyQ/blueflood/issues/comments{/number}","contents_url":"https://api.github.com/repos/VinnyQ/blueflood/contents/{+path}","compare_url":"https://api.github.com/repos/VinnyQ/blueflood/compare/{base}...{head}","merges_url":"https://api.github.com/repos/VinnyQ/blueflood/merges","archive_url":"https://api.github.com/repos/VinnyQ/blueflood/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/VinnyQ/blueflood/downloads","issues_url":"https://api.github.com/repos/VinnyQ/blueflood/issues{/number}","pulls_url":"https://api.github.com/repos/VinnyQ/blueflood/pulls{/number}","milestones_url":"https://api.github.com/repos/VinnyQ/blueflood/milestones{/number}","notifications_url":"https://api.github.com/repos/VinnyQ/blueflood/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/VinnyQ/blueflood/labels{/name}","releases_url":"https://api.github.com/repos/VinnyQ/blueflood/releases{/id}","created_at":"2015-07-14T15:30:22Z","updated_at":"2015-07-14T15:30:23Z","pushed_at":"2015-09-18T22:07:08Z","git_url":"git://github.com/VinnyQ/blueflood.git","ssh_url":"git@github.com:VinnyQ/blueflood.git","clone_url":"https://github.com/VinnyQ/blueflood.git","svn_url":"https://github.com/VinnyQ/blueflood","homepage":"http://www.blueflood.io","size":3999,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"rackerlabs:enums-feature","ref":"enums-feature","sha":"8d57866f4c31bec0f538407a7c8ddbef339ada66","user":{"login":"rackerlabs","id":84293,"avatar_url":"https://avatars.githubusercontent.com/u/84293?v=3","gravatar_id":"","url":"https://api.github.com/users/rackerlabs","html_url":"https://github.com/rackerlabs","followers_url":"https://api.github.com/users/rackerlabs/followers","following_url":"https://api.github.com/users/rackerlabs/following{/other_user}","gists_url":"https://api.github.com/users/rackerlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/rackerlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rackerlabs/subscriptions","organizations_url":"https://api.github.com/users/rackerlabs/orgs","repos_url":"https://api.github.com/users/rackerlabs/repos","events_url":"https://api.github.com/users/rackerlabs/events{/privacy}","received_events_url":"https://api.github.com/users/rackerlabs/received_events","type":"Organization","site_admin":false},"repo":{"id":10081109,"name":"blueflood","full_name":"rackerlabs/blueflood","owner":{"login":"rackerlabs","id":84293,"avatar_url":"https://avatars.githubusercontent.com/u/84293?v=3","gravatar_id":"","url":"https://api.github.com/users/rackerlabs","html_url":"https://github.com/rackerlabs","followers_url":"https://api.github.com/users/rackerlabs/followers","following_url":"https://api.github.com/users/rackerlabs/following{/other_user}","gists_url":"https://api.github.com/users/rackerlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/rackerlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rackerlabs/subscriptions","organizations_url":"https://api.github.com/users/rackerlabs/orgs","repos_url":"https://api.github.com/users/rackerlabs/repos","events_url":"https://api.github.com/users/rackerlabs/events{/privacy}","received_events_url":"https://api.github.com/users/rackerlabs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rackerlabs/blueflood","description":"A distributed system designed to ingest and process time series data","fork":false,"url":"https://api.github.com/repos/rackerlabs/blueflood","forks_url":"https://api.github.com/repos/rackerlabs/blueflood/forks","keys_url":"https://api.github.com/repos/rackerlabs/blueflood/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rackerlabs/blueflood/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rackerlabs/blueflood/teams","hooks_url":"https://api.github.com/repos/rackerlabs/blueflood/hooks","issue_events_url":"https://api.github.com/repos/rackerlabs/blueflood/issues/events{/number}","events_url":"https://api.github.com/repos/rackerlabs/blueflood/events","assignees_url":"https://api.github.com/repos/rackerlabs/blueflood/assignees{/user}","branches_url":"https://api.github.com/repos/rackerlabs/blueflood/branches{/branch}","tags_url":"https://api.github.com/repos/rackerlabs/blueflood/tags","blobs_url":"https://api.github.com/repos/rackerlabs/blueflood/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rackerlabs/blueflood/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rackerlabs/blueflood/git/refs{/sha}","trees_url":"https://api.github.com/repos/rackerlabs/blueflood/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rackerlabs/blueflood/statuses/{sha}","languages_url":"https://api.github.com/repos/rackerlabs/blueflood/languages","stargazers_url":"https://api.github.com/repos/rackerlabs/blueflood/stargazers","contributors_url":"https://api.github.com/repos/rackerlabs/blueflood/contributors","subscribers_url":"https://api.github.com/repos/rackerlabs/blueflood/subscribers","subscription_url":"https://api.github.com/repos/rackerlabs/blueflood/subscription","commits_url":"https://api.github.com/repos/rackerlabs/blueflood/commits{/sha}","git_commits_url":"https://api.github.com/repos/rackerlabs/blueflood/git/commits{/sha}","comments_url":"https://api.github.com/repos/rackerlabs/blueflood/comments{/number}","issue_comment_url":"https://api.github.com/repos/rackerlabs/blueflood/issues/comments{/number}","contents_url":"https://api.github.com/repos/rackerlabs/blueflood/contents/{+path}","compare_url":"https://api.github.com/repos/rackerlabs/blueflood/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rackerlabs/blueflood/merges","archive_url":"https://api.github.com/repos/rackerlabs/blueflood/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rackerlabs/blueflood/downloads","issues_url":"https://api.github.com/repos/rackerlabs/blueflood/issues{/number}","pulls_url":"https://api.github.com/repos/rackerlabs/blueflood/pulls{/number}","milestones_url":"https://api.github.com/repos/rackerlabs/blueflood/milestones{/number}","notifications_url":"https://api.github.com/repos/rackerlabs/blueflood/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rackerlabs/blueflood/labels{/name}","releases_url":"https://api.github.com/repos/rackerlabs/blueflood/releases{/id}","created_at":"2013-05-15T14:50:39Z","updated_at":"2015-09-16T21:04:42Z","pushed_at":"2015-09-21T17:08:01Z","git_url":"git://github.com/rackerlabs/blueflood.git","ssh_url":"git@github.com:rackerlabs/blueflood.git","clone_url":"https://github.com/rackerlabs/blueflood.git","svn_url":"https://github.com/rackerlabs/blueflood","homepage":"http://www.blueflood.io","size":11578,"stargazers_count":364,"watchers_count":364,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":47,"mirror_url":null,"open_issues_count":29,"forks":47,"open_issues":29,"watchers":364,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rackerlabs/blueflood/pulls/521"},"html":{"href":"https://github.com/rackerlabs/blueflood/pull/521"},"issue":{"href":"https://api.github.com/repos/rackerlabs/blueflood/issues/521"},"comments":{"href":"https://api.github.com/repos/rackerlabs/blueflood/issues/521/comments"},"review_comments":{"href":"https://api.github.com/repos/rackerlabs/blueflood/pulls/521/comments"},"review_comment":{"href":"https://api.github.com/repos/rackerlabs/blueflood/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/rackerlabs/blueflood/pulls/521/commits"},"statuses":{"href":"https://api.github.com/repos/rackerlabs/blueflood/statuses/3d6d289712cfcfb84187a5a069632aad08ba8300"}}}}