Skip to content

Conversation

@charliepark
Copy link
Contributor

@charliepark charliepark commented Jan 27, 2024

Fixes #1866.

We're pulling in data for the instance page's metrics tab, showing read / write counts and size, and the number of flushes. Currently, we aren't adjusting the numbers, and are just showing the raw count / bytes.

This PR updates how we render the data. Because the data is cumulative, we can use the largest data value to determine the unit of measurement for the set of data. We then divide the given datapoint by the appropriate divisor and pass that data along to the chart.

I'm open to suggestions for better ways to label the overall chart.

While it's fine on datapoints using Byte counts …
Screenshot 2024-01-26 at 3 36 21 PM

… it's a little meh on Count charts …
Screenshot 2024-01-26 at 4 27 08 PM
(The thing you're supposed to be looking at is at the very top of the chart, currently showing "count x K".)

@benjaminleonard if you have any thoughts, I'm all ears.

I'm also open to extracting this into a utility function, if we think it'll be useful in other places.

@vercel
Copy link

vercel bot commented Jan 27, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
console ✅ Ready (Inspect) Visit Preview Jan 30, 2024 4:46am

@benjaminleonard
Copy link
Contributor

Byte counts look good – wondering if for the counts we show the full number in the tooltip and use K in the axis. And just stick with "Writes (Count)"?

Took me a second to realise K wasn't a unit. Lowercase K with no space between it and the number will likely help too.

@charliepark
Copy link
Contributor Author

In the latest commit I pulled in @benjaminleonard's suggestions for that Y-Axis labeling vs. popup number.
Screenshot 2024-01-29 at 1 04 53 PM
Screenshot 2024-01-29 at 1 06 00 PM

@benjaminleonard
Copy link
Contributor

Wondering if there's some logic we can write, something like a find comfortable axis function – that given a range and a number of desired steps quantises to multiples. In this case we'd say snap to 0.5k and it'd give us 7 steps up to 3.5k.

We have a similar issue with the KiB / MiB / GiB where they aren't universally divisible in a neat way.

Not to blow up the complexity of this PR. You could merge this and we could tackle in a follow up.

@david-crespo
Copy link
Collaborator

Yeah, I was thinking that is the main outstanding issue here — would be much nicer if those were round numbers. I will think about it a bit.

@benjaminleonard
Copy link
Contributor

Actual implementation requires some experimentation to get something more robust, but in the realm of this might work:

function findAxis(range: number, targetSteps: number, snap: number): number[] {
    let stepSize = Math.ceil((range / targetSteps) / snap) * snap;
    let steps = Math.ceil(range / stepSize);

    let axis: number[] = [];
    for(let i = 0; i <= steps; i++) {
        axis.push(i * stepSize);
    }

    return axis;
}

console.log(findAxis(3.3, 7, 0.5));
// [0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5]
console.log(findAxis(10, 6, 0.5));
// [0, 2, 4, 6, 8, 10]

}
}

const divisor = divisorBase ^ cycleCount

This comment was marked as resolved.

@david-crespo
Copy link
Collaborator

So.. we are already doing work to get clean round numbers for the ticks. We pick a maxY that's divisible by the number of ticks, and then we get ticks evenly spaced out between 0 and maxY.

// We use the largest data point +20% for the graph scale. !rawData doesn't
// mean it's empty (it will never be empty because we fill in artificial 0s at
// beginning and end), it means the metrics requests haven't come back yet
const maxY = useMemo(() => {
if (!rawData) return null
const dataMax = Math.max(...rawData.map((datum) => datum.value))
return roundUpToDivBy(dataMax * 1.2, TICK_COUNT) // avoid uneven ticks
}, [rawData])
// If max value is set we normalize the graph so that
// is the maximum, we also use our own function as recharts
// doesn't fill the whole domain (just up to the data max)
const yTicks = maxY
? { domain: [0, maxY], ticks: getVerticalTicks(TICK_COUNT, maxY) }
: undefined

function getVerticalTicks(n: number, max: number): number[] {
const idxs = new Array(n).fill(0)
return idxs.map((_, i) => Math.floor(((i + 1) / n) * max))
}

So I think all we need to do to avoid the decimals is pass TICK_COUNT * <relevant power of 10> to roundUpToDivBy. The hard bit is figuring out the power of 10. Or it would be if you hadn't already done it — that's what divisor is. If I pass in divisor to TimeSeriesChart and do this roundUpToDivBy(dataMax * 1.2, TICK_COUNT * divisor) (and turn the toFixed(2) into toFixed(0) in yAxisTickFormatter) I am able to get the following:

image

That confirms I'm thinking about this roughly the right way. However, the bytes numbers are pre-divided while the counts are not, and this messes up the bytes charts, which don't want their axis multiplied by 1024:

image

So I'll need to figure out how to reconcile this.

@david-crespo
Copy link
Collaborator

david-crespo commented Jan 30, 2024

Not sure how this happens (we should look into it) but it seems we cannot assume these numbers are monotonically increasing and therefore the last value is the largest.

https://oxide.sys.rack2.eng.oxide.computer/projects/trey-trey-trey/instances/apache/metrics
https://oxide.sys.rack2.eng.oxide.computer/projects/trey-trey-trey/instances/foo/metrics

image

@david-crespo
Copy link
Collaborator

I think that's this: oxidecomputer/omicron#1624

I knew it sounded familiar.

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

license-eye has totally checked 467 files.

Valid Invalid Ignored Fixed
414 1 52 0
Click to see the invalid file list
  • app/pages/project/instances/instance/tabs/MetricsTab.spec.ts

@david-crespo
Copy link
Collaborator

While we could improve this, it's clearly an improvement on what's there and works well with big numbers (tested by changing the fake data generator). I want to wrap up #1910 for the release, so I am good with merging this and fixing it up later.

Screenshot 2024-01-29 at 10 55 32 PM

Screenshot 2024-01-29 at 10 55 38 PM

const largestValue = useMemo(() => {
if (!metrics || metrics.items.length === 0) return 0
return Math.max(...metrics.items.map((m) => (m.datum.datum as Cumulativeint64).value))
}, [metrics])
Copy link
Collaborator

Choose a reason for hiding this comment

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

I fixed the last value not necessarily being the largest by looking at all values and finding the max. I always feel weird about spreading 3000 args into Math.max but I tested it a while ago (we do this elsewhere) and it is apparently fine.

@charliepark
Copy link
Contributor Author

There are a few more enhancements we've talked about in chat, but we'll merge this PR and then decide on prioritization and path forward on general metrics improvements separately.

@charliepark charliepark merged commit 5cf4339 into main Jan 30, 2024
@charliepark charliepark deleted the improve-disk-metrics-numbers branch January 30, 2024 17:33
david-crespo added a commit to oxidecomputer/omicron that referenced this pull request Jan 31, 2024
oxidecomputer/console@b9013a3...1a4f5d8

* [1a4f5d81](oxidecomputer/console@1a4f5d81) oxidecomputer/console#1910
* [34596e33](oxidecomputer/console@34596e33) oxidecomputer/console#1928
* [ff7cdb28](oxidecomputer/console@ff7cdb28) oxidecomputer/console#1926
* [efa39789](oxidecomputer/console@efa39789) oxidecomputer/console#1867
* [4bfadc02](oxidecomputer/console@4bfadc02) oxidecomputer/console#1927
* [695d3671](oxidecomputer/console@695d3671) oxidecomputer/console#1925
* [30070292](oxidecomputer/console@30070292) better path filter for local files in msw handler
* [5cf4339c](oxidecomputer/console@5cf4339c) oxidecomputer/console#1916
* [a26f7c1e](oxidecomputer/console@a26f7c1e) oxidecomputer/console#1922
* [231b93ed](oxidecomputer/console@231b93ed) oxidecomputer/console#1923
* [c8364638](oxidecomputer/console@c8364638) better msw warning filter so we don't get warning noise in console
* [764f7310](oxidecomputer/console@764f7310) oxidecomputer/console#1908
* [945619eb](oxidecomputer/console@945619eb) oxidecomputer/console#1921
* [e2d82a4c](oxidecomputer/console@e2d82a4c) oxidecomputer/console#1887
* [d6a67bd5](oxidecomputer/console@d6a67bd5) oxidecomputer/console#1918
* [1fb746f4](oxidecomputer/console@1fb746f4) oxidecomputer/console#1899
* [ca7c85de](oxidecomputer/console@ca7c85de) oxidecomputer/console#1917
* [28598e1d](oxidecomputer/console@28598e1d) oxidecomputer/console#1914
* [34eb478d](oxidecomputer/console@34eb478d) oxidecomputer/console#1912
* [4d693088](oxidecomputer/console@4d693088) bump vite-plugin-html to stop getting deprecation warning
* [d5c39549](oxidecomputer/console@d5c39549) oxidecomputer/console#1909
* [7c6f53db](oxidecomputer/console@7c6f53db) oxidecomputer/console#1854
david-crespo added a commit to oxidecomputer/omicron that referenced this pull request Jan 31, 2024
oxidecomputer/console@b9013a3...1a4f5d8

* [1a4f5d81](oxidecomputer/console@1a4f5d81)
oxidecomputer/console#1910
* [34596e33](oxidecomputer/console@34596e33)
oxidecomputer/console#1928
* [ff7cdb28](oxidecomputer/console@ff7cdb28)
oxidecomputer/console#1926
* [efa39789](oxidecomputer/console@efa39789)
oxidecomputer/console#1867
* [4bfadc02](oxidecomputer/console@4bfadc02)
oxidecomputer/console#1927
* [695d3671](oxidecomputer/console@695d3671)
oxidecomputer/console#1925
* [30070292](oxidecomputer/console@30070292)
better path filter for local files in msw handler
* [5cf4339c](oxidecomputer/console@5cf4339c)
oxidecomputer/console#1916
* [a26f7c1e](oxidecomputer/console@a26f7c1e)
oxidecomputer/console#1922
* [231b93ed](oxidecomputer/console@231b93ed)
oxidecomputer/console#1923
* [c8364638](oxidecomputer/console@c8364638)
better msw warning filter so we don't get warning noise in console
* [764f7310](oxidecomputer/console@764f7310)
oxidecomputer/console#1908
* [945619eb](oxidecomputer/console@945619eb)
oxidecomputer/console#1921
* [e2d82a4c](oxidecomputer/console@e2d82a4c)
oxidecomputer/console#1887
* [d6a67bd5](oxidecomputer/console@d6a67bd5)
oxidecomputer/console#1918
* [1fb746f4](oxidecomputer/console@1fb746f4)
oxidecomputer/console#1899
* [ca7c85de](oxidecomputer/console@ca7c85de)
oxidecomputer/console#1917
* [28598e1d](oxidecomputer/console@28598e1d)
oxidecomputer/console#1914
* [34eb478d](oxidecomputer/console@34eb478d)
oxidecomputer/console#1912
* [4d693088](oxidecomputer/console@4d693088)
bump vite-plugin-html to stop getting deprecation warning
* [d5c39549](oxidecomputer/console@d5c39549)
oxidecomputer/console#1909
* [7c6f53db](oxidecomputer/console@7c6f53db)
oxidecomputer/console#1854
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.

Instance disk metrics should not be displayed in bytes

4 participants