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

mgr/dashboard: fix prometheus api issues on landing page v3 #50214

Merged
merged 2 commits into from
Mar 15, 2023

Conversation

nizamial09
Copy link
Member

When no prometheus is configured in the cluster, it gives out error
while polling to the prometheus endpoint. so a proper check needs to be
added there.

only fetch the alerts when you toggle the alert viewer. don't fetch it
every 5 second cause its going to cause a heavy toll on the api.

Contribution Guidelines

Checklist

  • Tracker (select at least one)
    • References tracker ticket
    • Very recent bug; references commit where it was introduced
    • New feature (ticket optional)
    • Doc update (no ticket needed)
    • Code cleanup (no ticket needed)
  • Component impact
    • Affects Dashboard, opened tracker ticket
    • Affects Orchestrator, opened tracker ticket
    • No impact that needs to be tracked
  • Documentation (select at least one)
    • Updates relevant documentation
    • No doc update is appropriate
  • Tests (select at least one)
Show available Jenkins commands
  • jenkins retest this please
  • jenkins test classic perf
  • jenkins test crimson perf
  • jenkins test signed
  • jenkins test make check
  • jenkins test make check arm64
  • jenkins test submodules
  • jenkins test dashboard
  • jenkins test dashboard cephadm
  • jenkins test api
  • jenkins test docs
  • jenkins render docs
  • jenkins test ceph-volume all
  • jenkins test ceph-volume tox
  • jenkins test windows

Copy link
Contributor

@Pegonzal Pegonzal left a comment

Choose a reason for hiding this comment

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

LGTM @nizamial09 !

Thanks for taking care of it.

Just a couple of minr things:

On the first time opening the page the alerts get mixed up after a short period of tyme of them loading:

image

Comment on lines +1 to +8
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

@NgModule({
declarations: [],
imports: [CommonModule]
})
export class HelpersModule {}
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this module being used?

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 couldn't find a place to put the prometheus-helpers anywhere so i created this helper module to put the prometheus-list-helper class inside. Although we are not directly accessing the module, the prometheus-list-helper gets extended to the DashboardComponent and couple of others as well.

@nizamial09
Copy link
Member Author

On the first time opening the page the alerts get mixed up after a short period of tyme of them loading

@Pegonzal i have not seen this in mine. checked a couple of time but couldn't reproduce. is this recurring for you?

@Pegonzal
Copy link
Contributor

On the first time opening the page the alerts get mixed up after a short period of tyme of them loading

@Pegonzal i have not seen this in mine. checked a couple of time but couldn't reproduce. is this recurring for you?

@nizamial09 this was happening to me when first opening the page but only once, and it would get fixed after a few seconds when all of the alerts had properly loaded, or so it semeed, so it is nothing to worry about, just wanted to mention it in case it it was part of another bigger issue, but I didn't find anything else

When no prometheus is configured in the cluster, it gives out error
while polling to the prometheus endpoint. so a proper check needs to be
added there.

Also some improvements to the exisiting behaviour

Fixes: https://tracker.ceph.com/issues/58867
Signed-off-by: Nizamudeen A <nia@redhat.com>
only fetch the alerts when you toggle the alert viewer. don't fetch it
every 5 second cause its going to cause a heavy toll on the api.

Fixes: https://tracker.ceph.com/issues/58867
Signed-off-by: Nizamudeen A <nia@redhat.com>

@Component({
selector: 'cd-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent implements OnInit, OnDestroy {
export class DashboardComponent extends PrometheusListHelper implements OnInit, OnDestroy {
Copy link
Member

Choose a reason for hiding this comment

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

First of all, I really love when I see some OOP stuff going on. That said, DashboardComponent is an Angular Component, and PrometheusHelper is an Angular Directive (with no selector, so it can't be used as Directive either) and which inherits from ListWithDetails, which in turn brings properties like expandedRow or tableStatus...

I think this is a bit messy inheritance model...

What do you want from PrometheusHelper? Some way to run code based on the online status of a backend component... For that, in some places we're using Status Guards (hooks in the Angular routing lifecycle to enable/activate pages based on conditions). However, that doesn't fit here.

So part of the issue is that we have to consume 2 service methods:

  • IsPrometheusConfigured(): this offloads the internal state of the service to the consumer component, which is not polite (consumers shouldn't have to worry about the internal state of anything else that themselves')
  • getPrometheusData()

If a devel just want to fetch Prometheus data, why forcing them to first check if Prometheus is configured? Let's follow the Python "better ask for forgiveness..." and detect that condition, either during the service instantiation or during the service method:

@Injectable({
  providedIn: 'root'
})
export class PrometheusService {
  private baseURL = 'api/prometheus';
  private settingsKey = { 
    alertmanager: 'api/settings/alertmanager-api-host',
    prometheus: 'api/settings/prometheus-api-host'
  };
  
  isPrometheusConfigured = false;  

  constructor(private http: HttpClient, private settingsService: SettingsService) 
  {
      this.isPrometheusConfigured$ = this.prometheusService.ifPrometheusConfigured().share();
  }

  getPrometheusData(params: any): any {
    return concat(
      this.isPrometheusConfigured$,
      this.http.get<any>(`${this.baseURL}/data`, { params })
    );
  }

Copy link
Member

Choose a reason for hiding this comment

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

BTW the example above is not 100% functiona, the 2nd subscription still needs to check for the Prometheus configured status.

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 prometheus-list.helper was already there but it was only accessible to prometheus component. So what i did is to move that component to shared. I'll refactor this code, and it'll be affecting several other components. i'll check it.

Copy link
Member Author

Choose a reason for hiding this comment

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

@epuertat for some days I've been trying this and i couldn't fully convert the existing behaviour. The original ifPrometheusConfigured() function doesn't returns a subscribable object. but even after making the changes that is needed to make it subscribable it doesn't work as it is before.

Comment on lines +171 to +202
this.prometheusService.ifPrometheusConfigured(() => {
if (this.timerGetPrometheusDataSub) {
this.timerGetPrometheusDataSub.unsubscribe();
}
this.timerGetPrometheusDataSub = timer(0, this.timerTime).subscribe(() => {
selectedTime = this.updateTimeStamp(selectedTime);

for (const queryName in queries) {
if (queries.hasOwnProperty(queryName)) {
const query = queries[queryName];
let interval = selectedTime.step;

if (query.includes('rate') && selectedTime.step < 20) {
interval = 20;
} else if (query.includes('rate')) {
interval = selectedTime.step * 2;
}

const intervalAdjustedQuery = query.replace(/\[(.*?)\]/g, `[${interval}s]`);

this.prometheusService
.getPrometheusData({
params: intervalAdjustedQuery,
start: selectedTime['start'],
end: selectedTime['end'],
step: selectedTime['step']
})
.subscribe((data: any) => {
if (data.result.length) {
this.queriesResults[queryName] = data.result[0].values;
}
});
Copy link
Member

Choose a reason for hiding this comment

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

Most of this code is unrelated to the Dashboard presentation and rather about processing Prometheus data, so why not having this encapsulated in the proper Prometheus service?

Not sure how 'customized' the queries are, but if they are simple queries, we could try and perhaps fetch multiple timeseries in a single query.

Copy link
Member Author

Choose a reason for hiding this comment

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

@Pegonzal since you worked the most here I will need your help with this. What do you think about this?

Copy link
Contributor

Choose a reason for hiding this comment

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

Most of this code is unrelated to the Dashboard presentation and rather about processing Prometheus data, so why not having this encapsulated in the proper Prometheus service?

I could look into cleaning it up a bit, and refactor it into the prometheus service.

Not sure how 'customized' the queries are, but if they are simple queries, we could try and perhaps fetch multiple timeseries in a single query.

I was looking into it and it might work, thanks Ernesto. I'll try to have them all together into one query to optimize it.

If you want @nizamial09 we can create a tracker and I'll take care of it, on a separate PR.

Copy link
Member Author

Choose a reason for hiding this comment

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

yup, i'll open a separate tracker and will assign it to you,

Copy link
Member Author

Choose a reason for hiding this comment

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

@nizamial09
Copy link
Member Author

jenkins test make check

@nizamial09 nizamial09 merged commit 4ca0190 into ceph:main Mar 15, 2023
@nizamial09 nizamial09 deleted the landing-page-prom-error-fix branch March 15, 2023 06:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants