{"action":"created","comment":{"url":"https://api.github.com/repos/nats-io/nats-streaming-server/pulls/comments/120606353","pull_request_review_id":42581511,"id":120606353,"diff_hunk":"@@ -0,0 +1,504 @@\n+// Copyright 2017 Apcera Inc. All rights reserved.\n+\n+package server\n+\n+import (\n+\t\"encoding/json\"\n+\t\"fmt\"\n+\t\"net/http\"\n+\t\"runtime\"\n+\t\"sort\"\n+\t\"strconv\"\n+\t\"time\"\n+\n+\tgnatsd \"github.com/nats-io/gnatsd/server\"\n+\t\"github.com/nats-io/nats-streaming-server/stores\"\n+)\n+\n+// Routes for the monitoring pages\n+const (\n+\tRootPath     = \"/nss\"\n+\tServerPath   = RootPath + \"/server\"\n+\tStorePath    = RootPath + \"/store\"\n+\tClientsPath  = RootPath + \"/clients\"\n+\tChannelsPath = RootPath + \"/channels\"\n+\n+\tdefaultMonitorListLimit = 1024\n+)\n+\n+// Serverz describes the NATS Streaming Server\n+type Serverz struct {\n+\tClusterID     string    `json:\"cluster_id\"`\n+\tServerID      string    `json:\"server_id\"`\n+\tVersion       string    `json:\"version\"`\n+\tGoVersion     string    `json:\"go\"`\n+\tState         string    `json:\"state\"`\n+\tNow           time.Time `json:\"now\"`\n+\tStart         time.Time `json:\"start_time\"`\n+\tUptime        string    `json:\"uptime\"`\n+\tClients       int       `json:\"clients\"`\n+\tSubscriptions int       `json:\"subscriptions\"`\n+\tChannels      int       `json:\"channels\"`\n+\tTotalMsgs     int       `json:\"total_msgs\"`\n+\tTotalBytes    uint64    `json:\"total_bytes\"`\n+}\n+\n+// Storez describes the NATS Streaming Store\n+type Storez struct {\n+\tClusterID  string             `json:\"cluster_id\"`\n+\tServerID   string             `json:\"server_id\"`\n+\tNow        time.Time          `json:\"now\"`\n+\tType       string             `json:\"type\"`\n+\tLimits     stores.StoreLimits `json:\"limits\"`\n+\tTotalMsgs  int                `json:\"total_msgs\"`\n+\tTotalBytes uint64             `json:\"total_bytes\"`\n+}\n+\n+// Clientsz lists the client connections\n+type Clientsz struct {\n+\tClusterID string     `json:\"cluster_id\"`\n+\tServerID  string     `json:\"server_id\"`\n+\tNow       time.Time  `json:\"now\"`\n+\tOffset    int        `json:\"offset\"`\n+\tLimit     int        `json:\"limit\"`\n+\tCount     int        `json:\"count\"`\n+\tTotal     int        `json:\"total\"`\n+\tClients   []*Clientz `json:\"clients\"`\n+}\n+\n+// Clientz describes a NATS Streaming Client connection\n+type Clientz struct {\n+\tID            string                      `json:\"id\"`\n+\tHBInbox       string                      `json:\"hb_inbox\"`\n+\tSubscriptions map[string][]*Subscriptionz `json:\"subscriptions,omitempty\"`\n+}\n+\n+// Channelsz lists the name of all NATS Streaming Channelsz\n+type Channelsz struct {\n+\tClusterID string    `json:\"cluster_id\"`\n+\tServerID  string    `json:\"server_id\"`\n+\tNow       time.Time `json:\"now\"`\n+\tOffset    int       `json:\"offset\"`\n+\tLimit     int       `json:\"limit\"`\n+\tCount     int       `json:\"count\"`\n+\tTotal     int       `json:\"total\"`\n+\tChannels  []string  `json:\"channels\"`\n+}\n+\n+// ChannelsWithSubsz list detailed channels along with subscriptions on each channel\n+type ChannelsWithSubsz struct {\n+\tClusterID string      `json:\"cluster_id\"`\n+\tServerID  string      `json:\"server_id\"`\n+\tNow       time.Time   `json:\"now\"`\n+\tOffset    int         `json:\"offset\"`\n+\tLimit     int         `json:\"limit\"`\n+\tCount     int         `json:\"count\"`\n+\tTotal     int         `json:\"total\"`\n+\tChannels  []*Channelz `json:\"channels\"`\n+}\n+\n+// Channelz describes a NATS Streaming Channel\n+type Channelz struct {\n+\tName          string           `json:\"name\"`\n+\tMsgs          int              `json:\"msgs\"`\n+\tBytes         uint64           `json:\"bytes\"`\n+\tFirstSeq      uint64           `json:\"first_seq\"`\n+\tLastSeq       uint64           `json:\"last_seq\"`\n+\tSubscriptions []*Subscriptionz `json:\"subscriptions,omitempty\"`\n+}\n+\n+// Subscriptionz describes a NATS Streaming Subscription\n+type Subscriptionz struct {\n+\tInbox        string `json:\"inbox\"`\n+\tAckInbox     string `json:\"ack_inbox\"`\n+\tDurableName  string `json:\"durable_name,omitempty\"`\n+\tQueueName    string `json:\"queue_name,omitempty\"`\n+\tIsDurable    bool   `json:\"is_durable\"`\n+\tMaxInflight  int    `json:\"max_inflight\"`\n+\tAckWait      int    `json:\"ack_wait\"`\n+\tLastSent     uint64 `json:\"last_sent\"`\n+\tPendingCount int    `json:\"pending_count\"`\n+\tIsStalled    bool   `json:\"is_stalled\"`\n+}\n+\n+func (s *StanServer) startMonitoring(nOpts *gnatsd.Options) error {\n+\tvar hh http.Handler\n+\t// If we are connecting to remote NATS Server, we start our own\n+\t// HTTP(s) server.\n+\tif s.opts.NATSServerURL != \"\" {\n+\t\ts.natsServer = gnatsd.New(nOpts)\n+\t\tif err := s.natsServer.StartMonitoring(); err != nil {\n+\t\t\treturn err\n+\t\t}\n+\t\thh = s.natsServer.HTTPHandler()\n+\t} else {\n+\t\t// We may need to wait for the HTTPHandler to be ready.\n+\t\ttimeout := time.Now().Add(10 * time.Second)\n+\t\tfor time.Now().Before(timeout) {\n+\t\t\tif hh = s.natsServer.HTTPHandler(); hh != nil {\n+\t\t\t\tbreak\n+\t\t\t}\n+\t\t\ttime.Sleep(250 * time.Millisecond)\n+\t\t}\n+\t}\n+\tif hh == nil {\n+\t\treturn fmt.Errorf(\"unable to start monitoring server\")\n+\t}\n+\n+\tmux := hh.(*http.ServeMux)\n+\tmux.HandleFunc(RootPath, s.handleRootz)\n+\tmux.HandleFunc(ServerPath, s.handleServerz)\n+\tmux.HandleFunc(StorePath, s.handleStorez)\n+\tmux.HandleFunc(ClientsPath, s.handleClientsz)\n+\tmux.HandleFunc(ChannelsPath, s.handleChannelsz)\n+\n+\treturn nil\n+}\n+\n+func (s *StanServer) handleRootz(w http.ResponseWriter, r *http.Request) {\n+\tfmt.Fprintf(w, `<html lang=\"en\">\n+   <head>\n+    <link rel=\"shortcut icon\" href=\"http://nats.io/img/favicon.ico\">\n+    <style type=\"text/css\">\n+      body { font-family: \"Century Gothic\", CenturyGothic, AppleGothic, sans-serif; font-size: 22; }\n+      a { margin-left: 32px; }\n+    </style>\n+  </head>\n+  <body>\n+    <img src=\"http://nats.io/img/logo.png\" alt=\"NATS Streaming\">\n+    <br/>\n+\t<a href=%s>server</a><br/>\n+\t<a href=%s>store</a><br/>\n+\t<a href=%s>clients</a><br/>\n+\t<a href=%s>channels</a><br/>\n+    <br/>\n+    <a href=http://nats.io/documentation/server/gnatsd-monitoring/>help</a>\n+  </body>\n+</html>`, ServerPath, StorePath, ClientsPath, ChannelsPath)\n+}\n+\n+func (s *StanServer) handleServerz(w http.ResponseWriter, r *http.Request) {\n+\tnumChannels := s.store.GetChannelsCount()\n+\tcount, bytes, _ := s.store.MsgsState(stores.AllChannels)\n+\ts.mu.RLock()\n+\tstate := s.state\n+\ts.mu.RUnlock()\n+\ts.monMu.RLock()\n+\tnumSubs := s.numSubs\n+\ts.monMu.RUnlock()\n+\tnow := time.Now()\n+\tserverz := &Serverz{\n+\t\tClusterID:     s.info.ClusterID,\n+\t\tServerID:      s.serverID,\n+\t\tVersion:       VERSION,\n+\t\tGoVersion:     runtime.Version(),\n+\t\tState:         state.String(),\n+\t\tNow:           now,\n+\t\tStart:         s.startTime,\n+\t\tUptime:        myUptime(now.Sub(s.startTime)),\n+\t\tClients:       s.store.GetClientsCount(),\n+\t\tChannels:      numChannels,\n+\t\tSubscriptions: numSubs,\n+\t\tTotalMsgs:     count,\n+\t\tTotalBytes:    bytes,\n+\t}\n+\tsendResponse(w, r, serverz)\n+}\n+\n+func myUptime(d time.Duration) string {\n+\t// Just use total seconds for uptime, and display days / years\n+\ttsecs := d / time.Second\n+\ttmins := tsecs / 60\n+\tthrs := tmins / 60\n+\ttdays := thrs / 24\n+\ttyrs := tdays / 365\n+\n+\tif tyrs > 0 {\n+\t\treturn fmt.Sprintf(\"%dy%dd%dh%dm%ds\", tyrs, tdays%365, thrs%24, tmins%60, tsecs%60)\n+\t}\n+\tif tdays > 0 {\n+\t\treturn fmt.Sprintf(\"%dd%dh%dm%ds\", tdays, thrs%24, tmins%60, tsecs%60)\n+\t}\n+\tif thrs > 0 {\n+\t\treturn fmt.Sprintf(\"%dh%dm%ds\", thrs, tmins%60, tsecs%60)\n+\t}\n+\tif tmins > 0 {\n+\t\treturn fmt.Sprintf(\"%dm%ds\", tmins, tsecs%60)\n+\t}\n+\treturn fmt.Sprintf(\"%ds\", tsecs)\n+}\n+\n+func (s *StanServer) handleStorez(w http.ResponseWriter, r *http.Request) {\n+\tcount, bytes, _ := s.store.MsgsState(stores.AllChannels)\n+\tstorez := &Storez{\n+\t\tClusterID:  s.info.ClusterID,\n+\t\tServerID:   s.serverID,\n+\t\tNow:        time.Now(),\n+\t\tType:       s.store.Name(),\n+\t\tLimits:     *s.storeLimits,\n+\t\tTotalMsgs:  count,\n+\t\tTotalBytes: bytes,\n+\t}\n+\tsendResponse(w, r, storez)\n+}\n+\n+type byClientID []*Clientz\n+\n+func (c byClientID) Len() int           { return len(c) }\n+func (c byClientID) Swap(i, j int)      { c[i], c[j] = c[j], c[i] }\n+func (c byClientID) Less(i, j int) bool { return c[i].ID < c[j].ID }\n+\n+func (s *StanServer) handleClientsz(w http.ResponseWriter, r *http.Request) {\n+\tsingleClient := r.URL.Query().Get(\"client\")\n+\tsubsOption, _ := strconv.Atoi(r.URL.Query().Get(\"subs\"))\n+\tif singleClient != \"\" {\n+\t\tvar clientz *Clientz\n+\t\tclient := s.store.GetClient(singleClient)\n+\t\tif client != nil {\n+\t\t\tclientz = getMonitorClient(client, subsOption)\n+\t\t}\n+\t\tif clientz == nil {\n+\t\t\tw.WriteHeader(http.StatusNotFound)\n+\t\t\tw.Write([]byte(fmt.Sprintf(\"Client %s not found\", singleClient)))\n+\t\t\treturn\n+\t\t}\n+\t\tsendResponse(w, r, clientz)\n+\t} else {\n+\t\toffset, _ := strconv.Atoi(r.URL.Query().Get(\"offset\"))\n+\t\tif offset < 0 {\n+\t\t\toffset = 0\n+\t\t}\n+\t\tlimit, _ := strconv.Atoi(r.URL.Query().Get(\"limit\"))\n+\t\tif limit <= 0 {\n+\t\t\tlimit = defaultMonitorListLimit\n+\t\t}\n+\t\tclients := s.store.GetClients()\n+\t\ttotalClients := len(clients)\n+\t\tcarr := make([]*Clientz, 0, totalClients)\n+\t\tfor _, c := range clients {\n+\t\t\tcz := &Clientz{ID: c.ID}\n+\t\t\tcarr = append(carr, cz)\n+\t\t}\n+\t\tsort.Sort(byClientID(carr))\n+\n+\t\tminoff := offset\n+\t\tif minoff > totalClients {\n+\t\t\tminoff = totalClients\n+\t\t}\n+\t\tmaxoff := offset + limit\n+\t\tif maxoff > totalClients {\n+\t\t\tmaxoff = totalClients\n+\t\t}\n+\t\tcarr = carr[minoff:maxoff]","path":"server/monitor.go","position":292,"original_position":292,"commit_id":"95e103160f36547cd96dc997220979790c6eab8f","original_commit_id":"95e103160f36547cd96dc997220979790c6eab8f","user":{"login":"kozlovic","id":13736691,"avatar_url":"https://avatars0.githubusercontent.com/u/13736691?v=3","gravatar_id":"","url":"https://api.github.com/users/kozlovic","html_url":"https://github.com/kozlovic","followers_url":"https://api.github.com/users/kozlovic/followers","following_url":"https://api.github.com/users/kozlovic/following{/other_user}","gists_url":"https://api.github.com/users/kozlovic/gists{/gist_id}","starred_url":"https://api.github.com/users/kozlovic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kozlovic/subscriptions","organizations_url":"https://api.github.com/users/kozlovic/orgs","repos_url":"https://api.github.com/users/kozlovic/repos","events_url":"https://api.github.com/users/kozlovic/events{/privacy}","received_events_url":"https://api.github.com/users/kozlovic/received_events","type":"User","site_admin":false},"body":"But at the end, since both store implementations maintain channels (same for clients) as a map, in order to return a subset, we would still need to create an array with all channels in order to sort and then apply the offset/limit and return a subset of this array.\r\nEven with adding an internal number on a channel structure, we would need to store the channels in two maps, one per name, one per number and that could be used as the offset key. Problem is for clients (that can be removed) and will be for channels when we add the ability to remove them.\r\nFor channels, after a server restart, the numbering would not be the same since recovery will not guarantee the same ordering than when channels were first created. So it means that getting offset/limit between server restart would return inconsistent value. With current ordering based on name, it will still be ok.\r\nWhat do you think?","created_at":"2017-06-07T12:03:58Z","updated_at":"2017-06-07T12:03:58Z","html_url":"https://github.com/nats-io/nats-streaming-server/pull/317#discussion_r120606353","pull_request_url":"https://api.github.com/repos/nats-io/nats-streaming-server/pulls/317","_links":{"self":{"href":"https://api.github.com/repos/nats-io/nats-streaming-server/pulls/comments/120606353"},"html":{"href":"https://github.com/nats-io/nats-streaming-server/pull/317#discussion_r120606353"},"pull_request":{"href":"https://api.github.com/repos/nats-io/nats-streaming-server/pulls/317"}}},"pull_request":{"url":"https://api.github.com/repos/nats-io/nats-streaming-server/pulls/317","id":123182204,"html_url":"https://github.com/nats-io/nats-streaming-server/pull/317","diff_url":"https://github.com/nats-io/nats-streaming-server/pull/317.diff","patch_url":"https://github.com/nats-io/nats-streaming-server/pull/317.patch","issue_url":"https://api.github.com/repos/nats-io/nats-streaming-server/issues/317","number":317,"state":"open","locked":false,"title":"[ADDED] Monitoring","user":{"login":"kozlovic","id":13736691,"avatar_url":"https://avatars0.githubusercontent.com/u/13736691?v=3","gravatar_id":"","url":"https://api.github.com/users/kozlovic","html_url":"https://github.com/kozlovic","followers_url":"https://api.github.com/users/kozlovic/followers","following_url":"https://api.github.com/users/kozlovic/following{/other_user}","gists_url":"https://api.github.com/users/kozlovic/gists{/gist_id}","starred_url":"https://api.github.com/users/kozlovic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kozlovic/subscriptions","organizations_url":"https://api.github.com/users/kozlovic/orgs","repos_url":"https://api.github.com/users/kozlovic/repos","events_url":"https://api.github.com/users/kozlovic/events{/privacy}","received_events_url":"https://api.github.com/users/kozlovic/received_events","type":"User","site_admin":false},"body":"Added some endpoints for monitoring:\r\n- server/\r\n- store/\r\n- clients/\r\n- channels/\r\n\r\nResolves #116","created_at":"2017-05-31T02:39:50Z","updated_at":"2017-06-07T12:03:58Z","closed_at":null,"merged_at":null,"merge_commit_sha":"59ffd4b836cf15ed00c084da3556171ace1896c6","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/nats-io/nats-streaming-server/pulls/317/commits","review_comments_url":"https://api.github.com/repos/nats-io/nats-streaming-server/pulls/317/comments","review_comment_url":"https://api.github.com/repos/nats-io/nats-streaming-server/pulls/comments{/number}","comments_url":"https://api.github.com/repos/nats-io/nats-streaming-server/issues/317/comments","statuses_url":"https://api.github.com/repos/nats-io/nats-streaming-server/statuses/95e103160f36547cd96dc997220979790c6eab8f","head":{"label":"nats-io:monitoring","ref":"monitoring","sha":"95e103160f36547cd96dc997220979790c6eab8f","user":{"login":"nats-io","id":10203055,"avatar_url":"https://avatars1.githubusercontent.com/u/10203055?v=3","gravatar_id":"","url":"https://api.github.com/users/nats-io","html_url":"https://github.com/nats-io","followers_url":"https://api.github.com/users/nats-io/followers","following_url":"https://api.github.com/users/nats-io/following{/other_user}","gists_url":"https://api.github.com/users/nats-io/gists{/gist_id}","starred_url":"https://api.github.com/users/nats-io/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nats-io/subscriptions","organizations_url":"https://api.github.com/users/nats-io/orgs","repos_url":"https://api.github.com/users/nats-io/repos","events_url":"https://api.github.com/users/nats-io/events{/privacy}","received_events_url":"https://api.github.com/users/nats-io/received_events","type":"Organization","site_admin":false},"repo":{"id":54661965,"name":"nats-streaming-server","full_name":"nats-io/nats-streaming-server","owner":{"login":"nats-io","id":10203055,"avatar_url":"https://avatars1.githubusercontent.com/u/10203055?v=3","gravatar_id":"","url":"https://api.github.com/users/nats-io","html_url":"https://github.com/nats-io","followers_url":"https://api.github.com/users/nats-io/followers","following_url":"https://api.github.com/users/nats-io/following{/other_user}","gists_url":"https://api.github.com/users/nats-io/gists{/gist_id}","starred_url":"https://api.github.com/users/nats-io/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nats-io/subscriptions","organizations_url":"https://api.github.com/users/nats-io/orgs","repos_url":"https://api.github.com/users/nats-io/repos","events_url":"https://api.github.com/users/nats-io/events{/privacy}","received_events_url":"https://api.github.com/users/nats-io/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/nats-io/nats-streaming-server","description":"NATS Streaming System Server","fork":false,"url":"https://api.github.com/repos/nats-io/nats-streaming-server","forks_url":"https://api.github.com/repos/nats-io/nats-streaming-server/forks","keys_url":"https://api.github.com/repos/nats-io/nats-streaming-server/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nats-io/nats-streaming-server/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nats-io/nats-streaming-server/teams","hooks_url":"https://api.github.com/repos/nats-io/nats-streaming-server/hooks","issue_events_url":"https://api.github.com/repos/nats-io/nats-streaming-server/issues/events{/number}","events_url":"https://api.github.com/repos/nats-io/nats-streaming-server/events","assignees_url":"https://api.github.com/repos/nats-io/nats-streaming-server/assignees{/user}","branches_url":"https://api.github.com/repos/nats-io/nats-streaming-server/branches{/branch}","tags_url":"https://api.github.com/repos/nats-io/nats-streaming-server/tags","blobs_url":"https://api.github.com/repos/nats-io/nats-streaming-server/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nats-io/nats-streaming-server/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nats-io/nats-streaming-server/git/refs{/sha}","trees_url":"https://api.github.com/repos/nats-io/nats-streaming-server/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nats-io/nats-streaming-server/statuses/{sha}","languages_url":"https://api.github.com/repos/nats-io/nats-streaming-server/languages","stargazers_url":"https://api.github.com/repos/nats-io/nats-streaming-server/stargazers","contributors_url":"https://api.github.com/repos/nats-io/nats-streaming-server/contributors","subscribers_url":"https://api.github.com/repos/nats-io/nats-streaming-server/subscribers","subscription_url":"https://api.github.com/repos/nats-io/nats-streaming-server/subscription","commits_url":"https://api.github.com/repos/nats-io/nats-streaming-server/commits{/sha}","git_commits_url":"https://api.github.com/repos/nats-io/nats-streaming-server/git/commits{/sha}","comments_url":"https://api.github.com/repos/nats-io/nats-streaming-server/comments{/number}","issue_comment_url":"https://api.github.com/repos/nats-io/nats-streaming-server/issues/comments{/number}","contents_url":"https://api.github.com/repos/nats-io/nats-streaming-server/contents/{+path}","compare_url":"https://api.github.com/repos/nats-io/nats-streaming-server/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nats-io/nats-streaming-server/merges","archive_url":"https://api.github.com/repos/nats-io/nats-streaming-server/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nats-io/nats-streaming-server/downloads","issues_url":"https://api.github.com/repos/nats-io/nats-streaming-server/issues{/number}","pulls_url":"https://api.github.com/repos/nats-io/nats-streaming-server/pulls{/number}","milestones_url":"https://api.github.com/repos/nats-io/nats-streaming-server/milestones{/number}","notifications_url":"https://api.github.com/repos/nats-io/nats-streaming-server/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nats-io/nats-streaming-server/labels{/name}","releases_url":"https://api.github.com/repos/nats-io/nats-streaming-server/releases{/id}","deployments_url":"https://api.github.com/repos/nats-io/nats-streaming-server/deployments","created_at":"2016-03-24T17:42:39Z","updated_at":"2017-06-07T01:29:56Z","pushed_at":"2017-06-06T10:30:43Z","git_url":"git://github.com/nats-io/nats-streaming-server.git","ssh_url":"git@github.com:nats-io/nats-streaming-server.git","clone_url":"https://github.com/nats-io/nats-streaming-server.git","svn_url":"https://github.com/nats-io/nats-streaming-server","homepage":"https://nats.io","size":1823,"stargazers_count":475,"watchers_count":475,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":48,"mirror_url":null,"open_issues_count":9,"forks":48,"open_issues":9,"watchers":475,"default_branch":"master"}},"base":{"label":"nats-io:master","ref":"master","sha":"b46db9dc898e6cd243ba78d47729dae1268b81a8","user":{"login":"nats-io","id":10203055,"avatar_url":"https://avatars1.githubusercontent.com/u/10203055?v=3","gravatar_id":"","url":"https://api.github.com/users/nats-io","html_url":"https://github.com/nats-io","followers_url":"https://api.github.com/users/nats-io/followers","following_url":"https://api.github.com/users/nats-io/following{/other_user}","gists_url":"https://api.github.com/users/nats-io/gists{/gist_id}","starred_url":"https://api.github.com/users/nats-io/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nats-io/subscriptions","organizations_url":"https://api.github.com/users/nats-io/orgs","repos_url":"https://api.github.com/users/nats-io/repos","events_url":"https://api.github.com/users/nats-io/events{/privacy}","received_events_url":"https://api.github.com/users/nats-io/received_events","type":"Organization","site_admin":false},"repo":{"id":54661965,"name":"nats-streaming-server","full_name":"nats-io/nats-streaming-server","owner":{"login":"nats-io","id":10203055,"avatar_url":"https://avatars1.githubusercontent.com/u/10203055?v=3","gravatar_id":"","url":"https://api.github.com/users/nats-io","html_url":"https://github.com/nats-io","followers_url":"https://api.github.com/users/nats-io/followers","following_url":"https://api.github.com/users/nats-io/following{/other_user}","gists_url":"https://api.github.com/users/nats-io/gists{/gist_id}","starred_url":"https://api.github.com/users/nats-io/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nats-io/subscriptions","organizations_url":"https://api.github.com/users/nats-io/orgs","repos_url":"https://api.github.com/users/nats-io/repos","events_url":"https://api.github.com/users/nats-io/events{/privacy}","received_events_url":"https://api.github.com/users/nats-io/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/nats-io/nats-streaming-server","description":"NATS Streaming System Server","fork":false,"url":"https://api.github.com/repos/nats-io/nats-streaming-server","forks_url":"https://api.github.com/repos/nats-io/nats-streaming-server/forks","keys_url":"https://api.github.com/repos/nats-io/nats-streaming-server/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nats-io/nats-streaming-server/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nats-io/nats-streaming-server/teams","hooks_url":"https://api.github.com/repos/nats-io/nats-streaming-server/hooks","issue_events_url":"https://api.github.com/repos/nats-io/nats-streaming-server/issues/events{/number}","events_url":"https://api.github.com/repos/nats-io/nats-streaming-server/events","assignees_url":"https://api.github.com/repos/nats-io/nats-streaming-server/assignees{/user}","branches_url":"https://api.github.com/repos/nats-io/nats-streaming-server/branches{/branch}","tags_url":"https://api.github.com/repos/nats-io/nats-streaming-server/tags","blobs_url":"https://api.github.com/repos/nats-io/nats-streaming-server/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nats-io/nats-streaming-server/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nats-io/nats-streaming-server/git/refs{/sha}","trees_url":"https://api.github.com/repos/nats-io/nats-streaming-server/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nats-io/nats-streaming-server/statuses/{sha}","languages_url":"https://api.github.com/repos/nats-io/nats-streaming-server/languages","stargazers_url":"https://api.github.com/repos/nats-io/nats-streaming-server/stargazers","contributors_url":"https://api.github.com/repos/nats-io/nats-streaming-server/contributors","subscribers_url":"https://api.github.com/repos/nats-io/nats-streaming-server/subscribers","subscription_url":"https://api.github.com/repos/nats-io/nats-streaming-server/subscription","commits_url":"https://api.github.com/repos/nats-io/nats-streaming-server/commits{/sha}","git_commits_url":"https://api.github.com/repos/nats-io/nats-streaming-server/git/commits{/sha}","comments_url":"https://api.github.com/repos/nats-io/nats-streaming-server/comments{/number}","issue_comment_url":"https://api.github.com/repos/nats-io/nats-streaming-server/issues/comments{/number}","contents_url":"https://api.github.com/repos/nats-io/nats-streaming-server/contents/{+path}","compare_url":"https://api.github.com/repos/nats-io/nats-streaming-server/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nats-io/nats-streaming-server/merges","archive_url":"https://api.github.com/repos/nats-io/nats-streaming-server/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nats-io/nats-streaming-server/downloads","issues_url":"https://api.github.com/repos/nats-io/nats-streaming-server/issues{/number}","pulls_url":"https://api.github.com/repos/nats-io/nats-streaming-server/pulls{/number}","milestones_url":"https://api.github.com/repos/nats-io/nats-streaming-server/milestones{/number}","notifications_url":"https://api.github.com/repos/nats-io/nats-streaming-server/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nats-io/nats-streaming-server/labels{/name}","releases_url":"https://api.github.com/repos/nats-io/nats-streaming-server/releases{/id}","deployments_url":"https://api.github.com/repos/nats-io/nats-streaming-server/deployments","created_at":"2016-03-24T17:42:39Z","updated_at":"2017-06-07T01:29:56Z","pushed_at":"2017-06-06T10:30:43Z","git_url":"git://github.com/nats-io/nats-streaming-server.git","ssh_url":"git@github.com:nats-io/nats-streaming-server.git","clone_url":"https://github.com/nats-io/nats-streaming-server.git","svn_url":"https://github.com/nats-io/nats-streaming-server","homepage":"https://nats.io","size":1823,"stargazers_count":475,"watchers_count":475,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":48,"mirror_url":null,"open_issues_count":9,"forks":48,"open_issues":9,"watchers":475,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/nats-io/nats-streaming-server/pulls/317"},"html":{"href":"https://github.com/nats-io/nats-streaming-server/pull/317"},"issue":{"href":"https://api.github.com/repos/nats-io/nats-streaming-server/issues/317"},"comments":{"href":"https://api.github.com/repos/nats-io/nats-streaming-server/issues/317/comments"},"review_comments":{"href":"https://api.github.com/repos/nats-io/nats-streaming-server/pulls/317/comments"},"review_comment":{"href":"https://api.github.com/repos/nats-io/nats-streaming-server/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/nats-io/nats-streaming-server/pulls/317/commits"},"statuses":{"href":"https://api.github.com/repos/nats-io/nats-streaming-server/statuses/95e103160f36547cd96dc997220979790c6eab8f"}}}}
{"actor":{"display_login":"kozlovic"}}