Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

haproxy http stats #5819

Merged
merged 5 commits into from
Dec 27, 2017
Merged

haproxy http stats #5819

merged 5 commits into from
Dec 27, 2017

Conversation

jsoriano
Copy link
Member

@jsoriano jsoriano commented Dec 6, 2017

Adds support for haproxy http stats endpoint with support with basic authentication (what fixes #5178).

@elasticmachine
Copy link
Collaborator

Can one of the admins verify this patch?

@ruflin
Copy link
Contributor

ruflin commented Dec 6, 2017

@jsoriano Thanks a lot for you contribution. Any chance we could separate the PR into 2 PR's. One with the changes to the testing / Makefile and the other one with the Stat change. So we can discuss these changes seperately and one does not hold back the other.

@jsoriano
Copy link
Member Author

jsoriano commented Dec 6, 2017

@ruflin sure

}

func (p *httpProto) Info() (*bytes.Buffer, error) {
return nil, errors.New("not supported")
Copy link
Contributor

Choose a reason for hiding this comment

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

That is interesting. So http does not support the info request? We should probably state that in the docs somewhere.

Copy link
Member Author

Choose a reason for hiding this comment

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

It seems so :/ I couldn't find a way to do it (apart of parsing the human stats html), and according to the code the dump info function is only called when executing the show info command https://github.com/haproxy/haproxy/blob/master/src/stats.c#L3130.

Ok, I'll review docs in the repo.

Copy link
Member Author

Choose a reason for hiding this comment

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

Doc and line to changelog added.

"hosts": self.get_hosts(),
"period": "5s"
}])
def _test_info(self):
Copy link
Contributor

Choose a reason for hiding this comment

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

Why did you add an _ in front and remove the intergration part line?

Copy link
Member Author

Choose a reason for hiding this comment

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

I moved common code to "internal" functions so it can be reused for multiple cases. At the end this test has only the tcp socket case (it could maybe have also another case for a unix socket file), but the stat test has multiple cases.

Copy link
Contributor

Choose a reason for hiding this comment

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

Got it. The diff tricked me here :-)

@jsoriano
Copy link
Member Author

jsoriano commented Dec 6, 2017

Changes on tests moved to #5820

@ruflin
Copy link
Contributor

ruflin commented Dec 6, 2017

Thanks a lot for taking this. Only had a quick look so far but that looks really promising. Will have a deeper look later.

@ruflin ruflin added Metricbeat Metricbeat review labels Dec 6, 2017
Copy link
Contributor

@ruflin ruflin left a comment

Choose a reason for hiding this comment

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

Could you add a line to the CHANGELOG.asciidoc and also update the docs file probably best the one on the module level that http and socket are supported, but only socket works for both metricsets?

func (p *httpProto) Stat() (*bytes.Buffer, error) {
url := p.URL.String()
// Force csv format
if !strings.HasSuffix(url, ";csv") {
Copy link
Contributor

Choose a reason for hiding this comment

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

What other formats do we have available?

Copy link
Member Author

Choose a reason for hiding this comment

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

Only human-oriented html, so csv is the only reasonable one to parse :)

Copy link
Member Author

Choose a reason for hiding this comment

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

JSON has been added to haproxy 1.8, but we may continue using CSV for backwards compatibility.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds like something we should probably add more details about to the docs.

return nil, fmt.Errorf("invalid response: %s", resp.Status)
}

d, err := ioutil.ReadAll(resp.Body)
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if we need here afterwards resp.Body.Close() to not leak the resource?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ouch, you are right, good catch

Copy link
Member Author

Choose a reason for hiding this comment

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

Close added

"hosts": self.get_hosts(),
"period": "5s"
}])
def _test_info(self):
Copy link
Contributor

Choose a reason for hiding this comment

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

Got it. The diff tricked me here :-)

@jsoriano jsoriano changed the title haproxy http stats and some fixes in tests haproxy http stats Dec 8, 2017
case "tcp":
return &Client{&unixProto{Network: u.Scheme, Address: u.Host}}, nil
case "unix":
return &Client{&unixProto{Network: u.Scheme, Address: u.Path}}, nil
Copy link
Member Author

@jsoriano jsoriano Dec 8, 2017

Choose a reason for hiding this comment

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

I have modified this, before the url was parsed just splitting protocol and address, and the addres obtained this way was fine both for tcp and unix sockets. But now after the change to use url package for url parsing the address is Host for tcp, but Path for unix.

In any case, even if seems to be supported, there was no test coverage for unix socket, this will have to be revisited, as a volume in the docker would be needed to test this.

Copy link
Contributor

Choose a reason for hiding this comment

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

What are you saying is "this should still work the same but we don't have any tests and we didn't have any before"? :-)

Copy link
Member Author

Choose a reason for hiding this comment

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

Exactly :D

Copy link
Contributor

@ruflin ruflin left a comment

Choose a reason for hiding this comment

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

Some last minor comments. PR looks good to me.

For example, to enable stats reporting via any local IP on port 14567, place
this statement under the `global` or `default` section of the haproxy config:

stats socket 127.0.0.1:14567
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add ticks around this to make sure it shows up as code in the docs.

be added. For example, to open this frontend to any IP on port 14567 with
required authentication add this to the haproxy config:

listen stats
Copy link
Contributor

Choose a reason for hiding this comment

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

Use a code block here:

["source","sh",subs="attributes"]
----
your code
----

I don't know what source type would work best here. @dedemorton perhaps knows?

Copy link
Member Author

@jsoriano jsoriano Dec 12, 2017

Choose a reason for hiding this comment

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

It is rendered by github as code just leaving spaces before, the same with the previous snippet. Should I better use code blocks in any case?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, please use code blocks as for our docs build Github is not really the one which counts in the end. We use code block in hopefully most other places.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok :)

Copy link
Member Author

Choose a reason for hiding this comment

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

I have set haproxy as "language", if empty, make docs fails.

case "tcp":
return &Client{&unixProto{Network: u.Scheme, Address: u.Host}}, nil
case "unix":
return &Client{&unixProto{Network: u.Scheme, Address: u.Path}}, nil
Copy link
Contributor

Choose a reason for hiding this comment

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

What are you saying is "this should still work the same but we don't have any tests and we didn't have any before"? :-)

}

if p.URL.User != nil {
password, _ := p.URL.User.Password()
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if we should check this error here? Is no password = error?

Copy link
Member Author

Choose a reason for hiding this comment

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

The ignored value is a boolean telling if the password was set, I don't know if there are cases where basic authentication would work with an empty password... In any case I think it can be fine as is, if the credentials are wrong, the request will fail and this error is checked.

if err != nil {
return response, err
return nil, errors.New("invalid url")
Copy link
Member

Choose a reason for hiding this comment

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

Use errors.Wrap so that the original error message is not lost.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok.

case "http", "https":
return &Client{&httpProto{URL: u}}, nil
default:
return nil, errors.New("invalid protocol scheme")
Copy link
Member

Choose a reason for hiding this comment

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

Include the invalid value in the error message with errors.Errorf.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, using errors.Errorf in the rest of the file too.

@andrewkroh
Copy link
Member

jenkins, test it

Copy link
Contributor

@ruflin ruflin left a comment

Choose a reason for hiding this comment

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

LGTM. Only change needs is the code blocks in the docs.

@ruflin
Copy link
Contributor

ruflin commented Dec 20, 2017

jenkins, test it

@ruflin
Copy link
Contributor

ruflin commented Dec 20, 2017

@jsoriano Can you run make fmt and push again? That should make CI happy.

@jsoriano jsoriano force-pushed the haproxy-userpass branch 2 times, most recently from d6e73f2 to 5013a93 Compare December 20, 2017 09:27
@jsoriano
Copy link
Member Author

Pushed changes after make fmt and make collect-docs and CI seems happier :)

@ruflin
Copy link
Contributor

ruflin commented Dec 21, 2017

jenkins, test it

@jsoriano jsoriano force-pushed the haproxy-userpass branch 2 times, most recently from 9fa6980 to b1e246a Compare December 21, 2017 10:07
@ruflin
Copy link
Contributor

ruflin commented Dec 21, 2017

jenkins, test it

@ruflin ruflin merged commit 5792e5a into elastic:master Dec 27, 2017
@ruflin
Copy link
Contributor

ruflin commented Dec 27, 2017

@jsoriano Merged. Thanks for all your work on this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

HAProxy module authentication support for metrics
4 participants