-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
New PHP-FPM metricbeat module #3415
Conversation
@tsouza I recommend you to run |
Add pool start time and start since stats Add support for proc stats Refactor stats api call Fix listen_queue => listen_queue_len" Revert "Fix listen_queue => listen_queue_len"" This reverts commit 46ff489fa8cce8d73c2aba42758a51bde4d68a77. Add suport for "listen_queue_len" Add documentation Minor const refactor Add generated doc Add basic testing Fix illegal char in asciidoc Fix type Update generated files Fix package name Add integration tests
212dcfc
to
539f229
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left you a few notes mainly on the schema of the events.
It would be nice to have a simple system tests that checks if docs and the generate events are in sync. See https://github.com/elastic/beats/blob/master/metricbeat/tests/system/test_mysql.py#L41 as an example.
Let me know if I can help in any way.
metricsets: ["pool"] | ||
enabled: true | ||
period: 10s | ||
hosts: ["localhost"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the default port the metrics are exposed? 80 or is it 9000 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
php-fpm default port is 9000
and default status endpoint is /status
. But these defaults does matter much since it's fastcgi
protocol and can't be accessed directly. So there is a need to configure a proxy (with fastcgi
support) and that can be any port and path (no defaults)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, problem is with the above port 80 is the default. Not sure what we should set here best.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can use the "default non-default" 8080 (which is at least nginx's default, iirc)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM
@@ -0,0 +1,6 @@ | |||
- module: php_fpm |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We currently have all module configs commented out which are not enabled by default. This might change in the near future, but for consistency it should be commented out here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The module I started looking at to learn is haproxy
, which is no commented out. But I'll do it then!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, haproxy has a config.yml and a config.full.yml, that is why it also works there.
title: "php_fpm" | ||
description: > | ||
PHP-FPM server status metrics collected from PHP-FPM. | ||
fields: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add here the experimental[]
flag? We do that for all new modules so we can still break compatibility after the first release. This might be a beta flag soonish.
Also please add short_config: false
so it does not show up in the short config. See https://github.com/elastic/beats/blob/master/metricbeat/module/prometheus/_meta/fields.yml#L7 as example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I forgot to mention it in the review, but also the metricsets should have a log line in the New(...) part that has a warning that it is experimental. Also see prometheus.
// HostParser is used for parsing the configured php-fpm hosts. | ||
var HostParser = parse.URLHostParserBuilder{ | ||
DefaultScheme: defaultScheme, | ||
DefaultPath: defaultPath, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To define a config option to change the defaultPath
you can use PathConfigKey
. See https://github.com/elastic/beats/blob/master/metricbeat/module/prometheus/collector/collector.go#L25 as an example. I would suggest to use path
or status_path
as the config option. All other parts are done automatically by the HostParser.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
// configuration entries if needed. | ||
func New(base mb.BaseMetricSet) (mb.MetricSet, error) { | ||
|
||
config := struct{}{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can remove the config part as it is empty in your case.
description: > | ||
The size of the socket queue of pending connections. | ||
|
||
- name: idle_processes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
processes.idle
description: > | ||
The number of idle processes. | ||
|
||
- name: active_processes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
processes.active
description: > | ||
The number of active processes. | ||
|
||
- name: total_processes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
processes.total
description: > | ||
The number of idle + active processes. | ||
|
||
- name: max_active_processes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
processes.max_active
} | ||
|
||
// PoolStats defines all stats fields from a php-fpm pool | ||
type PoolStats struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the response is in JSON, you could use the schema
package to do the conversion. But we can also do that in a follow up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed the response is in JSON and also it came to me that there would be a better way of handling this situation. But I wonder what will happen to the field names itself, since php-fpm replies a JSON with whitespace in field names (e.g. accepted conn
)
Mind pointing out an implementation that uses it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not directly JSON, but similar: https://github.com/elastic/beats/blob/master/metricbeat/module/mongodb/status/data.go
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job!
// NewStatsClient creates a new StatsClient | ||
func NewStatsClient(m mb.BaseMetricSet, isFullStats bool) *StatsClient { | ||
var address string | ||
address = m.HostData().SanitizedURI + "?json" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can move the query param to the URLHostParserBuilder
by setting QueryParams: "json"
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just write address := m.HostData().SanitizedURI
and drop the var address string
. (https://golang.org/ref/spec#Short_variable_declarations)
|
||
// Fetch php-fpm stats | ||
func (c *StatsClient) Fetch() (io.ReadCloser, error) { | ||
req, err := http.NewRequest("GET", c.address, nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once #3413 merges we should update this to use it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I was thinking of skipping the http proxy and directly access php-fpm using a fastcgi client. I could find this one go-fastcgi-client (since golang's fcgi package is for server only). What do you think?
The current metric names and it's description was copied directly from php-fpm configuration file. As they do not follow beats convention much (as pointed out by @ruflin), I decided to take a closer look to find proper names. It seems that the process metrics regarding So I am worried about that users might start to correlate between |
@tsouza If possible I would suggest to leave out calculated values as this can also be potentially done on the elasticsearch side. The way you describe it above it seems even to be temporary so not too usefule as you said. To move this PR forward I suggest to remove the values you are not sure about are useful. The hard part of doing a Metricset is getting all the data and do the conversion. Adding a field is fairly easy. So in case someone requests it, we get the opportunity to ask why it is needed and how it is used and we can easily add it. WDYT? |
"hostname": m.Host(), | ||
|
||
"pool": stats.Pool, | ||
"connections.queued": stats.ListenQueue, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have to nest this into a common.MapStr as otherwise elasticsearch 2.x will complain here. So this becomes:
"connections": common.MapStr{
"queued": stats.ListenQueue,
"accepted" : stats.AcceptdConn,
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok! The docs was not clear in that sense to me! So I just took a shot hah
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we actually detected this problem with 2.x only after we wrote the docs ;-)
* Add docker environment for integration and system testing * Add system test file to check for correct docs. * Brings docs in line with generated output * Update data.json * Remove hostname fields as already part of metricset * Apply schema instead of manual conversion * Rename pool.pool to pool.name * Remove separate http client as not needed anymore This is a follow up PR for elastic#3415
* Add docker environment for integration and system testing * Add system test file to check for correct docs. * Brings docs in line with generated output * Update data.json * Remove hostname fields as already part of metricset * Apply schema instead of manual conversion * Rename pool.pool to pool.name * Remove separate http client as not needed anymore This is a follow up PR for #3415
* Add docker environment for integration and system testing * Add system test file to check for correct docs. * Brings docs in line with generated output * Update data.json * Remove hostname fields as already part of metricset * Apply schema instead of manual conversion * Rename pool.pool to pool.name * Remove separate http client as not needed anymore This is a follow up PR for elastic#3415
This adds PHP-FPM support for metricbeat (#2247)
It is my first attempt writing a metricbeat module. One minor configuration that is not clear to me is how to externalize configuration of
DefaultPath
of theHostParser
. Currently it is set to/status
(which is php-fpm's default) but I just don't know how to make it user-configurable.Also, I believe metricbeat creates sample dashboards, I would like to build a php-fpm sample dashboard and add it. Where to start?