Skip to content

Conversation

wololowarrior
Copy link

@wololowarrior wololowarrior commented Sep 7, 2025

This commit adds functionality to filter metrics by tags in the Service Performance Monitoring (SPM) page.

Which problem is this PR solving?

Description of the changes

How was this change tested?

Checklist

Copy link
Contributor

graphite-app bot commented Sep 7, 2025

How to use the Graphite Merge Queue

Add the label merge-queue to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

@wololowarrior wololowarrior force-pushed the metrics-filtering-using-tags branch from 047cbc8 to 556d48b Compare September 7, 2025 07:08
Copy link
Member

@yurishkuro yurishkuro left a comment

Choose a reason for hiding this comment

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

Make sure to stress test how it looks when all tag drop downs don't fit in one line

@@ -0,0 +1,31 @@
/*
Copyright (c) 2025 The Jaeger Authors.
Copy link
Member

Choose a reason for hiding this comment

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

Use spdx id instead of full header

// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
Copy link
Member

Choose a reason for hiding this comment

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

Use spdx id

@@ -105,6 +105,12 @@ const defaultConfig: Config = {
},
},
docsLink: 'https://www.jaegertracing.io/docs/latest/spm/',
tagFilters: [],
tagAttributes: [
{ name: 'environment', label: 'Environment' },
Copy link
Member

Choose a reason for hiding this comment

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

Non standard, cannot be default

Copy link
Author

@wololowarrior wololowarrior Sep 8, 2025

Choose a reason for hiding this comment

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

Yes, I commited some of the testing values. Will remove

tagAttributes: [
{ name: 'environment', label: 'Environment' },
{ name: 'http.status_code', label: 'HTTP Status' },
{ name: 'http.method', label: 'HTTP Method' },
Copy link
Member

Choose a reason for hiding this comment

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

Default can only be something that will work out if the box. Including http route by default is nice, but how will it work with Prometheus if the label is not exposed?

Copy link
Author

@wololowarrior wololowarrior Sep 8, 2025

Choose a reason for hiding this comment

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

By default, i can see these; the traces are generated using microsim. http.Method isnt there by default in prometheus, it'll require spanmetrics to be configured.

harshil.gupta@harshil jaeger % curl "http://localhost:9090/api/v1/labels" | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   148  100   148    0     0  18642      0 --:--:-- --:--:-- --:--:-- 21142
{
  "status": "success",
  "data": [
    "__name__",
    "exported_job",
    "instance",
    "job",
    "le",
    "otel_scope_name",
    "service_name",
    "span_kind",
    "span_name",
    "status_code"
  ]
}

Copy link
Author

Choose a reason for hiding this comment

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

I can see there is a operation in prometheus by default. Maybe we can include that as default.

labels": [
        {
          "name": "operation",
          "value": "/GetDriver"
        },
        {
          "name": "service_name",
          "value": "redis"
        }
      ],

@@ -71,6 +71,18 @@ export type MonitorConfig = {
menuEnabled?: boolean;
emptyState?: MonitorEmptyStateConfig;
docsLink?: string;
tagFilters?: readonly TagFilter[];
Copy link
Member

Choose a reason for hiding this comment

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

Add documentation to new fields and types

@@ -31,6 +31,7 @@ export type MetricsAPIQueryParams = {
step: number;
ratePer: number;
spanKind: spanKinds;
tag?: string;
Copy link
Member

Choose a reason for hiding this comment

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

Add documentation

}, [valueAsObject]);

// Handle value selection for a specific attribute
const handleValueChange = useCallback((attributeName, selectedValue) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

why useCallback here? the only place it is used is passing it to an unmemoized component in a prop that creates a new function every render anyway.

multiple things would need to change for there to be any perf impact

.map(([key, val]) => `${key}=${val}`)
.join(' ');

onChange(tagString);
Copy link
Contributor

Choose a reason for hiding this comment

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

react requires state updaters to be pure: see docs "Updater functions run during rendering, so updater functions must be pure and only return the result. Don’t try to set state from inside of them or run other side effects"

}, [service, tagAttributes]);

// Update selected values when value prop changes
useEffect(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

but this will clobber any local state changes you make every time the prop changes. you need to either lift all of this state up to the parent or keep state only for changes made at this level and merge local state with valueAsObject in render e..g.,

// somewhere in render
const [localObjChanges, setLocalObjChanges] = useState() // don't attempt to sync state this with parent prop

// takes parent prop and patches local state changes on top in pure way
const selectedValues = mergeFn(valueAsObject, localObjChanges)

@wololowarrior
Copy link
Author

Hey @yurishkuro @mdwyer6 , I truly appreciate you reviewing.
I've used Copilot for most of UI, since I've not worked with UI languages at all, you can let me know what changes are needed. Will try to address other points
I'll add a way to run this feature E2E.

@wololowarrior
Copy link
Author

Make sure to stress test how it looks when all tag drop downs don't fit in one line

@yurishkuro Here's what the stress test looks like
Screenshot 2025-09-09 at 12 12 57 PM
Screenshot 2025-09-09 at 12 13 06 PM

This commit adds functionality to filter metrics by tags in the Service Performance Monitoring (SPM) page.

Signed-off-by: Harshil Gupta <harshilgupta1808@gmail.com>
Signed-off-by: Harshil Gupta <harshilgupta1808@gmail.com>
Signed-off-by: Harshil Gupta <harshilgupta1808@gmail.com>
Signed-off-by: Harshil Gupta <harshilgupta1808@gmail.com>
Signed-off-by: Harshil Gupta <harshilgupta1808@gmail.com>
@wololowarrior wololowarrior force-pushed the metrics-filtering-using-tags branch from 92deeca to 4d21f20 Compare September 9, 2025 07:17
@wololowarrior wololowarrior marked this pull request as ready for review September 11, 2025 09:25
@wololowarrior wololowarrior requested a review from a team as a code owner September 11, 2025 09:25
@wololowarrior wololowarrior requested review from jkowall and removed request for a team September 11, 2025 09:25
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.

3 participants