Skip to content

add low memory metric to abstract server #3288

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

Merged
merged 8 commits into from
May 1, 2023

Conversation

EdColeman
Copy link
Contributor

Adds metric to detect low memory conditions

  • metric added to AbstractServer so all processes inherit the reporting of the value.
  • includes minor ide checkstyle suggested fixes to tests.

@EdColeman EdColeman requested a review from dlmarion April 11, 2023 00:00
@EdColeman
Copy link
Contributor Author

Fixes issue #3243

Copy link
Contributor

@dlmarion dlmarion left a comment

Choose a reason for hiding this comment

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

This looks good, I'm glad that you added the new metric to one of the tests. I think you will also need to add the metric to the collection of unreported metrics in MetricsIT. Also, all of the classes that subclass AbstractServer (TabletServer, Manager, etc) call MetricsUtil.initializeProducers. I have not looked to see if there is an issue with calling it twice in the same process. I was originally thinking that in the subclasses of AbstractServer, we would just add this class as another producer to the list instead of calling it here too. Have you evaluated that already?

public void registerMetrics(MeterRegistry registry) {
lowMemoryMetricGuage =
Gauge
.builder(METRICS_APP_PREFIX + applicationName + "." + hostname + "."
Copy link
Contributor

@ddanielr ddanielr Apr 11, 2023

Choose a reason for hiding this comment

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

I'm not super familiar with Micrometer, but the way this is currently implemented, wouldn't
the metrics be created in the following structure?
accumulo.app.app1.server1.detected.low.memory = 1|0
accumulo.app.app1.server2.detected.low.memory = 1|0
accumulo.app.app2.server1.detected.low.memory = 1|0

I'm pretty sure these would all be considered unique metrics.

Does Micrometer support tags or metric labels?
If the application name and host name were added as tags on the metric, then the metric would look like
accumulo.app.detected.low.memory{"application Name": "app1", "hostname": "server1"} = 1|0

This drops the unique metric definition down to accumulo.app.detected.low.memory and allows sorting and filtering based on application name or hostname.

Alerting still works by firing on accumulo.app.detected.low.memory =1 but better granularity is allowed on the visualization and alerting ends.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There are tags - I'm trying to confirm that they are being set correctly as I look at Dave's other comments.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree, I think we want something like accumulo.server.detected.low.memory and the application name should be in a tag.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Leveraged tags in 674a9da

@ctubbsii ctubbsii linked an issue Apr 11, 2023 that may be closed by this pull request
@@ -602,7 +602,7 @@ public void run() {
LOG.error("Error initializing metrics, metrics will not be emitted.", e1);
}
pausedMetrics = new PausedCompactionMetrics();
MetricsUtil.initializeProducers(this, pausedMetrics);
initServerMetrics(pausedMetrics);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this was dropped accidentally. Compactor implements MetricsProducer too, so it's registerMetrics method is not getting called.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed in 49b93b3

processMetrics.registerMetrics(registry);
}

public void initServerMetrics(MetricsProducer... producers) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this method is necessary, and it's initializing the metrics for AbstractServer differently than everything else. Since you have modified AbstractServer to implement MetricsProducer, then:

  1. You should have any subclasses of AbstractServer call super.registerMetrics in their respective registerMetrics method. For example, Compactor.registerMetrics.
  2. You should pass this in subclasses of AbstractServer in the call to MetricsUtil.initializeProducers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dlmarion What do you think is easier to understand? Classes that extended abstract server must call super.registerMetrics or call a method 'initServerMetrics' ? Either way requires something that may not be obvious.

Because of the tagging, the registration / initialization needs to occur in the run method - and after certain things have been initialized (host and port)

I'm not thrilled with either approach, but went with a specific initServerMetrics method - if relying on calling super.registerMetrics' and the needing to call the static MetricsUtil.initializeProducerswhich results in an indirect call toregisterMetrics`?

I was thinking about moving the static initializeMetrics out of MetricsUtil and put the functionality into AbstractServer - I think that functionality only applies to services extending AbstractServer.

The initializeProducers functionality needs to exist to register metrics producers for things that are created outside of the AbstarctServer context (thrift metrics, cache,....) - but those are created / exist within a service context that has already been expected to initialize the registry.

Copy link
Contributor

Choose a reason for hiding this comment

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

@dlmarion What do you think is easier to understand? Classes that extended abstract server must call super.registerMetrics or call a method 'initServerMetrics' ? Either way requires something that may not be obvious.

With Java, I think it's standard practice, or should be, for developers to evaluate whether or not the superclass method needs to be called when overriding a method.

Because of the tagging, the registration / initialization needs to occur in the run method - and after certain things have been initialized (host and port)

agreed

I'm not thrilled with either approach, but went with a specific initServerMetrics method - if relying on calling super.registerMetrics' and the needing to call the static MetricsUtil.initializeProducerswhich results in an indirect call toregisterMetrics`?

I was thinking about moving the static initializeMetrics out of MetricsUtil and put the functionality into AbstractServer - I think that functionality only applies to services extending AbstractServer.

I think that might be fine iff only AbstractServer subclasses call that method.

The initializeProducers functionality needs to exist to register metrics producers for things that are created outside of the AbstarctServer context (thrift metrics, cache,....) - but those are created / exist within a service context that has already been expected to initialize the registry.

agreed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 49b93b3 - backed of removal of MetricsUtil for now to minimize changes. May look into additional changes in future PRs, but this code works as expected.

@EdColeman
Copy link
Contributor Author

@dlmarion can you see if 49b93b3 contains the changes you requested? Or do you think there should be additional improvements?

@dlmarion
Copy link
Contributor

I think with these changes overall, all subclasses of AbstractServer need to call MetricsUtil.initializeProducers, passing in this at a minimum. I think that CompactionCoordinator is missing this.

@EdColeman EdColeman merged commit c0586be into apache:main May 1, 2023
@EdColeman EdColeman deleted the 3243_add_low_memory_metric branch May 1, 2023 18:37
@ctubbsii ctubbsii added this to the 3.0.0 milestone Jul 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Metrics: Emit metric when server is low on memory
4 participants