123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- import {useEffect} from 'react';
- import * as Sentry from '@sentry/react';
- import {defined} from 'sentry/utils';
- import {trackAnalytics} from 'sentry/utils/analytics';
- import {dedupeArray} from 'sentry/utils/dedupeArray';
- import {DiscoverDatasets} from 'sentry/utils/discover/types';
- import {MutableSearch} from 'sentry/utils/tokenizeSearch';
- import useOrganization from 'sentry/utils/useOrganization';
- import {
- useExploreDataset,
- useExploreFields,
- useExploreQuery,
- useExploreTitle,
- useExploreVisualizes,
- } from 'sentry/views/explore/contexts/pageParamsContext';
- import type {Visualize} from 'sentry/views/explore/contexts/pageParamsContext/visualizes';
- import type {AggregatesTableResult} from 'sentry/views/explore/hooks/useExploreAggregatesTable';
- import type {SpansTableResult} from 'sentry/views/explore/hooks/useExploreSpansTable';
- import type {TracesTableResult} from 'sentry/views/explore/hooks/useExploreTracesTable';
- import type {ReadableExploreQueryParts} from 'sentry/views/explore/multiQueryMode/locationUtils';
- import {combineConfidenceForSeries} from 'sentry/views/explore/utils';
- import type {useSortedTimeSeries} from 'sentry/views/insights/common/queries/useSortedTimeSeries';
- import {usePerformanceSubscriptionDetails} from 'sentry/views/performance/newTraceDetails/traceTypeWarnings/usePerformanceSubscriptionDetails';
- const {info, fmt} = Sentry._experiment_log;
- export function useTrackAnalytics({
- queryType,
- aggregatesTableResult,
- spansTableResult,
- tracesTableResult,
- timeseriesResult,
- dataset,
- title,
- query,
- fields,
- visualizes,
- page_source,
- }: {
- aggregatesTableResult: AggregatesTableResult;
- dataset: DiscoverDatasets;
- fields: string[];
- page_source: 'explore' | 'compare';
- query: string;
- queryType: 'aggregate' | 'samples' | 'traces';
- spansTableResult: SpansTableResult;
- timeseriesResult: ReturnType<typeof useSortedTimeSeries>;
- visualizes: Visualize[];
- title?: string;
- tracesTableResult?: TracesTableResult;
- }) {
- const organization = useOrganization();
- const {
- data: {hasExceededPerformanceUsageLimit},
- isLoading: isLoadingSubscriptionDetails,
- } = usePerformanceSubscriptionDetails();
- const tableError =
- queryType === 'aggregate'
- ? (aggregatesTableResult.result.error?.message ?? '')
- : queryType === 'traces'
- ? (tracesTableResult?.result.error?.message ?? '')
- : (spansTableResult.result.error?.message ?? '');
- const chartError = timeseriesResult.error?.message ?? '';
- const query_status = tableError || chartError ? 'error' : 'success';
- useEffect(() => {
- if (
- queryType !== 'aggregate' ||
- aggregatesTableResult.result.isPending ||
- timeseriesResult.isPending ||
- isLoadingSubscriptionDetails
- ) {
- return;
- }
- const search = new MutableSearch(query);
- const columns = aggregatesTableResult.eventView.getColumns() as unknown as string[];
- trackAnalytics('trace.explorer.metadata', {
- organization,
- dataset,
- result_mode: 'aggregates',
- columns,
- columns_count: columns.length,
- query_status,
- result_length: aggregatesTableResult.result.data?.length || 0,
- result_missing_root: 0,
- user_queries: search.formatString(),
- user_queries_count: search.tokens.length,
- visualizes: visualizes.map(visualize => ({
- chartType: visualize.chartType,
- yAxes: visualize.yAxes,
- })),
- visualizes_count: visualizes.length,
- title: title || '',
- confidences: computeConfidence(visualizes, timeseriesResult.data),
- has_exceeded_performance_usage_limit: hasExceededPerformanceUsageLimit,
- page_source,
- });
- info(
- fmt`trace.explorer.metadata:
- organization: ${organization.slug}
- dataset: ${dataset}
- query: [omitted]
- visualizes: ${visualizes.map(v => v.chartType).join(', ')}
- title: ${title || ''}
- queryType: ${queryType}
- result_length: ${String(aggregatesTableResult.result.data?.length || 0)}
- user_queries: ${search.formatString()}
- user_queries_count: ${String(String(search.tokens).length)}
- visualizes_count: ${String(String(visualizes).length)}
- has_exceeded_performance_usage_limit: ${String(hasExceededPerformanceUsageLimit)}
- page_source: ${page_source}
- `,
- {isAnalytics: true}
- );
- }, [
- organization,
- dataset,
- fields,
- query,
- visualizes,
- title,
- queryType,
- aggregatesTableResult.result.isPending,
- aggregatesTableResult.result.status,
- aggregatesTableResult.result.data?.length,
- aggregatesTableResult.eventView,
- timeseriesResult.isPending,
- timeseriesResult.data,
- hasExceededPerformanceUsageLimit,
- isLoadingSubscriptionDetails,
- query_status,
- page_source,
- ]);
- useEffect(() => {
- if (
- queryType !== 'samples' ||
- spansTableResult.result.isPending ||
- timeseriesResult.isPending ||
- isLoadingSubscriptionDetails
- ) {
- return;
- }
- const search = new MutableSearch(query);
- trackAnalytics('trace.explorer.metadata', {
- organization,
- dataset,
- result_mode: 'span samples',
- columns: fields,
- columns_count: fields.length,
- query_status,
- result_length: spansTableResult.result.data?.length || 0,
- result_missing_root: 0,
- user_queries: search.formatString(),
- user_queries_count: search.tokens.length,
- visualizes,
- visualizes_count: visualizes.length,
- title: title || '',
- confidences: computeConfidence(visualizes, timeseriesResult.data),
- has_exceeded_performance_usage_limit: hasExceededPerformanceUsageLimit,
- page_source,
- });
- info(fmt`trace.explorer.metadata:
- organization: ${organization.slug}
- dataset: ${dataset}
- query: ${query}
- visualizes: ${visualizes.map(v => v.chartType).join(', ')}
- title: ${title || ''}
- queryType: ${queryType}
- result_length: ${String(spansTableResult.result.data?.length || 0)}
- user_queries: ${search.formatString()}
- user_queries_count: ${String(search.tokens.length)}
- visualizes_count: ${String(visualizes.length)}
- has_exceeded_performance_usage_limit: ${String(hasExceededPerformanceUsageLimit)}
- page_source: ${page_source}
- `);
- }, [
- organization,
- dataset,
- fields,
- query,
- visualizes,
- title,
- queryType,
- spansTableResult.result.isPending,
- spansTableResult.result.status,
- spansTableResult.result.data?.length,
- timeseriesResult.isPending,
- timeseriesResult.data,
- hasExceededPerformanceUsageLimit,
- isLoadingSubscriptionDetails,
- query_status,
- page_source,
- ]);
- const tracesTableResultDefined = defined(tracesTableResult);
- useEffect(() => {
- if (
- !tracesTableResultDefined ||
- queryType !== 'traces' ||
- tracesTableResult.result.isPending ||
- timeseriesResult.isPending ||
- isLoadingSubscriptionDetails
- ) {
- return;
- }
- const search = new MutableSearch(query);
- const columns = [
- 'trace id',
- 'trace root',
- 'total spans',
- 'timeline',
- 'root duration',
- 'timestamp',
- ];
- const resultMissingRoot =
- tracesTableResult?.result?.data?.data?.filter(trace => !defined(trace.name))
- .length ?? 0;
- trackAnalytics('trace.explorer.metadata', {
- organization,
- dataset,
- result_mode: 'trace samples',
- columns,
- columns_count: columns.length,
- query_status,
- result_length: tracesTableResult.result.data?.data?.length || 0,
- result_missing_root: resultMissingRoot,
- user_queries: search.formatString(),
- user_queries_count: search.tokens.length,
- visualizes,
- visualizes_count: visualizes.length,
- title: title || '',
- confidences: computeConfidence(visualizes, timeseriesResult.data),
- has_exceeded_performance_usage_limit: hasExceededPerformanceUsageLimit,
- page_source,
- });
- }, [
- organization,
- dataset,
- fields,
- query,
- visualizes,
- title,
- queryType,
- tracesTableResult?.result.isPending,
- tracesTableResult?.result.status,
- tracesTableResult?.result.data?.data,
- timeseriesResult.isPending,
- timeseriesResult.data,
- hasExceededPerformanceUsageLimit,
- isLoadingSubscriptionDetails,
- query_status,
- page_source,
- tracesTableResultDefined,
- ]);
- }
- export function useAnalytics({
- queryType,
- aggregatesTableResult,
- spansTableResult,
- tracesTableResult,
- timeseriesResult,
- }: {
- aggregatesTableResult: AggregatesTableResult;
- queryType: 'aggregate' | 'samples' | 'traces';
- spansTableResult: SpansTableResult;
- timeseriesResult: ReturnType<typeof useSortedTimeSeries>;
- tracesTableResult: TracesTableResult;
- }) {
- const dataset = useExploreDataset();
- const title = useExploreTitle();
- const query = useExploreQuery();
- const fields = useExploreFields();
- const visualizes = useExploreVisualizes();
- return useTrackAnalytics({
- queryType,
- aggregatesTableResult,
- spansTableResult,
- tracesTableResult,
- timeseriesResult,
- dataset,
- title,
- query,
- fields,
- visualizes,
- page_source: 'explore',
- });
- }
- export function useCompareAnalytics({
- query: queryParts,
- index,
- queryType,
- aggregatesTableResult,
- spansTableResult,
- timeseriesResult,
- }: {
- aggregatesTableResult: AggregatesTableResult;
- index: number;
- query: ReadableExploreQueryParts;
- queryType: 'aggregate' | 'samples' | 'traces';
- spansTableResult: SpansTableResult;
- timeseriesResult: ReturnType<typeof useSortedTimeSeries>;
- }) {
- const dataset = DiscoverDatasets.SPANS_EAP_RPC;
- const query = queryParts.query;
- const fields = queryParts.fields;
- const visualizes = queryParts.yAxes.map(yAxis => {
- return {
- chartType: queryParts.chartType,
- yAxes: [yAxis],
- label: String(index),
- } as Visualize;
- });
- return useTrackAnalytics({
- queryType,
- aggregatesTableResult,
- spansTableResult,
- timeseriesResult,
- dataset,
- query,
- fields,
- visualizes,
- page_source: 'compare',
- });
- }
- function computeConfidence(
- visualizes: Visualize[],
- data: ReturnType<typeof useSortedTimeSeries>['data']
- ) {
- return visualizes.map(visualize => {
- const dedupedYAxes = dedupeArray(visualize.yAxes);
- const series = dedupedYAxes.flatMap(yAxis => data[yAxis]).filter(defined);
- return String(combineConfidenceForSeries(series));
- });
- }
|