|
@@ -1,9 +1,9 @@
|
|
|
import styled from '@emotion/styled';
|
|
|
|
|
|
-import DeprecatedAsyncComponent from 'sentry/components/deprecatedAsyncComponent';
|
|
|
import {t} from 'sentry/locale';
|
|
|
import type {DataCategoryInfo, Organization} from 'sentry/types';
|
|
|
import {Outcome} from 'sentry/types';
|
|
|
+import {useApiQuery} from 'sentry/utils/queryClient';
|
|
|
|
|
|
import type {UsageSeries} from './types';
|
|
|
import {formatUsageWithUnits, getFormatUsageOptions} from './utils';
|
|
@@ -12,11 +12,7 @@ type Props = {
|
|
|
dataCategory: DataCategoryInfo['plural'];
|
|
|
organization: Organization;
|
|
|
projectIds: number[];
|
|
|
-} & DeprecatedAsyncComponent['props'];
|
|
|
-
|
|
|
-type State = {
|
|
|
- orgStats: UsageSeries | undefined;
|
|
|
-} & DeprecatedAsyncComponent['state'];
|
|
|
+};
|
|
|
|
|
|
/**
|
|
|
* Making 1 extra API call to display this number isn't very efficient.
|
|
@@ -28,42 +24,34 @@ type State = {
|
|
|
* We're going with this approach for simplicity sake. By keeping the range
|
|
|
* as small as possible, this call is quite fast.
|
|
|
*/
|
|
|
-class UsageStatsPerMin extends DeprecatedAsyncComponent<Props, State> {
|
|
|
- componentDidUpdate(prevProps: Props) {
|
|
|
- const {projectIds} = this.props;
|
|
|
- if (prevProps.projectIds !== projectIds) {
|
|
|
- this.reloadData();
|
|
|
+function UsageStatsPerMin({dataCategory, organization, projectIds}: Props) {
|
|
|
+ const {
|
|
|
+ data: orgStats,
|
|
|
+ isLoading,
|
|
|
+ isError,
|
|
|
+ } = useApiQuery<UsageSeries>(
|
|
|
+ [
|
|
|
+ `/organizations/${organization.slug}/stats_v2/`,
|
|
|
+ {
|
|
|
+ query: {
|
|
|
+ statsPeriod: '5m', // Any value <1h will return current hour's data
|
|
|
+ interval: '1m',
|
|
|
+ groupBy: ['category', 'outcome'],
|
|
|
+ project: projectIds,
|
|
|
+ field: ['sum(quantity)'],
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ {
|
|
|
+ staleTime: 0,
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- getEndpoints(): ReturnType<DeprecatedAsyncComponent['getEndpoints']> {
|
|
|
- return [['orgStats', this.endpointPath, {query: this.endpointQuery}]];
|
|
|
- }
|
|
|
+ );
|
|
|
|
|
|
- get endpointPath() {
|
|
|
- const {organization} = this.props;
|
|
|
- return `/organizations/${organization.slug}/stats_v2/`;
|
|
|
+ if (isLoading || isError || !orgStats || orgStats.intervals.length === 0) {
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
- get endpointQuery() {
|
|
|
- const {projectIds} = this.props;
|
|
|
- return {
|
|
|
- statsPeriod: '5m', // Any value <1h will return current hour's data
|
|
|
- interval: '1m',
|
|
|
- groupBy: ['category', 'outcome'],
|
|
|
- project: projectIds,
|
|
|
- field: ['sum(quantity)'],
|
|
|
- };
|
|
|
- }
|
|
|
-
|
|
|
- get minuteData(): string | undefined {
|
|
|
- const {dataCategory} = this.props;
|
|
|
- const {loading, error, orgStats} = this.state;
|
|
|
-
|
|
|
- if (loading || error || !orgStats || orgStats.intervals.length === 0) {
|
|
|
- return undefined;
|
|
|
- }
|
|
|
-
|
|
|
+ const minuteData = (): string | undefined => {
|
|
|
// The last minute in the series is still "in progress"
|
|
|
// Read data from 2nd last element for the latest complete minute
|
|
|
const {intervals, groups} = orgStats;
|
|
@@ -86,19 +74,13 @@ class UsageStatsPerMin extends DeprecatedAsyncComponent<Props, State> {
|
|
|
dataCategory,
|
|
|
getFormatUsageOptions(dataCategory)
|
|
|
);
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
- renderComponent() {
|
|
|
- if (!this.minuteData) {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- return (
|
|
|
- <Wrapper>
|
|
|
- {this.minuteData} {t('in last min')}
|
|
|
- </Wrapper>
|
|
|
- );
|
|
|
- }
|
|
|
+ return (
|
|
|
+ <Wrapper>
|
|
|
+ {minuteData()} {t('in last min')}
|
|
|
+ </Wrapper>
|
|
|
+ );
|
|
|
}
|
|
|
|
|
|
export default UsageStatsPerMin;
|