{"action":"created","comment":{"url":"https://api.github.com/repos/DataDog/datadog-trace-agent/pulls/comments/193396832","pull_request_review_id":126358399,"id":193396832,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDE5MzM5NjgzMg==","diff_hunk":"@@ -14,151 +14,294 @@ import (\n \twriterconfig \"github.com/DataDog/datadog-trace-agent/writer/config\"\n )\n \n-// StatsWriter ingests stats buckets and flushes their aggregation to the API.\n+// StatsWriter ingests stats buckets and flushes them to the API.\n type StatsWriter struct {\n-\tstats    info.StatsWriterInfo\n+\tBaseWriter\n+\n+\t// InStats is the stream of stat buckets to send out.\n+\tInStats <-chan []model.StatsBucket\n+\n+\t// info holds some stats about the writer itself, to keep an\n+\t// eye on things.\n+\tinfo info.StatsWriterInfo\n+\n+\t// hostName is the resolved host name on which the agent is\n+\t// running, to be sent as part of a stats payload.\n \thostName string\n-\tenv      string\n-\tconf     writerconfig.StatsWriterConfig\n-\tInStats  <-chan []model.StatsBucket\n+\t// env is environment this agent is configured with, to be\n+\t// sent as part of the stats payload.\n+\tenv string\n \n-\tBaseWriter\n+\tconf writerconfig.StatsWriterConfig\n }\n \n-// NewStatsWriter returns a new writer for services.\n+// NewStatsWriter returns a new writer for stats.\n func NewStatsWriter(conf *config.AgentConfig, InStats <-chan []model.StatsBucket) *StatsWriter {\n \twriterConf := conf.StatsWriterConfig\n \tlog.Infof(\"Stats writer initializing with config: %+v\", writerConf)\n \n \treturn &StatsWriter{\n-\t\thostName: conf.HostName,\n-\t\tenv:      conf.DefaultEnv,\n-\t\tconf:     writerConf,\n-\t\tInStats:  InStats,\n \t\tBaseWriter: *NewBaseWriter(conf, \"/api/v0.2/stats\", func(endpoint Endpoint) PayloadSender {\n \t\t\treturn NewCustomQueuablePayloadSender(endpoint, writerConf.SenderConfig)\n \t\t}),\n+\n+\t\tInStats: InStats,\n+\n+\t\thostName: conf.HostName,\n+\t\tenv:      conf.DefaultEnv,\n+\n+\t\tconf: writerConf,\n \t}\n }\n \n-// Start starts the writer.\n+// Start starts the different goroutines of the writer, including the\n+// main goroutine, reading stat buckets and flushing them.\n func (w *StatsWriter) Start() {\n \tw.BaseWriter.Start()\n+\n+\t// main goroutine\n \tgo func() {\n \t\tdefer watchdog.LogOnPanic()\n \t\tw.Run()\n \t}()\n+\n+\t// monitoring goroutine\n+\tgo func() {\n+\t\tdefer watchdog.LogOnPanic()\n+\t\tw.monitor()\n+\t}()\n }\n \n-// Run runs the main loop of the writer goroutine. If flushes\n-// stats buckets once received from the concentrator.\n+// Run runs the event loop of the writer' main goroutine. It reads\n+// stat buckets from InStats, builds stat payloads and sends them out\n+// using the base writer's payloadSender.\n func (w *StatsWriter) Run() {\n \tw.exitWG.Add(1)\n \tdefer w.exitWG.Done()\n \n \tlog.Debug(\"starting stats writer\")\n \n-\tupdateInfoTicker := time.NewTicker(w.conf.UpdateInfoPeriod)\n-\tdefer updateInfoTicker.Stop()\n-\n-\t// Monitor sender for events\n-\tgo func() {\n-\t\tfor event := range w.payloadSender.Monitor() {\n-\t\t\tif event == nil {\n-\t\t\t\tcontinue\n-\t\t\t}\n-\n-\t\t\tswitch event := event.(type) {\n-\t\t\tcase SenderSuccessEvent:\n-\t\t\t\tlog.Infof(\"flushed stat payload to the API, time:%s, size:%d bytes\", event.SendStats.SendTime,\n-\t\t\t\t\tlen(event.Payload.Bytes))\n-\t\t\t\tw.statsClient.Gauge(\"datadog.trace_agent.stats_writer.flush_duration\",\n-\t\t\t\t\tevent.SendStats.SendTime.Seconds(), nil, 1)\n-\t\t\t\tatomic.AddInt64(&w.stats.Payloads, 1)\n-\t\t\tcase SenderFailureEvent:\n-\t\t\t\tlog.Errorf(\"failed to flush stat payload, time:%s, size:%d bytes, error: %s\",\n-\t\t\t\t\tevent.SendStats.SendTime, len(event.Payload.Bytes), event.Error)\n-\t\t\t\tatomic.AddInt64(&w.stats.Errors, 1)\n-\t\t\tcase SenderRetryEvent:\n-\t\t\t\tlog.Errorf(\"retrying flush stat payload, retryNum: %d, delay:%s, error: %s\",\n-\t\t\t\t\tevent.RetryNum, event.RetryDelay, event.Error)\n-\t\t\t\tatomic.AddInt64(&w.stats.Retries, 1)\n-\t\t\tdefault:\n-\t\t\t\tlog.Debugf(\"don't know how to handle event with type %T\", event)\n-\t\t\t}\n-\t\t}\n-\t}()\n-\n \tfor {\n \t\tselect {\n \t\tcase stats := <-w.InStats:\n \t\t\tw.handleStats(stats)\n-\t\tcase <-updateInfoTicker.C:\n-\t\t\tgo w.updateInfo()\n \t\tcase <-w.exit:\n \t\t\tlog.Info(\"exiting stats writer\")\n \t\t\treturn\n \t\t}\n \t}\n }\n \n-// Stop stops the main Run loop.\n+// Stop stops the writer's goroutines.\n func (w *StatsWriter) Stop() {\n \tclose(w.exit)\n \tw.exitWG.Wait()\n+\n+\t// Closing the base writer, among other things, will close the\n+\t// w.payloadSender.Monitor() channel, stoping the monitoring\n+\t// goroutine.\n \tw.BaseWriter.Stop()\n }\n \n func (w *StatsWriter) handleStats(stats []model.StatsBucket) {\n-\tnumStats := len(stats)\n-\n-\t// If no stats, we can't construct anything\n-\tif numStats == 0 {\n+\tpayloads, nbStatBuckets, nbEntries := w.buildPayloads(stats, w.conf.MaxEntriesPerPayload)\n+\tif len(payloads) == 0 {\n \t\treturn\n \t}\n-\tlog.Debugf(\"going to flush stats buckets, %d buckets\", numStats)\n-\tatomic.AddInt64(&w.stats.StatsBuckets, int64(numStats))\n \n-\tstatsPayload := &model.StatsPayload{\n-\t\tHostName: w.hostName,\n-\t\tEnv:      w.env,\n-\t\tStats:    stats,\n-\t}\n+\tlog.Debugf(\"going to flush %v entries in %v stat buckets in %v payloads\",\n+\t\tnbEntries, nbStatBuckets, len(payloads),\n+\t)\n \n-\tdata, err := model.EncodeStatsPayload(statsPayload)\n-\tif err != nil {\n-\t\tlog.Errorf(\"encoding issue: %v\", err)\n-\t\treturn\n-\t}\n+\tatomic.AddInt64(&w.info.StatsBuckets, int64(nbStatBuckets))\n \n \theaders := map[string]string{\n \t\tlanguageHeaderKey:  strings.Join(info.Languages(), \"|\"),\n \t\t\"Content-Type\":     \"application/json\",\n \t\t\"Content-Encoding\": \"gzip\",\n \t}\n \n-\tatomic.AddInt64(&w.stats.Bytes, int64(len(data)))\n+\tfor _, p := range payloads {\n+\t\t// Synchronously send the paylods one after the other\n+\t\tdata, err := model.EncodeStatsPayload(p)\n+\t\tif err != nil {\n+\t\t\tlog.Errorf(\"encoding issue: %v\", err)\n+\t\t\treturn\n+\t\t}\n+\n+\t\tpayload := NewPayload(data, headers)\n+\t\tw.payloadSender.Send(payload)\n+\n+\t\tatomic.AddInt64(&w.info.Bytes, int64(len(data)))\n+\t}\n+}\n+\n+type timeWindow struct {\n+\tstart, duration int64\n+}\n+\n+// buildPayloads returns a set of payloads to send out, each paylods\n+// guaranteed to have the number of stats buckets under the given\n+// maximum.\n+func (w *StatsWriter) buildPayloads(stats []model.StatsBucket, maxEntriesPerPayloads int) ([]*model.StatsPayload, int, int) {\n+\tif len(stats) == 0 { // It could happen apparently\n+\t\treturn []*model.StatsPayload{}, 0, 0\n+\t}\n+\n+\t// 1. Get an estimate of how many payloads we need, based on\n+\t//    the total number of map entries (i.e: sum of number of\n+\t//    items in the stats bucket's count map). Called N for the\n+\t//    rest of the description.  NOTE: we use the number of\n+\t//    items in the count map as the reference, but in reality,\n+\t//    what take place are the distributions. We are guaranteed\n+\t//    the number of entries in the count map is > than the\n+\t//    number of entries in the distributions maps, so the\n+\t//    algorithm is correct, but indeed this means we could do\n+\t//    better.\n+\tnbEntries := 0\n+\tfor _, s := range stats {\n+\t\tnbEntries += len(s.Counts)\n+\t}\n+\n+\tif maxEntriesPerPayloads <= 0 || nbEntries < maxEntriesPerPayloads { // Nothing to do, break early.\n+\t\treturn []*model.StatsPayload{&model.StatsPayload{\n+\t\t\tHostName: w.hostName,\n+\t\t\tEnv:      w.env,\n+\t\t\tStats:    stats,\n+\t\t}}, len(stats), nbEntries\n+\t}\n+\n+\tnbPayloads := nbEntries / maxEntriesPerPayloads","path":"writer/stats_writer.go","position":226,"original_position":226,"commit_id":"df80a8cab62fdb1eba8e62b0dcc92f12e58fd086","original_commit_id":"df80a8cab62fdb1eba8e62b0dcc92f12e58fd086","user":{"login":"LotharSee","id":2720261,"node_id":"MDQ6VXNlcjI3MjAyNjE=","avatar_url":"https://avatars1.githubusercontent.com/u/2720261?v=4","gravatar_id":"","url":"https://api.github.com/users/LotharSee","html_url":"https://github.com/LotharSee","followers_url":"https://api.github.com/users/LotharSee/followers","following_url":"https://api.github.com/users/LotharSee/following{/other_user}","gists_url":"https://api.github.com/users/LotharSee/gists{/gist_id}","starred_url":"https://api.github.com/users/LotharSee/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/LotharSee/subscriptions","organizations_url":"https://api.github.com/users/LotharSee/orgs","repos_url":"https://api.github.com/users/LotharSee/repos","events_url":"https://api.github.com/users/LotharSee/events{/privacy}","received_events_url":"https://api.github.com/users/LotharSee/received_events","type":"User","site_admin":false},"body":"Oops saw next line ; forget it.","created_at":"2018-06-06T12:48:47Z","updated_at":"2018-06-06T12:48:47Z","html_url":"https://github.com/DataDog/datadog-trace-agent/pull/432#discussion_r193396832","pull_request_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/pulls/432","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/DataDog/datadog-trace-agent/pulls/comments/193396832"},"html":{"href":"https://github.com/DataDog/datadog-trace-agent/pull/432#discussion_r193396832"},"pull_request":{"href":"https://api.github.com/repos/DataDog/datadog-trace-agent/pulls/432"}},"in_reply_to_id":193396642},"pull_request":{"url":"https://api.github.com/repos/DataDog/datadog-trace-agent/pulls/432","id":192693673,"node_id":"MDExOlB1bGxSZXF1ZXN0MTkyNjkzNjcz","html_url":"https://github.com/DataDog/datadog-trace-agent/pull/432","diff_url":"https://github.com/DataDog/datadog-trace-agent/pull/432.diff","patch_url":"https://github.com/DataDog/datadog-trace-agent/pull/432.patch","issue_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/issues/432","number":432,"state":"open","locked":false,"title":"stats writer: split stats payloads based on number of entries.","user":{"login":"vlad-mh","id":1613036,"node_id":"MDQ6VXNlcjE2MTMwMzY=","avatar_url":"https://avatars2.githubusercontent.com/u/1613036?v=4","gravatar_id":"","url":"https://api.github.com/users/vlad-mh","html_url":"https://github.com/vlad-mh","followers_url":"https://api.github.com/users/vlad-mh/followers","following_url":"https://api.github.com/users/vlad-mh/following{/other_user}","gists_url":"https://api.github.com/users/vlad-mh/gists{/gist_id}","starred_url":"https://api.github.com/users/vlad-mh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vlad-mh/subscriptions","organizations_url":"https://api.github.com/users/vlad-mh/orgs","repos_url":"https://api.github.com/users/vlad-mh/repos","events_url":"https://api.github.com/users/vlad-mh/events{/privacy}","received_events_url":"https://api.github.com/users/vlad-mh/received_events","type":"User","site_admin":false},"body":"Adds a splitting logic in the stats writer in order never to exceed a pre-configured maximum number of \"entries\" in a stats payload.\r\n\r\nDoing so ensures we don't hit the maximum payload size of the Datadog trace intake API.\r\n\r\nThe first commit is just a cleanup of the stats writer code, and some added comments.\r\n\r\nThe second commit adds the configuration value `max_entries_per_payload`. This value should be tweaked very cautiously. Setting it too low will have the agent send much more payloads than it should when flushing, which will impact performances and will hit the backend significantly more. Setting the value too high, and the payloads might end up being rejected due to their size.\r\n\r\nThe third commit is the actual splitting logic + unit tests.","created_at":"2018-06-05T12:43:20Z","updated_at":"2018-06-06T12:48:47Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5db905347e5bed9fb2a696f66c1182a42e59b848","assignee":null,"assignees":[],"requested_reviewers":[{"login":"gbbr","id":6686356,"node_id":"MDQ6VXNlcjY2ODYzNTY=","avatar_url":"https://avatars2.githubusercontent.com/u/6686356?v=4","gravatar_id":"","url":"https://api.github.com/users/gbbr","html_url":"https://github.com/gbbr","followers_url":"https://api.github.com/users/gbbr/followers","following_url":"https://api.github.com/users/gbbr/following{/other_user}","gists_url":"https://api.github.com/users/gbbr/gists{/gist_id}","starred_url":"https://api.github.com/users/gbbr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gbbr/subscriptions","organizations_url":"https://api.github.com/users/gbbr/orgs","repos_url":"https://api.github.com/users/gbbr/repos","events_url":"https://api.github.com/users/gbbr/events{/privacy}","received_events_url":"https://api.github.com/users/gbbr/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":{"url":"https://api.github.com/repos/DataDog/datadog-trace-agent/milestones/15","html_url":"https://github.com/DataDog/datadog-trace-agent/milestone/15","labels_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/milestones/15/labels","id":3357380,"node_id":"MDk6TWlsZXN0b25lMzM1NzM4MA==","number":15,"title":"6.3.0","description":"","creator":{"login":"palazzem","id":1560405,"node_id":"MDQ6VXNlcjE1NjA0MDU=","avatar_url":"https://avatars2.githubusercontent.com/u/1560405?v=4","gravatar_id":"","url":"https://api.github.com/users/palazzem","html_url":"https://github.com/palazzem","followers_url":"https://api.github.com/users/palazzem/followers","following_url":"https://api.github.com/users/palazzem/following{/other_user}","gists_url":"https://api.github.com/users/palazzem/gists{/gist_id}","starred_url":"https://api.github.com/users/palazzem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/palazzem/subscriptions","organizations_url":"https://api.github.com/users/palazzem/orgs","repos_url":"https://api.github.com/users/palazzem/repos","events_url":"https://api.github.com/users/palazzem/events{/privacy}","received_events_url":"https://api.github.com/users/palazzem/received_events","type":"User","site_admin":false},"open_issues":3,"closed_issues":2,"state":"open","created_at":"2018-05-18T14:17:29Z","updated_at":"2018-06-06T12:47:56Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/pulls/432/commits","review_comments_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/pulls/432/comments","review_comment_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/pulls/comments{/number}","comments_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/issues/432/comments","statuses_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/statuses/df80a8cab62fdb1eba8e62b0dcc92f12e58fd086","head":{"label":"DataDog:vlad/stats-writer-split-payload","ref":"vlad/stats-writer-split-payload","sha":"df80a8cab62fdb1eba8e62b0dcc92f12e58fd086","user":{"login":"DataDog","id":365230,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM2NTIzMA==","avatar_url":"https://avatars1.githubusercontent.com/u/365230?v=4","gravatar_id":"","url":"https://api.github.com/users/DataDog","html_url":"https://github.com/DataDog","followers_url":"https://api.github.com/users/DataDog/followers","following_url":"https://api.github.com/users/DataDog/following{/other_user}","gists_url":"https://api.github.com/users/DataDog/gists{/gist_id}","starred_url":"https://api.github.com/users/DataDog/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DataDog/subscriptions","organizations_url":"https://api.github.com/users/DataDog/orgs","repos_url":"https://api.github.com/users/DataDog/repos","events_url":"https://api.github.com/users/DataDog/events{/privacy}","received_events_url":"https://api.github.com/users/DataDog/received_events","type":"Organization","site_admin":false},"repo":{"id":38379832,"node_id":"MDEwOlJlcG9zaXRvcnkzODM3OTgzMg==","name":"datadog-trace-agent","full_name":"DataDog/datadog-trace-agent","owner":{"login":"DataDog","id":365230,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM2NTIzMA==","avatar_url":"https://avatars1.githubusercontent.com/u/365230?v=4","gravatar_id":"","url":"https://api.github.com/users/DataDog","html_url":"https://github.com/DataDog","followers_url":"https://api.github.com/users/DataDog/followers","following_url":"https://api.github.com/users/DataDog/following{/other_user}","gists_url":"https://api.github.com/users/DataDog/gists{/gist_id}","starred_url":"https://api.github.com/users/DataDog/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DataDog/subscriptions","organizations_url":"https://api.github.com/users/DataDog/orgs","repos_url":"https://api.github.com/users/DataDog/repos","events_url":"https://api.github.com/users/DataDog/events{/privacy}","received_events_url":"https://api.github.com/users/DataDog/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/DataDog/datadog-trace-agent","description":"Datadog APM agent.","fork":false,"url":"https://api.github.com/repos/DataDog/datadog-trace-agent","forks_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/forks","keys_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/keys{/key_id}","collaborators_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/teams","hooks_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/hooks","issue_events_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/issues/events{/number}","events_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/events","assignees_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/assignees{/user}","branches_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/branches{/branch}","tags_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/tags","blobs_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/git/refs{/sha}","trees_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/git/trees{/sha}","statuses_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/statuses/{sha}","languages_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/languages","stargazers_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/stargazers","contributors_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/contributors","subscribers_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/subscribers","subscription_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/subscription","commits_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/commits{/sha}","git_commits_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/git/commits{/sha}","comments_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/comments{/number}","issue_comment_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/issues/comments{/number}","contents_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/contents/{+path}","compare_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/compare/{base}...{head}","merges_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/merges","archive_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/downloads","issues_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/issues{/number}","pulls_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/pulls{/number}","milestones_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/milestones{/number}","notifications_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/labels{/name}","releases_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/releases{/id}","deployments_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/deployments","created_at":"2015-07-01T15:45:17Z","updated_at":"2018-06-05T13:42:04Z","pushed_at":"2018-06-06T12:42:28Z","git_url":"git://github.com/DataDog/datadog-trace-agent.git","ssh_url":"git@github.com:DataDog/datadog-trace-agent.git","clone_url":"https://github.com/DataDog/datadog-trace-agent.git","svn_url":"https://github.com/DataDog/datadog-trace-agent","homepage":"http://www.datadog.com","size":5462,"stargazers_count":46,"watchers_count":46,"language":"Go","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":21,"mirror_url":null,"archived":false,"open_issues_count":24,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":21,"open_issues":24,"watchers":46,"default_branch":"master"}},"base":{"label":"DataDog:master","ref":"master","sha":"416acd39e81c5d6a1c8b79fe30abee295d4325b0","user":{"login":"DataDog","id":365230,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM2NTIzMA==","avatar_url":"https://avatars1.githubusercontent.com/u/365230?v=4","gravatar_id":"","url":"https://api.github.com/users/DataDog","html_url":"https://github.com/DataDog","followers_url":"https://api.github.com/users/DataDog/followers","following_url":"https://api.github.com/users/DataDog/following{/other_user}","gists_url":"https://api.github.com/users/DataDog/gists{/gist_id}","starred_url":"https://api.github.com/users/DataDog/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DataDog/subscriptions","organizations_url":"https://api.github.com/users/DataDog/orgs","repos_url":"https://api.github.com/users/DataDog/repos","events_url":"https://api.github.com/users/DataDog/events{/privacy}","received_events_url":"https://api.github.com/users/DataDog/received_events","type":"Organization","site_admin":false},"repo":{"id":38379832,"node_id":"MDEwOlJlcG9zaXRvcnkzODM3OTgzMg==","name":"datadog-trace-agent","full_name":"DataDog/datadog-trace-agent","owner":{"login":"DataDog","id":365230,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM2NTIzMA==","avatar_url":"https://avatars1.githubusercontent.com/u/365230?v=4","gravatar_id":"","url":"https://api.github.com/users/DataDog","html_url":"https://github.com/DataDog","followers_url":"https://api.github.com/users/DataDog/followers","following_url":"https://api.github.com/users/DataDog/following{/other_user}","gists_url":"https://api.github.com/users/DataDog/gists{/gist_id}","starred_url":"https://api.github.com/users/DataDog/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DataDog/subscriptions","organizations_url":"https://api.github.com/users/DataDog/orgs","repos_url":"https://api.github.com/users/DataDog/repos","events_url":"https://api.github.com/users/DataDog/events{/privacy}","received_events_url":"https://api.github.com/users/DataDog/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/DataDog/datadog-trace-agent","description":"Datadog APM agent.","fork":false,"url":"https://api.github.com/repos/DataDog/datadog-trace-agent","forks_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/forks","keys_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/keys{/key_id}","collaborators_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/teams","hooks_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/hooks","issue_events_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/issues/events{/number}","events_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/events","assignees_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/assignees{/user}","branches_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/branches{/branch}","tags_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/tags","blobs_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/git/refs{/sha}","trees_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/git/trees{/sha}","statuses_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/statuses/{sha}","languages_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/languages","stargazers_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/stargazers","contributors_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/contributors","subscribers_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/subscribers","subscription_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/subscription","commits_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/commits{/sha}","git_commits_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/git/commits{/sha}","comments_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/comments{/number}","issue_comment_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/issues/comments{/number}","contents_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/contents/{+path}","compare_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/compare/{base}...{head}","merges_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/merges","archive_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/downloads","issues_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/issues{/number}","pulls_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/pulls{/number}","milestones_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/milestones{/number}","notifications_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/labels{/name}","releases_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/releases{/id}","deployments_url":"https://api.github.com/repos/DataDog/datadog-trace-agent/deployments","created_at":"2015-07-01T15:45:17Z","updated_at":"2018-06-05T13:42:04Z","pushed_at":"2018-06-06T12:42:28Z","git_url":"git://github.com/DataDog/datadog-trace-agent.git","ssh_url":"git@github.com:DataDog/datadog-trace-agent.git","clone_url":"https://github.com/DataDog/datadog-trace-agent.git","svn_url":"https://github.com/DataDog/datadog-trace-agent","homepage":"http://www.datadog.com","size":5462,"stargazers_count":46,"watchers_count":46,"language":"Go","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":21,"mirror_url":null,"archived":false,"open_issues_count":24,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":21,"open_issues":24,"watchers":46,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/DataDog/datadog-trace-agent/pulls/432"},"html":{"href":"https://github.com/DataDog/datadog-trace-agent/pull/432"},"issue":{"href":"https://api.github.com/repos/DataDog/datadog-trace-agent/issues/432"},"comments":{"href":"https://api.github.com/repos/DataDog/datadog-trace-agent/issues/432/comments"},"review_comments":{"href":"https://api.github.com/repos/DataDog/datadog-trace-agent/pulls/432/comments"},"review_comment":{"href":"https://api.github.com/repos/DataDog/datadog-trace-agent/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/DataDog/datadog-trace-agent/pulls/432/commits"},"statuses":{"href":"https://api.github.com/repos/DataDog/datadog-trace-agent/statuses/df80a8cab62fdb1eba8e62b0dcc92f12e58fd086"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"LotharSee"}}