-
Notifications
You must be signed in to change notification settings - Fork 6k
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
mgr/dashboard: fix prometheus api issues on landing page v3 #50214
Conversation
1588b27
to
8cba36e
Compare
8cba36e
to
1393a31
Compare
1393a31
to
ef52d00
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.
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:
import { NgModule } from '@angular/core'; | ||
import { CommonModule } from '@angular/common'; | ||
|
||
@NgModule({ | ||
declarations: [], | ||
imports: [CommonModule] | ||
}) | ||
export class HelpersModule {} |
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.
Is this module being used?
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 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.
@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>
ef52d00
to
6cb0679
Compare
|
||
@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 { |
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.
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 })
);
}
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.
BTW the example above is not 100% functiona, the 2nd subscription still needs to check for the Prometheus configured status.
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 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.
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.
@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.
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; | ||
} | ||
}); |
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.
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.
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.
@Pegonzal since you worked the most here I will need your help with this. What do you think about this?
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.
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.
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.
yup, i'll open a separate tracker and will assign it to you,
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.
jenkins test make check |
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
To sign and title your commits, please refer to Submitting Patches to Ceph.
If you are submitting a fix for a stable branch (e.g. "pacific"), please refer to Submitting Patches to Ceph - Backports for the proper workflow.
Checklist
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