Skip to content
This repository was archived by the owner on Aug 30, 2019. It is now read-only.

writer: allow writing to multiple endpoints. #496

Closed
wants to merge 8 commits into from
Closed

Conversation

gbbr
Copy link
Contributor

@gbbr gbbr commented Oct 17, 2018

Description

This change adds a new set of options to the apm_config sub-section of the config file, enabling the possibility of forwarding data (traces, stats & services) to additional endpoints besides the main one.

Example configuration:

apm_config:
  ...
  # The trace agent will also forward traces, stats and services to these endpoints,
  # besides the main endpoint.
  additional_endpoints:
    # Simply specify the list of URLs to forward to along with one or more API keys
    # to use for that URL.
    https://trace.agent.datadoghq.eu:
    - 1234abcd
    - 4567efghi
    https://trace.agent.other-endpoint.com:
    - 890jkl

References

@gbbr gbbr added this to the next milestone Oct 17, 2018
@gbbr gbbr force-pushed the gbbr/multiwriter branch 2 times, most recently from 7e8cf03 to e11686c Compare October 17, 2018 13:49
@gbbr

This comment has been minimized.

@olivielpeau

This comment has been minimized.

@gbbr gbbr force-pushed the gbbr/multiwriter branch 8 times, most recently from 1e49d6e to f7b442a Compare October 18, 2018 10:02
@gbbr gbbr requested review from AlexJF and palazzem October 18, 2018 10:03
@gbbr

This comment has been minimized.

@gbbr gbbr modified the milestones: next, 6.7.0 Oct 18, 2018
@gbbr
Copy link
Contributor Author

gbbr commented Oct 18, 2018

@AlexJF @palazzem ready for review

config/agent.go Outdated
APIEndpoint string
APIKey string `json:"-"` // never publish this
APIEnabled bool
APIEndpoint string
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I should merge these two into one:

    Endpoints []*Endpoint

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, don't see the point of treating main vs additional differently and if we need to we can just ensure the main is the first in this endpoints list.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing it in the scope of this PR, separate commit.

Copy link

@AlexJF AlexJF left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partial review, I'll look at the remaining files after lunch 👨‍🍳

config/agent.go Outdated
APIEndpoint string
APIKey string `json:"-"` // never publish this
APIEnabled bool
APIEndpoint string
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, don't see the point of treating main vs additional differently and if we need to we can just ensure the main is the first in this endpoints list.

apiKey := e.APIKey
if apiKey == "" {
// if this endpoint doesn't have its own API key, try the main one.
apiKey = conf.APIKey
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't even allow this to occur. Looking at the infra PR, they dedupe endpoints missing apikey already at the config: https://github.com/DataDog/datadog-agent/pull/352/files#diff-091ace02b49a46f55f2586cfec89a160R95

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, removed it entirely. I've modified the config to ignore endpoints without API keys; but I think deduping is a bit overkill unless I'm missing some aspect.

// newClient returns a http.Client configured with the Agent options.
func newClient(conf *config.AgentConfig, noProxy bool) *http.Client {
transport := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: conf.SkipSSLValidation},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've had some issues with some other code that was using custom transports. We should probably include all settings set in DefaultTransport as well otherwise most timeouts will be zeroed out and we'll wait for much longer than we should when network issues happen.

https://golang.org/src/net/http/transport.go (line 42). I'm fine with this going to another PR but we should track this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're very right here, this was indeed an oversight. Great catch! I've copied the http.DefaultTransport except the Proxy: http.ProxyFromEnvironment part which I assume was likely also an oversight on our behalf. We can ponder whether to introduce that back in a separate topic. I'm afraid not to cause any backwards breaking changes because of introducing it.

if len(endpoints) == 1 {
return NewCustomQueuablePayloadSender(endpoints[0], cfg)
}
var senders []PayloadSender
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nit, we can already allocate enough space for len(endpoints).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely.

func newMultiSender(cfg config.QueuablePayloadSenderConf) func([]Endpoint) PayloadSender {
return func(endpoints []Endpoint) PayloadSender {
if len(endpoints) == 1 {
return NewCustomQueuablePayloadSender(endpoints[0], cfg)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice shortcut here, saving a bunch of overhead if not needed 👍


// newMultiSender returns a new factory to generate PayloadSenders capable of forwarding
// payloads to multiple endpoints.
func newMultiSender(cfg config.QueuablePayloadSenderConf) func([]Endpoint) PayloadSender {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name here threw me off initially and breaks expectations imo.

Can we have a newMultiSender(cfg, []Endpoint) and turn this into

newMultiSenderFactory(cfg) func([]Endpoint) {
   return func (endpoints) PayloadSender {
      return newMultiSender(cfg, endpoints);
  }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it. Done.

Copy link
Contributor Author

@gbbr gbbr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great review and I agree with all your points. Submitted a new commit addressing all comments, except the merging of APIEndpoint and AdditionalEndpoints into one, which will follow in this very PR in an upcoming commit (tomorrow).

config/agent.go Outdated
APIEndpoint string
APIKey string `json:"-"` // never publish this
APIEnabled bool
APIEndpoint string
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing it in the scope of this PR, separate commit.

apiKey := e.APIKey
if apiKey == "" {
// if this endpoint doesn't have its own API key, try the main one.
apiKey = conf.APIKey
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, removed it entirely. I've modified the config to ignore endpoints without API keys; but I think deduping is a bit overkill unless I'm missing some aspect.

// newClient returns a http.Client configured with the Agent options.
func newClient(conf *config.AgentConfig, noProxy bool) *http.Client {
transport := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: conf.SkipSSLValidation},
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're very right here, this was indeed an oversight. Great catch! I've copied the http.DefaultTransport except the Proxy: http.ProxyFromEnvironment part which I assume was likely also an oversight on our behalf. We can ponder whether to introduce that back in a separate topic. I'm afraid not to cause any backwards breaking changes because of introducing it.


// newMultiSender returns a new factory to generate PayloadSenders capable of forwarding
// payloads to multiple endpoints.
func newMultiSender(cfg config.QueuablePayloadSenderConf) func([]Endpoint) PayloadSender {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it. Done.

if len(endpoints) == 1 {
return NewCustomQueuablePayloadSender(endpoints[0], cfg)
}
var senders []PayloadSender
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely.

@gbbr gbbr force-pushed the gbbr/multiwriter branch from 3e24e1b to 07e2808 Compare October 18, 2018 15:12
@gbbr gbbr force-pushed the gbbr/multiwriter branch from 07e2808 to 65c92e4 Compare October 19, 2018 07:46
@gbbr gbbr force-pushed the gbbr/multiwriter branch 2 times, most recently from 36ea26c to 5317672 Compare October 19, 2018 09:13
@gbbr gbbr force-pushed the gbbr/multiwriter branch from 5317672 to e573587 Compare October 19, 2018 09:21
@gbbr
Copy link
Contributor Author

gbbr commented Oct 19, 2018

@AlexJF merged all endpoints in the latest commit. Tested manually with app too, seems to work fine. PTAL when you get a chance.

@gbbr
Copy link
Contributor Author

gbbr commented Oct 19, 2018

@AlexJF good catch, changed in next commit.

Copy link

@AlexJF AlexJF left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good from my side! If everything works in practice lets ship it! 🚢

@gbbr
Copy link
Contributor Author

gbbr commented Oct 22, 2018

Seems Github is buggy. Kept getting errors from using the "Squash & Merge" button and PR is still open even though it was merged twice (see master commits)

@gbbr gbbr closed this Oct 22, 2018
@gbbr
Copy link
Contributor Author

gbbr commented Oct 22, 2018

Seems Github is buggy. Kept getting errors from using the "Squash & Merge" button and PR is still open even though it was merged twice (see master commits)

@gbbr gbbr deleted the gbbr/multiwriter branch October 22, 2018 08:12
@gbbr
Copy link
Contributor Author

gbbr commented Oct 22, 2018

Seems Github is buggy. Kept getting errors from using the "Squash & Merge" button and PR is still open even though it was merged twice (see master commits)

raphaelgavache pushed a commit that referenced this pull request Oct 24, 2018
* writer: add support for multiple endpoints
* writer: add host information to stats
* statsd: ensure all stats get version tag
* writer: remove statsClient field from BaseWriter
raphaelgavache pushed a commit that referenced this pull request Oct 24, 2018
* writer: add support for multiple endpoints
* writer: add host information to stats
* statsd: ensure all stats get version tag
* writer: remove statsClient field from BaseWriter
* all: merge APIEndpoint into Endpoints
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants