-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Add metrics Feature #7507
Add metrics Feature #7507
Conversation
…Feature Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
9142744
to
afd64df
Compare
packages/metrics/package.json
Outdated
"name": "@k8slens/metrics", | ||
"private": false, | ||
"version": "6.5.0-alpha.1", | ||
"description": "Code that is common to all Features and those registering them.", |
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.
This should be something about metrics?
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.
good catch, copy-pasta! 😄
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.
fixed
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
@@ -0,0 +1,4 @@ | |||
{ | |||
"extends": "@k8slens/typescript/config/base.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.
Should this be in the dependencies or does it just work?
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.
hmm good question.. no other package imports this but all of them use it... it should probably be a dev dependency for all?
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
@@ -0,0 +1 @@ | |||
module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; |
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.
Should this be in the dependencies or does it just work?
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
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.
Should be added yeah. Hard to remember because they seem to work anyway because of node module resolution and npm
workspaces automatically hoisting dependencies to root of monorepo. If we had something more strict, like pnpm
then it would be easier to remember.
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.
PR #7545 makes it bit more strict to remind us.
); | ||
}); | ||
|
||
const PodDetailsInitContainers = NonInjectedPodDetailsInitContainers; |
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.
No need for 2 components since we're not injecting anything 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.
good catch, fixed
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Adding it here so I'll remember to fix this. There's a new warning in the console when navigating to Cluster overview:
|
@@ -118,5 +121,6 @@ export const ClusterOverview = withInjectables<Dependencies>(NonInjectedClusterO | |||
podStore: di.inject(podStoreInjectable), | |||
eventStore: di.inject(eventStoreInjectable), | |||
nodeStore: di.inject(nodeStoreInjectable), | |||
uiBlocks: di.injectMany(clusterOverviewUIBlockInjectionToken), |
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.
Here we should use computedInjectMany
to make it reactive. Currently it doesn't refresh if new implementation for clusterOverviewUIBlockInjectionToken
is registered in runtime. (or deregistered).
This works at the moment because registration of the Feature is happening before anything is rendered, but it's good practice to always support runtime registrations (less work in the future when we enable possibility to register Features through runtime extensions)
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.
good call, fixed
packages/metrics/index.ts
Outdated
export type ClusterOverviewUIBlock = { | ||
id: string; | ||
Component: React.ElementType; | ||
orderNumber: number; | ||
}; | ||
|
||
export const clusterOverviewUIBlockInjectionToken = getInjectionToken<ClusterOverviewUIBlock>({ | ||
id: "cluster-overview-ui-block-injection-token", | ||
}); |
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 me, it seems that these do not belong here. Maybe add a comment to remind that these should be moved under cluster-overview
feature whenever it emerges.
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 a comment here
export const podDetailsMetricsInjectionToken = getInjectionToken<KubeObjectDetailMetrics>({ | ||
id: "pod-details-metrics-injection-token", | ||
}); | ||
|
||
export const deploymentDetailsMetricsInjectionToken = getInjectionToken<KubeObjectDetailMetrics>({ | ||
id: "deployment-details-metrics-injection-token", | ||
}); | ||
|
||
export const nodeDetailsMetricsInjectionToken = getInjectionToken<KubeObjectDetailMetrics>({ | ||
id: "node-details-metrics-injection-token", | ||
}); | ||
|
||
export const replicaSetDetailsMetricsInjectionToken = getInjectionToken<KubeObjectDetailMetrics>({ | ||
id: "replica-set-details-metrics-injection-token", | ||
}); | ||
|
||
export const persistentVolumeClaimDetailsMetricsInjectionToken = getInjectionToken<KubeObjectDetailMetrics>({ | ||
id: "persistent-volume-claim-details-metrics-injection-token", | ||
}); | ||
|
||
export const statefulSetDetailsMetricsInjectionToken = getInjectionToken<KubeObjectDetailMetrics>({ | ||
id: "stateful-set-details-metrics-injection-token", | ||
}); | ||
|
||
export const namespaceDetailsMetricsInjectionToken = getInjectionToken<KubeObjectDetailMetrics>({ |
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 it possible to make all of these bit more generic, so that we don't need multiple injectionToken
s for same kind of stuff?
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 it's useful to have separate tokens for each resource type. Maybe someone wants to implement metrics just for one resource but not all?
We don't implement metrics for all resource types ourselves. The other thing is that core
decides the placement of the metrics (at least for now), for example Pod
details have both Pod
metrics and Container
metrics where Pod metrics are on top of the details and Container lower in the middle of the details component.
const metrics = di.injectMany(token); | ||
const first = metrics[0]; | ||
|
||
const Component = first?.Component ?? EmptyMetrics; |
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.
This doesn't seem right. If we expect that there's only one item, then we should use di.inject
instead of injectMany
, but in this case, I think that the correct solution would be to prepare for the fact that there's multiple implementations and render all of them.
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've changed this to use computedMany
@@ -0,0 +1,24 @@ | |||
/** |
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.
In general, the guideline should be that the core
doesn't know anything about metrics
, therefore the fact that metrics
exports *MetricsInjectionToken
seems bit odd.
It would make more sense if the kubeObjectDetailItemInjectionToken
would be extracted to package and then all of these implementations could also be moved.
Might be that you have already thought it, but it cascaded to something too big?
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 it was deemed to be a too big of an effort right now to move the implementations into a package. It was decided that the old implementations would stay in the core
because they are too entangled and the benefit of moving is not that big. We want to make these metrics replaceable but not totally remove them from the core at this point.
Added some comments. Looking good. |
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
can't reproduce this anymore, maybe fixed by merging master / changing overview ui blocks to computed value |
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
@@ -58,5 +73,6 @@ export const metricsFeature = getFeature({ | |||
|
|||
di.register(podDetailsMetricsInjectable); | |||
di.register(podDetailsContainerMetricsInjectable); | |||
di.register(deploymentDetailsMetricsInjectable); |
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.
No action required, this is also possible:
di.register(
clusterPieChartsClusterOverviewInjectable,
clusterMetricsOverviewBlockInjectable,
makeMargaritasInjectable,
itPutsTheLotionInTheBasketInjectable
);
instantiate: (di) => { | ||
const podMetrics = di.injectMany(podDetailsMetricsInjectionToken); | ||
const first = podMetrics[0]; | ||
|
||
const Component = first ?? Empty; | ||
const Component = first?.Component ?? EmptyMetrics; |
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.
Could we instead register EmptyMetrics
as implementation of podDetailsMetricsInjectionToken
when there's nothing better around?
|
||
type GetMetricsKubeObjectDetailItem = (token: InjectionToken<KubeObjectDetailMetrics, void>, metricResourceType: ClusterMetricsResourceType) => KubeObjectDetailItem; | ||
|
||
export const getMetricsKubeObjectDetailItemInjectable = getInjectable({ |
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.
Does this have to be a factory function? Eg. instead of getMetricsKubeObjectDetailItemInjectable
, could it be metricsKubeObjectDetailItemInjectable
, and receive metricResourceType
as its key as keyedSingleton
?
@@ -121,6 +122,6 @@ export const ClusterOverview = withInjectables<Dependencies>(NonInjectedClusterO | |||
podStore: di.inject(podStoreInjectable), | |||
eventStore: di.inject(eventStoreInjectable), | |||
nodeStore: di.inject(nodeStoreInjectable), | |||
uiBlocks: di.injectMany(clusterOverviewUIBlockInjectionToken), | |||
uiBlocks: di.inject(computedInjectManyInjectable)(clusterOverviewUIBlockInjectionToken), |
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.
Shout if you want di.computedInjectMany(...)
...
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.
That'd be useful!
This PR moves the current metrics implementation to a feature inside
packages/core
and introduces a new package@k8slens/metrics
which exposesinjectionTokens
for implementing metrics features.This PR has tokens for following metrics:
Metrics from the
core
can be included with one line of code inopen-lens
,registerFeature(metricsFeature)
. Without registering the feature, Lens will not render metrics where thoseinjectionTokens
are used.Resolves #7506