import {Fragment, useState} from 'react'; import {hasEveryAccess} from 'sentry/components/acl/access'; import Feature from 'sentry/components/acl/feature'; import FeatureDisabled from 'sentry/components/acl/featureDisabled'; import {Alert} from 'sentry/components/alert'; import MiniBarChart from 'sentry/components/charts/miniBarChart'; import EmptyMessage from 'sentry/components/emptyMessage'; import ExternalLink from 'sentry/components/links/externalLink'; import LoadingError from 'sentry/components/loadingError'; import LoadingIndicator from 'sentry/components/loadingIndicator'; import Panel from 'sentry/components/panels/panel'; import PanelBody from 'sentry/components/panels/panelBody'; import PanelHeader from 'sentry/components/panels/panelHeader'; import PluginList from 'sentry/components/pluginList'; import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {t, tct} from 'sentry/locale'; import type {TimeseriesValue} from 'sentry/types/core'; import type {Series} from 'sentry/types/echarts'; import type {Plugin} from 'sentry/types/integrations'; import type {Project} from 'sentry/types/project'; import {useApiQuery} from 'sentry/utils/queryClient'; import useOrganization from 'sentry/utils/useOrganization'; import {useParams} from 'sentry/utils/useParams'; import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader'; import TextBlock from 'sentry/views/settings/components/text/textBlock'; import PermissionAlert from 'sentry/views/settings/project/permissionAlert'; function DataForwardingStats() { const {orgId, projectId} = useParams<{orgId: string; projectId: string}>(); const until = Math.floor(new Date().getTime() / 1000); const since = until - 3600 * 24 * 30; const options = { query: { since, until, resolution: '1d', stat: 'forwarded', }, }; const { data: stats, isPending, isError, refetch, } = useApiQuery( [`/projects/${orgId}/${projectId}/stats/`, options], {staleTime: 0} ); if (isPending) { return ; } if (isError) { return ; } const series: Series = { seriesName: t('Forwarded'), data: stats.map(([timestamp, value]) => ({name: timestamp * 1000, value})), }; const forwardedAny = series.data.some(({value}) => value > 0); return ( {t('Forwarded events in the last 30 days (by day)')} {forwardedAny ? ( ) : ( )} ); } type Props = { project: Project; }; function ProjectDataForwarding({project}: Props) { const organization = useOrganization(); const {projectId} = useParams<{projectId: string}>(); const [pluginState, setPluginState] = useState([]); const { data: fetchedPlugins, isPending, isError, refetch, } = useApiQuery([`/projects/${organization.slug}/${projectId}/plugins/`], { staleTime: 0, }); if (isPending) { return ; } if (isError) { return ; } const plugins = pluginState.length ? pluginState : fetchedPlugins; const forwardingPlugins = () => { return plugins.filter(p => p.type === 'data-forwarding' && p.hasConfiguration); }; const updatePlugin = (plugin: Plugin, enabled: boolean) => { const newPlugins = plugins.map(p => ({ ...p, enabled: p.id === plugin.id ? enabled : p.enabled, })); setPluginState(newPlugins); }; const onEnablePlugin = (plugin: Plugin) => updatePlugin(plugin, true); const onDisablePlugin = (plugin: Plugin) => updatePlugin(plugin, false); const hasAccess = hasEveryAccess(['project:write'], {organization, project}); const pluginsPanel = plugins.length > 0 ? ( ) : ( ); return (
{({hasFeature, features}) => ( {tct( `Data Forwarding allows processed events to be sent to your favorite business intelligence tools. The exact payload and types of data depend on the integration you're using. Learn more about this functionality in our [link:documentation].`, { link: ( ), } )} {tct( `Sentry forwards [em:all applicable error events] to the provider, in some cases this may be a significant volume of data.`, { em: , } )} {!hasFeature && ( )} {hasAccess && hasFeature && pluginsPanel} )}
); } export default ProjectDataForwarding;