-
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 metricbeat module: pgbouncer #41174
base: main
Are you sure you want to change the base?
Conversation
💚 CLA has been signed |
This pull request is now in conflicts. Could you fix it? 🙏
|
This pull request does not have a backport label.
To fixup this pull request, you need to add the backport labels for the needed
|
|
3f19266
to
22fe659
Compare
Pinging @elastic/elastic-agent-data-plane (Team:Elastic-Agent-Data-Plane) |
Thanks @manuelsaks for your contribution. |
@lalit-satapathy as this is related to PostgreSQL, would you mind assigning someone from your team for the reviewing part? |
/test |
1 similar comment
/test |
We are moving in the right direction, one last error:
|
/test |
The problem is:
This occurs when running the def test_index_management(self):
"""
Test that the template can be loaded with `setup --index-management`
"""
es = Elasticsearch([self.get_elasticsearch_url()])
self.render_config_template(
modules=[{
"name": "apache",
"metricsets": ["status"],
"hosts": ["localhost"],
}],
elasticsearch={"host": self.get_elasticsearch_url()},
)
exit_code = self.run_beat(extra_args=["setup", "--index-management", "-E", "setup.template.overwrite=true"])
assert exit_code == 0
assert self.log_contains('Loaded index template')
assert len(es.cat.templates(name='metricbeat-*', h='name')) > 0 If I increase the field limit from the
to
the test passes. Please advise what should I do now. |
/test |
/test |
/test |
/test |
/test |
run docs-build |
@manuelsaks Sorry for the extra delay, we found the root cause of the issue you were facing and it has been fixed. |
@kush-elastic can you please review this new beats module? |
- name: free_clients | ||
type: long | ||
description: > | ||
Count of free clients. These are clients that are disconnected, but PgBouncer keeps the memory around that was allocated for them so it can be reused for future clients to avoid allocations. | ||
- name: used_clients | ||
type: long | ||
description: > | ||
Count of used clients. | ||
- name: login_clients | ||
type: long | ||
description: > | ||
Count of clients in login state. |
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 do you think of normalizing these fields in Sub JSON fields?
{
"clients": {
"free":0,
"used":0,
"login":0
}
}
Same goes for servers as well. It will be easier for user to understand from document.
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.
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.
Added comments
func (m *MetricSet) Fetch(reporter mb.ReporterV2) error { | ||
ctx := context.Background() | ||
results, err := m.QueryStats(ctx, "SHOW LISTS;") |
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 you need context here, you should probably use interface ReportingMetricSetV2WithContext
which will give you Fetch(ctx context.Context, r ReporterV2) error
.
Avoid using Background context 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.
for _, s := range results { | ||
listValue, ok := s["list"].(string) | ||
if !ok { | ||
return fmt.Errorf("expected string type for 'list' but got something else") |
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.
are we suppose to not collect remaining results and just return error from 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.
Yeah, it might be better to log a warning instead of returning an error here, so that we can still process the remaining valid results. What do you think?
if len(errs) > 0 { | ||
t.Fatalf("Expected 0 error, had %d. %v\n", len(errs), errs) | ||
} | ||
assert.NotEmpty(t, events) |
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 len(errs) > 0 { | |
t.Fatalf("Expected 0 error, had %d. %v\n", len(errs), errs) | |
} | |
assert.NotEmpty(t, events) | |
require.Empty(t, errs, "Expected no errors during fetch") | |
require.NotEmpty(t, events, "Expected to receive at least one event") |
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.
"credentials_cache": { | ||
"size": 616, | ||
"used": 1, | ||
"free": 49, | ||
"memtotal": 30800 | ||
}, | ||
"peer_pool_cache": { | ||
"size": 616, | ||
"used": 1, | ||
"free": 49, | ||
"memtotal": 30800 | ||
}, |
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 SURE IF APPLICABLE:
how about normalizing this from cache?
if in future you add something else in the metricset it would be easier to manage those data as well.
"credentials_cache": { | |
"size": 616, | |
"used": 1, | |
"free": 49, | |
"memtotal": 30800 | |
}, | |
"peer_pool_cache": { | |
"size": 616, | |
"used": 1, | |
"free": 49, | |
"memtotal": 30800 | |
}, | |
{ | |
"cache": { | |
"credentials": { | |
"size": 616, | |
"used": 1, | |
"free": 49, | |
"memtotal": 30800 | |
}, | |
"peer_pool": { | |
"size": 616, | |
"used": 1, | |
"free": 49, | |
"memtotal": 30800 | |
} | |
} | |
} |
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.
These are the only cache metrics, so I'm not sure if extracting them is necessary.
func (m *MetricSet) Fetch(reporter mb.ReporterV2) error { | ||
// Create a new context for this operation. | ||
ctx := context.Background() |
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.
Same goes here. you can use ReportingMetricSetV2WithContext
.
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.
tmpData, err := schema.Apply(result) | ||
if err != nil { | ||
// Log the error and skip this iteration if schema application fails. | ||
log.Printf("Error applying schema: %v", err) |
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.
BaseMetricSet
should already have logger, please initialize that and use it across module.
if len(errs) > 0 { | ||
t.Fatalf("Expected 0 error, had %d. %v\n", len(errs), errs) | ||
} | ||
assert.NotEmpty(t, events) |
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.
Please refer previous comment and update accordingly.
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 follows the standard design patterns of Metricbeat modules, ensuring consistency with other database modules like PostgreSQL. It implements the MetricSet interface to collect metrics from PgBouncer.
The module interacts with PgBouncer using SQL queries to gather pool statistics and server performance data. The data is parsed and processed through Metricbeat's internal processing pipeline. It communicates with PgBouncer using the native Postgres protocol over TCP. It sends queries to fetch relevant metrics and processes the responses, converting them into Metricbeat-compatible events.
PGBouncer is widely used as a connection pooler for PostgreSQL, and monitoring its performance is crucial for maintaining the health of database-backed systems. By adding this module, Metricbeat provides users with out-of-the-box monitoring capabilities for PGBouncer, enabling them to track metrics such as connection pool utilization, server performance, and query rates. This integration helps users maintain optimal database performance, reduce latency, and prevent resource exhaustion in their systems.
-->
Checklist
CHANGELOG.next.asciidoc
orCHANGELOG-developer.next.asciidoc
.Disruptive User Impact
It shouldn't impact users.
Author's Checklist
How to test this PR locally
localhost:5601
test
pattern and check logs in discover.