chore(analytics): remove tinybird (#11146)
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
53
.github/workflows/ci-tinybird.yaml
vendored
53
.github/workflows/ci-tinybird.yaml
vendored
@ -1,53 +0,0 @@
|
|||||||
name: CI Tinybird
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- feature/reimplement-tinybird
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- 'package.json'
|
|
||||||
- 'packages/twenty-tinybird/**'
|
|
||||||
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- 'package.json'
|
|
||||||
- 'packages/twenty-tinybird/**'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
env:
|
|
||||||
TINYBIRD_HOST: https://api.eu-central-1.aws.tinybird.co
|
|
||||||
TINYBIRD_TOKEN: ${{ secrets.TB_ADMIN_TOKEN }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
changed-files-check:
|
|
||||||
uses: ./.github/workflows/changed-files.yaml
|
|
||||||
with:
|
|
||||||
files: packages/twenty-tinybird/**
|
|
||||||
ci:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: changed-files-check
|
|
||||||
if: needs.changed-files-check.outputs.any_changed == 'true'
|
|
||||||
timeout-minutes: 10
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: './packages/twenty-tinybird'
|
|
||||||
services:
|
|
||||||
tinybird:
|
|
||||||
image: tinybirdco/tinybird-local:beta
|
|
||||||
ports:
|
|
||||||
- 7181:7181
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@master
|
|
||||||
with:
|
|
||||||
fetch-depth: 1
|
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
|
||||||
- name: Install Tinybird CLI
|
|
||||||
run: curl https://tinybird.co | sh
|
|
||||||
- name: Build project
|
|
||||||
run: tb build
|
|
||||||
- name: Test project
|
|
||||||
run: tb test run
|
|
||||||
|
|
||||||
@ -1,179 +0,0 @@
|
|||||||
import { WebhookAnalyticsTooltip } from '@/analytics/components/WebhookAnalyticsTooltip';
|
|
||||||
import { ANALYTICS_GRAPH_DESCRIPTION_MAP } from '@/analytics/constants/AnalyticsGraphDescriptionMap';
|
|
||||||
import { ANALYTICS_GRAPH_TITLE_MAP } from '@/analytics/constants/AnalyticsGraphTitleMap';
|
|
||||||
import { useGraphData } from '@/analytics/hooks/useGraphData';
|
|
||||||
import { analyticsGraphDataComponentState } from '@/analytics/states/analyticsGraphDataComponentState';
|
|
||||||
import { AnalyticsComponentProps as AnalyticsActivityGraphProps } from '@/analytics/types/AnalyticsComponentProps';
|
|
||||||
import { computeAnalyticsGraphDataFunction } from '@/analytics/utils/computeAnalyticsGraphDataFunction';
|
|
||||||
import { Select } from '@/ui/input/components/Select';
|
|
||||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
|
||||||
import { useTheme } from '@emotion/react';
|
|
||||||
import styled from '@emotion/styled';
|
|
||||||
import { ResponsiveLine } from '@nivo/line';
|
|
||||||
import { Section } from '@react-email/components';
|
|
||||||
import { useId, useState } from 'react';
|
|
||||||
import { H2Title } from 'twenty-ui';
|
|
||||||
|
|
||||||
const StyledGraphContainer = styled.div`
|
|
||||||
background-color: ${({ theme }) => theme.background.secondary};
|
|
||||||
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
|
||||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
|
||||||
height: 199px;
|
|
||||||
|
|
||||||
padding: ${({ theme }) => theme.spacing(4, 2, 2, 2)};
|
|
||||||
width: 496px;
|
|
||||||
`;
|
|
||||||
const StyledTitleContainer = styled.div`
|
|
||||||
align-items: flex-start;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const AnalyticsActivityGraph = ({
|
|
||||||
recordId,
|
|
||||||
endpointName,
|
|
||||||
}: AnalyticsActivityGraphProps) => {
|
|
||||||
const [analyticsGraphData, setAnalyticsGraphData] = useRecoilComponentStateV2(
|
|
||||||
analyticsGraphDataComponentState,
|
|
||||||
);
|
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
const [windowLengthGraphOption, setWindowLengthGraphOption] = useState<
|
|
||||||
'7D' | '1D' | '12H' | '4H'
|
|
||||||
>('7D');
|
|
||||||
|
|
||||||
const { fetchGraphData } = useGraphData({
|
|
||||||
recordId,
|
|
||||||
endpointName,
|
|
||||||
});
|
|
||||||
|
|
||||||
const transformDataFunction = computeAnalyticsGraphDataFunction(endpointName);
|
|
||||||
|
|
||||||
const dropdownId = useId();
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{analyticsGraphData.length ? (
|
|
||||||
<Section>
|
|
||||||
<StyledTitleContainer>
|
|
||||||
<H2Title
|
|
||||||
title={`${ANALYTICS_GRAPH_TITLE_MAP[endpointName]}`}
|
|
||||||
description={`${ANALYTICS_GRAPH_DESCRIPTION_MAP[endpointName]}`}
|
|
||||||
/>
|
|
||||||
<Select
|
|
||||||
dropdownId={dropdownId}
|
|
||||||
value={windowLengthGraphOption}
|
|
||||||
options={[
|
|
||||||
{ value: '7D', label: 'This week' },
|
|
||||||
{ value: '1D', label: 'Today' },
|
|
||||||
{ value: '12H', label: 'Last 12 hours' },
|
|
||||||
{ value: '4H', label: 'Last 4 hours' },
|
|
||||||
]}
|
|
||||||
onChange={(windowLengthGraphOption) => {
|
|
||||||
setWindowLengthGraphOption(windowLengthGraphOption);
|
|
||||||
fetchGraphData(windowLengthGraphOption).then((graphInput) => {
|
|
||||||
setAnalyticsGraphData(transformDataFunction(graphInput));
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</StyledTitleContainer>
|
|
||||||
|
|
||||||
<StyledGraphContainer>
|
|
||||||
<ResponsiveLine
|
|
||||||
data={analyticsGraphData}
|
|
||||||
curve={'monotoneX'}
|
|
||||||
enableArea={true}
|
|
||||||
colors={{ scheme: 'set1' }}
|
|
||||||
//it "addapts" to the color scheme of the graph without hardcoding them
|
|
||||||
//is there a color scheme for graph Data in twenty? Do we always want the gradient?
|
|
||||||
theme={{
|
|
||||||
text: {
|
|
||||||
fill: theme.font.color.light,
|
|
||||||
fontSize: theme.font.size.sm,
|
|
||||||
fontFamily: theme.font.family,
|
|
||||||
},
|
|
||||||
axis: {
|
|
||||||
domain: {
|
|
||||||
line: {
|
|
||||||
stroke: theme.border.color.light,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
line: {
|
|
||||||
stroke: theme.border.color.light,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
line: {
|
|
||||||
stroke: theme.border.color.light,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
crosshair: {
|
|
||||||
line: {
|
|
||||||
stroke: theme.font.color.light,
|
|
||||||
strokeDasharray: '2 2',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
margin={{ top: 20, right: 0, bottom: 30, left: 30 }}
|
|
||||||
xFormat="time:%Y-%m-%d %H:%M%"
|
|
||||||
xScale={{
|
|
||||||
type: 'time',
|
|
||||||
useUTC: false,
|
|
||||||
format: '%Y-%m-%d %H:%M:%S',
|
|
||||||
precision: 'hour',
|
|
||||||
}}
|
|
||||||
defs={[
|
|
||||||
{
|
|
||||||
colors: [
|
|
||||||
{
|
|
||||||
color: 'inherit',
|
|
||||||
offset: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
color: 'inherit',
|
|
||||||
offset: 100,
|
|
||||||
opacity: 0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
id: 'gradientGraph',
|
|
||||||
type: 'linearGradient',
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
fill={[
|
|
||||||
{
|
|
||||||
id: 'gradientGraph',
|
|
||||||
match: '*',
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
yScale={{ type: 'linear' }}
|
|
||||||
axisBottom={{
|
|
||||||
format: '%b %d, %I:%M %p', //TODO: add the user prefered time format for the graph
|
|
||||||
tickValues: 2,
|
|
||||||
tickPadding: 5,
|
|
||||||
tickSize: 6,
|
|
||||||
}}
|
|
||||||
axisLeft={{
|
|
||||||
tickPadding: 5,
|
|
||||||
tickSize: 6,
|
|
||||||
tickValues: 4,
|
|
||||||
}}
|
|
||||||
enableGridX={false}
|
|
||||||
lineWidth={1}
|
|
||||||
gridYValues={4}
|
|
||||||
enablePoints={false}
|
|
||||||
isInteractive={true}
|
|
||||||
useMesh={true}
|
|
||||||
enableSlices={false}
|
|
||||||
enableCrosshair={false}
|
|
||||||
tooltip={({ point }) => <WebhookAnalyticsTooltip point={point} />} // later add a condition to get different tooltips
|
|
||||||
/>
|
|
||||||
</StyledGraphContainer>
|
|
||||||
</Section>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
import { useGraphData } from '@/analytics/hooks/useGraphData';
|
|
||||||
import { analyticsGraphDataComponentState } from '@/analytics/states/analyticsGraphDataComponentState';
|
|
||||||
import { AnalyticsComponentProps as AnalyticsGraphEffectProps } from '@/analytics/types/AnalyticsComponentProps';
|
|
||||||
import { computeAnalyticsGraphDataFunction } from '@/analytics/utils/computeAnalyticsGraphDataFunction';
|
|
||||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
|
||||||
import { useState } from 'react';
|
|
||||||
|
|
||||||
export const AnalyticsGraphEffect = ({
|
|
||||||
recordId,
|
|
||||||
endpointName,
|
|
||||||
}: AnalyticsGraphEffectProps) => {
|
|
||||||
const setAnalyticsGraphData = useSetRecoilComponentStateV2(
|
|
||||||
analyticsGraphDataComponentState,
|
|
||||||
);
|
|
||||||
|
|
||||||
const transformDataFunction = computeAnalyticsGraphDataFunction(endpointName);
|
|
||||||
const [isLoaded, setIsLoaded] = useState(false);
|
|
||||||
|
|
||||||
const { fetchGraphData } = useGraphData({
|
|
||||||
recordId,
|
|
||||||
endpointName,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!isLoaded) {
|
|
||||||
fetchGraphData('7D').then((graphInput) => {
|
|
||||||
setAnalyticsGraphData(transformDataFunction(graphInput));
|
|
||||||
});
|
|
||||||
setIsLoaded(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return <></>;
|
|
||||||
};
|
|
||||||
@ -1,89 +0,0 @@
|
|||||||
import { formatDateISOStringToDateTimeSimplified } from '@/localization/utils/formatDateISOStringToDateTimeSimplified';
|
|
||||||
import { UserContext } from '@/users/contexts/UserContext';
|
|
||||||
import styled from '@emotion/styled';
|
|
||||||
import { Point } from '@nivo/line';
|
|
||||||
import { ReactElement, useContext } from 'react';
|
|
||||||
|
|
||||||
const StyledTooltipContainer = styled.div`
|
|
||||||
align-items: center;
|
|
||||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
|
||||||
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
|
||||||
display: flex;
|
|
||||||
width: 128px;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
background: ${({ theme }) => theme.background.transparent.secondary};
|
|
||||||
box-shadow: ${({ theme }) => theme.boxShadow.light};
|
|
||||||
backdrop-filter: ${({ theme }) => theme.blur.medium};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledTooltipDateContainer = styled.div`
|
|
||||||
align-items: flex-start;
|
|
||||||
align-self: stretch;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
|
||||||
font-family: ${({ theme }) => theme.font.family};
|
|
||||||
gap: ${({ theme }) => theme.spacing(2)};
|
|
||||||
color: ${({ theme }) => theme.font.color.secondary};
|
|
||||||
padding: ${({ theme }) => theme.spacing(2)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledTooltipDataRow = styled.div`
|
|
||||||
align-items: flex-start;
|
|
||||||
align-self: stretch;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
color: ${({ theme }) => theme.font.color.tertiary};
|
|
||||||
padding: ${({ theme }) => theme.spacing(2)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledLine = styled.div`
|
|
||||||
background-color: ${({ theme }) => theme.border.color.medium};
|
|
||||||
height: 1px;
|
|
||||||
width: 100%;
|
|
||||||
`;
|
|
||||||
const StyledColorPoint = styled.div<{ color: string }>`
|
|
||||||
background-color: ${({ color }) => color};
|
|
||||||
border-radius: 50%;
|
|
||||||
height: 8px;
|
|
||||||
width: 8px;
|
|
||||||
display: inline-block;
|
|
||||||
`;
|
|
||||||
const StyledDataDefinition = styled.div`
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: ${({ theme }) => theme.spacing(2)};
|
|
||||||
`;
|
|
||||||
const StyledSpan = styled.span`
|
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
|
||||||
`;
|
|
||||||
type WebhookAnalyticsTooltipProps = {
|
|
||||||
point: Point;
|
|
||||||
};
|
|
||||||
export const WebhookAnalyticsTooltip = ({
|
|
||||||
point,
|
|
||||||
}: WebhookAnalyticsTooltipProps): ReactElement => {
|
|
||||||
const { timeFormat, timeZone } = useContext(UserContext);
|
|
||||||
const windowInterval = new Date(point.data.x);
|
|
||||||
const windowIntervalDate = formatDateISOStringToDateTimeSimplified(
|
|
||||||
windowInterval,
|
|
||||||
timeZone,
|
|
||||||
timeFormat,
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<StyledTooltipContainer>
|
|
||||||
<StyledTooltipDateContainer>
|
|
||||||
{windowIntervalDate}
|
|
||||||
</StyledTooltipDateContainer>
|
|
||||||
<StyledLine />
|
|
||||||
<StyledTooltipDataRow>
|
|
||||||
<StyledDataDefinition>
|
|
||||||
<StyledColorPoint color={point.serieColor} />
|
|
||||||
{String(point.serieId)}
|
|
||||||
</StyledDataDefinition>
|
|
||||||
<StyledSpan>{String(point.data.y)}</StyledSpan>
|
|
||||||
</StyledTooltipDataRow>
|
|
||||||
</StyledTooltipContainer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
import { AnalyticsTinybirdJwtMap } from '~/generated-metadata/graphql';
|
|
||||||
|
|
||||||
export const ANALYTICS_ENDPOINT_TYPE_MAP: AnalyticsTinybirdJwtMap = {
|
|
||||||
getWebhookAnalytics: 'webhook',
|
|
||||||
getPageviewsAnalytics: 'pageviews',
|
|
||||||
getUsersAnalytics: 'users',
|
|
||||||
getServerlessFunctionDuration: 'function',
|
|
||||||
getServerlessFunctionSuccessRate: 'function',
|
|
||||||
getServerlessFunctionErrorCount: 'function',
|
|
||||||
};
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
import { AnalyticsTinybirdJwtMap } from '~/generated-metadata/graphql';
|
|
||||||
|
|
||||||
export const ANALYTICS_GRAPH_DESCRIPTION_MAP: AnalyticsTinybirdJwtMap = {
|
|
||||||
getWebhookAnalytics: 'See your webhook activity over time',
|
|
||||||
getPageviewsAnalytics: 'See your Page Views activity over time',
|
|
||||||
getUsersAnalytics: 'See your Users activity over time',
|
|
||||||
getServerlessFunctionDuration: 'See your function duration over time',
|
|
||||||
getServerlessFunctionSuccessRate: 'See your function success rate over time',
|
|
||||||
getServerlessFunctionErrorCount: 'See your function error count over time',
|
|
||||||
};
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
export const ANALYTICS_GRAPH_OPTION_MAP = {
|
|
||||||
'7D': { granularity: 'day' },
|
|
||||||
'1D': { granularity: 'hour' },
|
|
||||||
'12H': { granularity: 'hour' },
|
|
||||||
'4H': { granularity: 'hour' },
|
|
||||||
};
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
import { AnalyticsTinybirdJwtMap } from '~/generated-metadata/graphql';
|
|
||||||
|
|
||||||
export const ANALYTICS_GRAPH_TITLE_MAP: AnalyticsTinybirdJwtMap = {
|
|
||||||
getWebhookAnalytics: 'Activity',
|
|
||||||
getPageviewsAnalytics: 'Page Views',
|
|
||||||
getUsersAnalytics: 'Users',
|
|
||||||
getServerlessFunctionDuration: 'Duration (ms)',
|
|
||||||
getServerlessFunctionSuccessRate: 'Success Rate (%)',
|
|
||||||
getServerlessFunctionErrorCount: 'Error Count',
|
|
||||||
};
|
|
||||||
@ -1,87 +0,0 @@
|
|||||||
import { useAnalyticsTinybirdJwts } from '@/analytics/hooks/useAnalyticsTinybirdJwts';
|
|
||||||
import { CurrentUser, currentUserState } from '@/auth/states/currentUserState';
|
|
||||||
import { act, renderHook } from '@testing-library/react';
|
|
||||||
import { useSetRecoilState } from 'recoil';
|
|
||||||
import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper';
|
|
||||||
|
|
||||||
const Wrapper = getJestMetadataAndApolloMocksWrapper({
|
|
||||||
apolloMocks: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('useAnalyticsTinybirdJwts', () => {
|
|
||||||
const JWT_NAME = 'getWebhookAnalytics';
|
|
||||||
const TEST_JWT_TOKEN = 'test-jwt-token';
|
|
||||||
|
|
||||||
it('should return undefined when no user is logged in', () => {
|
|
||||||
const { result } = renderHook(
|
|
||||||
() => {
|
|
||||||
const setCurrentUserState = useSetRecoilState(currentUserState);
|
|
||||||
return {
|
|
||||||
hook: useAnalyticsTinybirdJwts(JWT_NAME),
|
|
||||||
setCurrentUserState,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
{ wrapper: Wrapper },
|
|
||||||
);
|
|
||||||
|
|
||||||
act(() => {
|
|
||||||
result.current.setCurrentUserState(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result.current.hook).toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the correct JWT token when available', () => {
|
|
||||||
const { result } = renderHook(
|
|
||||||
() => {
|
|
||||||
const setCurrentUserState = useSetRecoilState(currentUserState);
|
|
||||||
return {
|
|
||||||
hook: useAnalyticsTinybirdJwts(JWT_NAME),
|
|
||||||
setCurrentUserState,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
{ wrapper: Wrapper },
|
|
||||||
);
|
|
||||||
|
|
||||||
act(() => {
|
|
||||||
result.current.setCurrentUserState({
|
|
||||||
id: '1',
|
|
||||||
email: 'test@test.com',
|
|
||||||
canImpersonate: false,
|
|
||||||
userVars: {},
|
|
||||||
analyticsTinybirdJwts: {
|
|
||||||
[JWT_NAME]: TEST_JWT_TOKEN,
|
|
||||||
},
|
|
||||||
} as CurrentUser);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result.current.hook).toBe(TEST_JWT_TOKEN);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return undefined when JWT token is not available', () => {
|
|
||||||
const { result } = renderHook(
|
|
||||||
() => {
|
|
||||||
const setCurrentUserState = useSetRecoilState(currentUserState);
|
|
||||||
return {
|
|
||||||
hook: useAnalyticsTinybirdJwts(JWT_NAME),
|
|
||||||
setCurrentUserState,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
{ wrapper: Wrapper },
|
|
||||||
);
|
|
||||||
|
|
||||||
act(() => {
|
|
||||||
result.current.setCurrentUserState({
|
|
||||||
id: '1',
|
|
||||||
email: 'test@test.com',
|
|
||||||
canImpersonate: false,
|
|
||||||
userVars: {},
|
|
||||||
analyticsTinybirdJwts: {
|
|
||||||
getPageviewsAnalytics: TEST_JWT_TOKEN,
|
|
||||||
},
|
|
||||||
} as CurrentUser);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result.current.hook).toBeUndefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,87 +0,0 @@
|
|||||||
import { useAnalyticsTinybirdJwts } from '@/analytics/hooks/useAnalyticsTinybirdJwts';
|
|
||||||
import { useGraphData } from '@/analytics/hooks/useGraphData';
|
|
||||||
import { fetchGraphDataOrThrow } from '@/analytics/utils/fetchGraphDataOrThrow';
|
|
||||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
|
||||||
import { renderHook } from '@testing-library/react';
|
|
||||||
jest.mock('@/analytics/hooks/useAnalyticsTinybirdJwts');
|
|
||||||
jest.mock('@/analytics/utils/fetchGraphDataOrThrow');
|
|
||||||
jest.mock('@/ui/feedback/snack-bar-manager/hooks/useSnackBar');
|
|
||||||
|
|
||||||
describe('useGraphData', () => {
|
|
||||||
const mockEnqueueSnackBar = jest.fn();
|
|
||||||
const mockUseSnackBar = jest.fn().mockReturnValue({
|
|
||||||
enqueueSnackBar: mockEnqueueSnackBar,
|
|
||||||
});
|
|
||||||
|
|
||||||
const mockUseAnalyticsTinybirdJwts = jest.fn();
|
|
||||||
const mockFetchGraphDataOrThrow = jest.fn();
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
jest.clearAllMocks();
|
|
||||||
(useSnackBar as jest.MockedFunction<typeof useSnackBar>).mockImplementation(
|
|
||||||
mockUseSnackBar,
|
|
||||||
);
|
|
||||||
(
|
|
||||||
useAnalyticsTinybirdJwts as jest.MockedFunction<
|
|
||||||
typeof useAnalyticsTinybirdJwts
|
|
||||||
>
|
|
||||||
).mockImplementation(mockUseAnalyticsTinybirdJwts);
|
|
||||||
(
|
|
||||||
fetchGraphDataOrThrow as jest.MockedFunction<typeof fetchGraphDataOrThrow>
|
|
||||||
).mockImplementation(mockFetchGraphDataOrThrow);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fetch graph data successfully', async () => {
|
|
||||||
const mockJwt = 'mock-jwt';
|
|
||||||
const mockRecordId = 'mock-record-id';
|
|
||||||
const mockEndpointName = 'getWebhookAnalytics';
|
|
||||||
const mockGraphData = [{ x: '2023-01-01', y: 100 }];
|
|
||||||
|
|
||||||
mockUseAnalyticsTinybirdJwts.mockReturnValue(mockJwt);
|
|
||||||
mockFetchGraphDataOrThrow.mockResolvedValue(mockGraphData);
|
|
||||||
|
|
||||||
const { result } = renderHook(() =>
|
|
||||||
useGraphData({ recordId: mockRecordId, endpointName: mockEndpointName }),
|
|
||||||
);
|
|
||||||
const { fetchGraphData } = result.current;
|
|
||||||
|
|
||||||
const data = await fetchGraphData('7D');
|
|
||||||
expect(data).toEqual(mockGraphData);
|
|
||||||
expect(mockFetchGraphDataOrThrow).toHaveBeenCalledWith({
|
|
||||||
recordId: mockRecordId,
|
|
||||||
windowLength: '7D',
|
|
||||||
tinybirdJwt: mockJwt,
|
|
||||||
endpointName: mockEndpointName,
|
|
||||||
});
|
|
||||||
expect(mockEnqueueSnackBar).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
it('should handle errors when fetching graph data', async () => {
|
|
||||||
const mockRecordId = 'mock-record-id';
|
|
||||||
const mockEndpointName = 'getWebhookAnalytics';
|
|
||||||
const mockError = new Error('Something went wrong');
|
|
||||||
|
|
||||||
mockUseAnalyticsTinybirdJwts.mockReturnValue('');
|
|
||||||
mockFetchGraphDataOrThrow.mockRejectedValue(mockError);
|
|
||||||
|
|
||||||
const { result } = renderHook(() =>
|
|
||||||
useGraphData({ recordId: mockRecordId, endpointName: mockEndpointName }),
|
|
||||||
);
|
|
||||||
const { fetchGraphData } = result.current;
|
|
||||||
|
|
||||||
const data = await fetchGraphData('7D');
|
|
||||||
expect(data).toEqual([]);
|
|
||||||
expect(mockFetchGraphDataOrThrow).toHaveBeenCalledWith({
|
|
||||||
recordId: mockRecordId,
|
|
||||||
windowLength: '7D',
|
|
||||||
tinybirdJwt: '',
|
|
||||||
endpointName: mockEndpointName,
|
|
||||||
});
|
|
||||||
expect(mockEnqueueSnackBar).toHaveBeenCalledWith(
|
|
||||||
'Something went wrong while fetching webhook usage: Something went wrong',
|
|
||||||
{
|
|
||||||
variant: SnackBarVariant.Error,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
|
||||||
import { AnalyticsTinybirdJwtMap } from '~/generated-metadata/graphql';
|
|
||||||
|
|
||||||
export const useAnalyticsTinybirdJwts = (
|
|
||||||
jwtName: keyof AnalyticsTinybirdJwtMap,
|
|
||||||
): string | undefined => {
|
|
||||||
const currentUser = useRecoilValue(currentUserState);
|
|
||||||
|
|
||||||
if (!currentUser) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentUser.analyticsTinybirdJwts?.[jwtName];
|
|
||||||
};
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
import { useAnalyticsTinybirdJwts } from '@/analytics/hooks/useAnalyticsTinybirdJwts';
|
|
||||||
import { AnalyticsComponentProps as useGraphDataProps } from '@/analytics/types/AnalyticsComponentProps';
|
|
||||||
import { fetchGraphDataOrThrow } from '@/analytics/utils/fetchGraphDataOrThrow';
|
|
||||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
|
||||||
import { isUndefined } from '@sniptt/guards';
|
|
||||||
import { useCallback } from 'react';
|
|
||||||
|
|
||||||
export const useGraphData = ({ recordId, endpointName }: useGraphDataProps) => {
|
|
||||||
const { enqueueSnackBar } = useSnackBar();
|
|
||||||
const tinybirdJwt = useAnalyticsTinybirdJwts(endpointName);
|
|
||||||
|
|
||||||
const fetchGraphData = useCallback(
|
|
||||||
async (windowLengthGraphOption: '7D' | '1D' | '12H' | '4H') => {
|
|
||||||
try {
|
|
||||||
if (isUndefined(tinybirdJwt)) {
|
|
||||||
throw new Error('No jwt associated with this endpoint found');
|
|
||||||
}
|
|
||||||
|
|
||||||
return await fetchGraphDataOrThrow({
|
|
||||||
recordId,
|
|
||||||
windowLength: windowLengthGraphOption,
|
|
||||||
tinybirdJwt,
|
|
||||||
endpointName,
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof Error) {
|
|
||||||
enqueueSnackBar(
|
|
||||||
`Something went wrong while fetching webhook usage: ${error.message}`,
|
|
||||||
{
|
|
||||||
variant: SnackBarVariant.Error,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[tinybirdJwt, recordId, endpointName, enqueueSnackBar],
|
|
||||||
);
|
|
||||||
|
|
||||||
return { fetchGraphData };
|
|
||||||
};
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
import { AnalyticsGraphDataInstanceContext } from '@/analytics/states/contexts/AnalyticsGraphDataInstanceContext';
|
|
||||||
import { NivoLineInput } from '@/analytics/types/NivoLineInput';
|
|
||||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
|
||||||
export const analyticsGraphDataComponentState = createComponentStateV2<
|
|
||||||
NivoLineInput[]
|
|
||||||
>({
|
|
||||||
key: 'analyticsGraphDataComponentState',
|
|
||||||
defaultValue: [],
|
|
||||||
componentInstanceContext: AnalyticsGraphDataInstanceContext,
|
|
||||||
});
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
import { createComponentInstanceContext } from '@/ui/utilities/state/component-state/utils/createComponentInstanceContext';
|
|
||||||
|
|
||||||
export const AnalyticsGraphDataInstanceContext =
|
|
||||||
createComponentInstanceContext();
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
import { AnalyticsTinybirdJwtMap } from '~/generated-metadata/graphql';
|
|
||||||
|
|
||||||
export type AnalyticsComponentProps = {
|
|
||||||
recordId: string;
|
|
||||||
endpointName: keyof AnalyticsTinybirdJwtMap;
|
|
||||||
};
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
export type NivoLineInput = {
|
|
||||||
id: string | number;
|
|
||||||
color?: string;
|
|
||||||
data: Array<{
|
|
||||||
x: number | string | Date;
|
|
||||||
y: number | string | Date;
|
|
||||||
}>;
|
|
||||||
};
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
import { computeAnalyticsGraphDataFunction } from '@/analytics/utils/computeAnalyticsGraphDataFunction';
|
|
||||||
import { mapServerlessFunctionDurationToNivoLineInput } from '@/analytics/utils/mapServerlessFunctionDurationToNivoLineInput';
|
|
||||||
import { mapServerlessFunctionErrorsToNivoLineInput } from '@/analytics/utils/mapServerlessFunctionErrorsToNivoLineInput';
|
|
||||||
import { mapWebhookAnalyticsResultToNivoLineInput } from '@/analytics/utils/mapWebhookAnalyticsResultToNivoLineInput';
|
|
||||||
|
|
||||||
jest.mock('@/analytics/utils/mapServerlessFunctionDurationToNivoLineInput');
|
|
||||||
jest.mock('@/analytics/utils/mapServerlessFunctionErrorsToNivoLineInput');
|
|
||||||
jest.mock('@/analytics/utils/mapWebhookAnalyticsResultToNivoLineInput');
|
|
||||||
|
|
||||||
describe('computeAnalyticsGraphDataFunction', () => {
|
|
||||||
afterEach(() => {
|
|
||||||
jest.clearAllMocks();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the mapWebhookAnalyticsResultToNivoLineInput function for "getWebhookAnalytics"', () => {
|
|
||||||
const result = computeAnalyticsGraphDataFunction('getWebhookAnalytics');
|
|
||||||
expect(result).toBe(mapWebhookAnalyticsResultToNivoLineInput);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the mapServerlessFunctionDurationToNivoLineInput function for "getServerlessFunctionDuration"', () => {
|
|
||||||
const result = computeAnalyticsGraphDataFunction(
|
|
||||||
'getServerlessFunctionDuration',
|
|
||||||
);
|
|
||||||
expect(result).toBe(mapServerlessFunctionDurationToNivoLineInput);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return a function that calls mapServerlessFunctionErrorsToNivoLineInput with "ErrorCount" for "getServerlessFunctionErrorCount"', () => {
|
|
||||||
const result = computeAnalyticsGraphDataFunction(
|
|
||||||
'getServerlessFunctionErrorCount',
|
|
||||||
);
|
|
||||||
const data = [{ start: '2023-01-01', error_count: 10 }];
|
|
||||||
result(data);
|
|
||||||
expect(mapServerlessFunctionErrorsToNivoLineInput).toHaveBeenCalledWith(
|
|
||||||
data,
|
|
||||||
'ErrorCount',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return a function that calls mapServerlessFunctionErrorsToNivoLineInput with "SuccessRate" for "getServerlessFunctionSuccessRate"', () => {
|
|
||||||
const result = computeAnalyticsGraphDataFunction(
|
|
||||||
'getServerlessFunctionSuccessRate',
|
|
||||||
);
|
|
||||||
const data = [{ start: '2023-01-01', success_rate: 90 }];
|
|
||||||
result(data);
|
|
||||||
expect(mapServerlessFunctionErrorsToNivoLineInput).toHaveBeenCalledWith(
|
|
||||||
data,
|
|
||||||
'SuccessRate',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error for an unknown endpoint', () => {
|
|
||||||
expect(() => computeAnalyticsGraphDataFunction('unknown')).toThrowError(
|
|
||||||
'No analytics function found associated with endpoint "unknown"',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,143 +0,0 @@
|
|||||||
import { ANALYTICS_GRAPH_OPTION_MAP } from '@/analytics/constants/AnalyticsGraphOptionMap';
|
|
||||||
import { computeStartEndDate } from '@/analytics/utils/computeStartEndDate';
|
|
||||||
import { fetchGraphDataOrThrow } from '@/analytics/utils/fetchGraphDataOrThrow';
|
|
||||||
|
|
||||||
// Im going to make this test more contundent later
|
|
||||||
jest.mock('@/analytics/utils/computeStartEndDate', () => ({
|
|
||||||
computeStartEndDate: jest.fn(() => ({
|
|
||||||
start: '2024-01-01',
|
|
||||||
end: '2024-01-07',
|
|
||||||
})),
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('fetchGraphDataOrThrow', () => {
|
|
||||||
// Setup fetch mock
|
|
||||||
const mockFetch = jest.fn();
|
|
||||||
global.fetch = mockFetch;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
jest.clearAllMocks();
|
|
||||||
});
|
|
||||||
|
|
||||||
const mockSuccessResponse = {
|
|
||||||
data: [
|
|
||||||
{ timestamp: '2024-01-01', count: 10 },
|
|
||||||
{ timestamp: '2024-01-02', count: 20 },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const defaultProps = {
|
|
||||||
recordId: 'test-123',
|
|
||||||
windowLength: '7D',
|
|
||||||
tinybirdJwt: 'test-jwt',
|
|
||||||
endpointName: 'getWebhookAnalytics',
|
|
||||||
};
|
|
||||||
|
|
||||||
it('should fetch data successfully for webhook type', async () => {
|
|
||||||
mockFetch.mockResolvedValueOnce({
|
|
||||||
ok: true,
|
|
||||||
json: () => Promise.resolve(mockSuccessResponse),
|
|
||||||
});
|
|
||||||
|
|
||||||
const result = await fetchGraphDataOrThrow(defaultProps);
|
|
||||||
|
|
||||||
// Verify URL construction
|
|
||||||
const lastCallArgs = mockFetch.mock.calls[0][0];
|
|
||||||
expect(lastCallArgs).toContain('webhookId=test-123');
|
|
||||||
expect(lastCallArgs).toContain('getWebhookAnalytics.json');
|
|
||||||
|
|
||||||
// Verify headers
|
|
||||||
const headers = mockFetch.mock.calls[0][1].headers;
|
|
||||||
expect(headers.Authorization).toBe('Bearer test-jwt');
|
|
||||||
|
|
||||||
// Verify response
|
|
||||||
expect(result).toEqual(mockSuccessResponse.data);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle different window lengths correctly', async () => {
|
|
||||||
mockFetch.mockResolvedValueOnce({
|
|
||||||
ok: true,
|
|
||||||
json: () => Promise.resolve(mockSuccessResponse),
|
|
||||||
});
|
|
||||||
|
|
||||||
await fetchGraphDataOrThrow({
|
|
||||||
...defaultProps,
|
|
||||||
windowLength: '1D',
|
|
||||||
});
|
|
||||||
|
|
||||||
// Verify that correct window length options were used
|
|
||||||
const lastCallArgs = mockFetch.mock.calls[0][0];
|
|
||||||
const options = ANALYTICS_GRAPH_OPTION_MAP['1D'];
|
|
||||||
Object.entries(options).forEach(([key, value]) => {
|
|
||||||
expect(lastCallArgs).toContain(`${key}=${value}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw error on failed request', async () => {
|
|
||||||
mockFetch.mockResolvedValueOnce({
|
|
||||||
ok: false,
|
|
||||||
json: () => Promise.resolve({ error: 'Failed to fetch' }),
|
|
||||||
});
|
|
||||||
|
|
||||||
await expect(fetchGraphDataOrThrow(defaultProps)).rejects.toThrow(
|
|
||||||
'Failed to fetch',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw error on network failure', async () => {
|
|
||||||
mockFetch.mockRejectedValueOnce(new Error('Network error'));
|
|
||||||
|
|
||||||
await expect(fetchGraphDataOrThrow(defaultProps)).rejects.toThrow(
|
|
||||||
'Network error',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should use computed start and end dates', async () => {
|
|
||||||
mockFetch.mockResolvedValueOnce({
|
|
||||||
ok: true,
|
|
||||||
json: () => Promise.resolve(mockSuccessResponse),
|
|
||||||
});
|
|
||||||
|
|
||||||
await fetchGraphDataOrThrow(defaultProps);
|
|
||||||
|
|
||||||
// Verify computeStartEndDate was called with correct window length
|
|
||||||
expect(computeStartEndDate).toHaveBeenCalledWith('7D');
|
|
||||||
|
|
||||||
// Verify the computed dates are included in the URL
|
|
||||||
const lastCallArgs = mockFetch.mock.calls[0][0];
|
|
||||||
expect(lastCallArgs).toContain('start=2024-01-01');
|
|
||||||
expect(lastCallArgs).toContain('end=2024-01-07');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should construct URL with all required parameters', async () => {
|
|
||||||
mockFetch.mockResolvedValueOnce({
|
|
||||||
ok: true,
|
|
||||||
json: () => Promise.resolve(mockSuccessResponse),
|
|
||||||
});
|
|
||||||
|
|
||||||
await fetchGraphDataOrThrow(defaultProps);
|
|
||||||
|
|
||||||
const lastCallArgs = mockFetch.mock.calls[0][0];
|
|
||||||
|
|
||||||
// Check base URL
|
|
||||||
expect(lastCallArgs).toContain(
|
|
||||||
'https://api.eu-central-1.aws.tinybird.co/v0/pipes/',
|
|
||||||
);
|
|
||||||
|
|
||||||
// Check endpoint
|
|
||||||
expect(lastCallArgs).toContain('getWebhookAnalytics.json');
|
|
||||||
|
|
||||||
// Check window length options
|
|
||||||
const options = ANALYTICS_GRAPH_OPTION_MAP['7D'];
|
|
||||||
Object.entries(options).forEach(([key, value]) => {
|
|
||||||
expect(lastCallArgs).toContain(`${key}=${value}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check computed dates
|
|
||||||
expect(lastCallArgs).toContain('start=2024-01-01');
|
|
||||||
expect(lastCallArgs).toContain('end=2024-01-07');
|
|
||||||
|
|
||||||
// Check record ID
|
|
||||||
expect(lastCallArgs).toContain('webhookId=test-123');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
import { mapServerlessFunctionDurationToNivoLineInput } from '@/analytics/utils/mapServerlessFunctionDurationToNivoLineInput';
|
|
||||||
|
|
||||||
describe('mapServerlessFunctionDurationToNivoLineInput', () => {
|
|
||||||
it('should convert the serverless function duration result to NivoLineInput format', () => {
|
|
||||||
const serverlessFunctionDurationResult = [
|
|
||||||
{
|
|
||||||
start: '2023-01-01T00:00:00.000Z',
|
|
||||||
minimum: 100,
|
|
||||||
maximum: 200,
|
|
||||||
average: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
start: '2023-01-02T00:00:00.000Z',
|
|
||||||
minimum: 80,
|
|
||||||
maximum: 160,
|
|
||||||
average: 120,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
start: '2023-01-03T00:00:00.000Z',
|
|
||||||
minimum: 90,
|
|
||||||
maximum: 180,
|
|
||||||
average: 135,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const expected = [
|
|
||||||
{
|
|
||||||
id: 'Maximum',
|
|
||||||
data: [
|
|
||||||
{ x: new Date('2023-01-01T00:00:00.000Z'), y: 200 },
|
|
||||||
{ x: new Date('2023-01-02T00:00:00.000Z'), y: 160 },
|
|
||||||
{ x: new Date('2023-01-03T00:00:00.000Z'), y: 180 },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'Minimum',
|
|
||||||
data: [
|
|
||||||
{ x: new Date('2023-01-01T00:00:00.000Z'), y: 100 },
|
|
||||||
{ x: new Date('2023-01-02T00:00:00.000Z'), y: 80 },
|
|
||||||
{ x: new Date('2023-01-03T00:00:00.000Z'), y: 90 },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'Average',
|
|
||||||
data: [
|
|
||||||
{ x: new Date('2023-01-01T00:00:00.000Z'), y: 150 },
|
|
||||||
{ x: new Date('2023-01-02T00:00:00.000Z'), y: 120 },
|
|
||||||
{ x: new Date('2023-01-03T00:00:00.000Z'), y: 135 },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const result = mapServerlessFunctionDurationToNivoLineInput(
|
|
||||||
serverlessFunctionDurationResult,
|
|
||||||
);
|
|
||||||
expect(result).toEqual(expected);
|
|
||||||
});
|
|
||||||
it('should handle an empty serverless function duration result', () => {
|
|
||||||
const serverlessFunctionDurationResult = [];
|
|
||||||
const result = mapServerlessFunctionDurationToNivoLineInput(
|
|
||||||
serverlessFunctionDurationResult,
|
|
||||||
);
|
|
||||||
expect(result).toEqual([]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
import { mapServerlessFunctionErrorsToNivoLineInput } from '@/analytics/utils/mapServerlessFunctionErrorsToNivoLineInput';
|
|
||||||
|
|
||||||
describe('mapServerlessFunctionErrorsToNivoLineInput', () => {
|
|
||||||
it('should map the serverless function result to Nivo line input format for error count', () => {
|
|
||||||
const serverlessFunctionResult = [
|
|
||||||
{ start: '2023-01-01', error_count: 10, success_rate: 0.66 },
|
|
||||||
{ start: '2023-01-02', error_count: 5, success_rate: 0.75 },
|
|
||||||
{ start: '2023-01-03', error_count: 8, success_rate: 0.69 },
|
|
||||||
];
|
|
||||||
|
|
||||||
const expected = [
|
|
||||||
{
|
|
||||||
id: 'Error',
|
|
||||||
data: [
|
|
||||||
{ x: new Date('2023-01-01'), y: 10 },
|
|
||||||
{ x: new Date('2023-01-02'), y: 5 },
|
|
||||||
{ x: new Date('2023-01-03'), y: 8 },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const result = mapServerlessFunctionErrorsToNivoLineInput(
|
|
||||||
serverlessFunctionResult,
|
|
||||||
'ErrorCount',
|
|
||||||
);
|
|
||||||
expect(result).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should map the serverless function result to Nivo line input format for success rate', () => {
|
|
||||||
const serverlessFunctionResult = [
|
|
||||||
{ start: '2023-01-01', error_count: 10, success_rate: 0.66 },
|
|
||||||
{ start: '2023-01-02', error_count: 5, success_rate: 0.75 },
|
|
||||||
{ start: '2023-01-03', error_count: 8, success_rate: 0.69 },
|
|
||||||
];
|
|
||||||
|
|
||||||
const expected = [
|
|
||||||
{
|
|
||||||
id: 'Success Rate',
|
|
||||||
data: [
|
|
||||||
{ x: new Date('2023-01-01'), y: 0.66 },
|
|
||||||
{ x: new Date('2023-01-02'), y: 0.75 },
|
|
||||||
{ x: new Date('2023-01-03'), y: 0.69 },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const result = mapServerlessFunctionErrorsToNivoLineInput(
|
|
||||||
serverlessFunctionResult,
|
|
||||||
'SuccessRate',
|
|
||||||
);
|
|
||||||
expect(result).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle empty input', () => {
|
|
||||||
const serverlessFunctionResult = [];
|
|
||||||
const expected = [
|
|
||||||
{
|
|
||||||
id: 'Error',
|
|
||||||
data: [],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const result = mapServerlessFunctionErrorsToNivoLineInput(
|
|
||||||
serverlessFunctionResult,
|
|
||||||
'ErrorCount',
|
|
||||||
);
|
|
||||||
expect(result).toEqual(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,187 +0,0 @@
|
|||||||
import { mapWebhookAnalyticsResultToNivoLineInput } from '@/analytics/utils/mapWebhookAnalyticsResultToNivoLineInput';
|
|
||||||
|
|
||||||
describe('mapWebhookAnalyticsResultToNivoLineInput', () => {
|
|
||||||
it('should correctly map empty array', () => {
|
|
||||||
const result = mapWebhookAnalyticsResultToNivoLineInput([]);
|
|
||||||
expect(result).toEqual([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should correctly map single data point', () => {
|
|
||||||
const input = [
|
|
||||||
{
|
|
||||||
start: '2024-01-01T00:00:00Z',
|
|
||||||
success_count: 10,
|
|
||||||
failure_count: 5,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const expected = [
|
|
||||||
{
|
|
||||||
id: 'Failed',
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
x: new Date('2024-01-01T00:00:00Z'),
|
|
||||||
y: 5,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'Succeeded',
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
x: new Date('2024-01-01T00:00:00Z'),
|
|
||||||
y: 10,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const result = mapWebhookAnalyticsResultToNivoLineInput(input);
|
|
||||||
expect(result).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should correctly map multiple data points', () => {
|
|
||||||
const input = [
|
|
||||||
{
|
|
||||||
start: '2024-01-01T00:00:00Z',
|
|
||||||
success_count: 10,
|
|
||||||
failure_count: 5,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
start: '2024-01-02T00:00:00Z',
|
|
||||||
success_count: 15,
|
|
||||||
failure_count: 3,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const expected = [
|
|
||||||
{
|
|
||||||
id: 'Failed',
|
|
||||||
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
x: new Date('2024-01-01T00:00:00Z'),
|
|
||||||
y: 5,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
x: new Date('2024-01-02T00:00:00Z'),
|
|
||||||
y: 3,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'Succeeded',
|
|
||||||
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
x: new Date('2024-01-01T00:00:00Z'),
|
|
||||||
y: 10,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
x: new Date('2024-01-02T00:00:00Z'),
|
|
||||||
y: 15,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const result = mapWebhookAnalyticsResultToNivoLineInput(input);
|
|
||||||
expect(result).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle zero counts', () => {
|
|
||||||
const input = [
|
|
||||||
{
|
|
||||||
start: '2024-01-01T00:00:00Z',
|
|
||||||
success_count: 0,
|
|
||||||
failure_count: 0,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const expected = [
|
|
||||||
{
|
|
||||||
id: 'Failed',
|
|
||||||
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
x: new Date('2024-01-01T00:00:00Z'),
|
|
||||||
y: 0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'Succeeded',
|
|
||||||
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
x: new Date('2024-01-01T00:00:00Z'),
|
|
||||||
y: 0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const result = mapWebhookAnalyticsResultToNivoLineInput(input);
|
|
||||||
expect(result).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should preserve data point order', () => {
|
|
||||||
const input = [
|
|
||||||
{
|
|
||||||
start: '2024-01-02T00:00:00Z',
|
|
||||||
success_count: 15,
|
|
||||||
failure_count: 3,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
start: '2024-01-01T00:00:00Z',
|
|
||||||
success_count: 10,
|
|
||||||
failure_count: 5,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const result = mapWebhookAnalyticsResultToNivoLineInput(input);
|
|
||||||
|
|
||||||
// Check that dates in data arrays maintain input order
|
|
||||||
expect(result[0].data[0].x).toEqual(new Date('2024-01-02T00:00:00Z'));
|
|
||||||
expect(result[0].data[1].x).toEqual(new Date('2024-01-01T00:00:00Z'));
|
|
||||||
expect(result[1].data[0].x).toEqual(new Date('2024-01-02T00:00:00Z'));
|
|
||||||
expect(result[1].data[1].x).toEqual(new Date('2024-01-01T00:00:00Z'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle malformed dates by creating invalid Date objects', () => {
|
|
||||||
const input = [
|
|
||||||
{
|
|
||||||
start: 'invalid-date',
|
|
||||||
success_count: 10,
|
|
||||||
failure_count: 5,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const result = mapWebhookAnalyticsResultToNivoLineInput(input);
|
|
||||||
|
|
||||||
expect(result[0].data[0].x.toString()).toBe('Invalid Date');
|
|
||||||
expect(result[1].data[0].x.toString()).toBe('Invalid Date');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should maintain consistent structure with mixed data', () => {
|
|
||||||
const input = [
|
|
||||||
{
|
|
||||||
start: '2024-01-01T00:00:00Z',
|
|
||||||
success_count: 10,
|
|
||||||
failure_count: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
start: '2024-01-02T00:00:00Z',
|
|
||||||
success_count: 0,
|
|
||||||
failure_count: 5,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const result = mapWebhookAnalyticsResultToNivoLineInput(input);
|
|
||||||
|
|
||||||
// Check both lines exist even when one has zero values
|
|
||||||
expect(result.length).toBe(2);
|
|
||||||
expect(result[0].data.length).toBe(2);
|
|
||||||
expect(result[1].data.length).toBe(2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
import { mapServerlessFunctionDurationToNivoLineInput } from '@/analytics/utils/mapServerlessFunctionDurationToNivoLineInput';
|
|
||||||
import { mapServerlessFunctionErrorsToNivoLineInput } from '@/analytics/utils/mapServerlessFunctionErrorsToNivoLineInput';
|
|
||||||
import { mapWebhookAnalyticsResultToNivoLineInput } from '@/analytics/utils/mapWebhookAnalyticsResultToNivoLineInput';
|
|
||||||
import { AnalyticsTinybirdJwtMap } from '~/generated-metadata/graphql';
|
|
||||||
|
|
||||||
export const computeAnalyticsGraphDataFunction = (
|
|
||||||
endpointName: keyof AnalyticsTinybirdJwtMap,
|
|
||||||
) => {
|
|
||||||
switch (endpointName) {
|
|
||||||
case 'getWebhookAnalytics':
|
|
||||||
return mapWebhookAnalyticsResultToNivoLineInput;
|
|
||||||
case 'getServerlessFunctionDuration':
|
|
||||||
return mapServerlessFunctionDurationToNivoLineInput;
|
|
||||||
case 'getServerlessFunctionErrorCount':
|
|
||||||
return (data: { start: string; error_count: number }[]) =>
|
|
||||||
mapServerlessFunctionErrorsToNivoLineInput(data, 'ErrorCount');
|
|
||||||
case 'getServerlessFunctionSuccessRate':
|
|
||||||
return (data: { start: string; success_rate: number }[]) =>
|
|
||||||
mapServerlessFunctionErrorsToNivoLineInput(data, 'SuccessRate');
|
|
||||||
default:
|
|
||||||
throw new Error(
|
|
||||||
`No analytics function found associated with endpoint "${endpointName}"`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
import { subDays, subHours } from 'date-fns';
|
|
||||||
|
|
||||||
export const computeStartEndDate = (
|
|
||||||
windowLength: '7D' | '1D' | '12H' | '4H',
|
|
||||||
) => {
|
|
||||||
const now = new Date(Date.now());
|
|
||||||
const end = now.toISOString();
|
|
||||||
switch (windowLength) {
|
|
||||||
case '7D':
|
|
||||||
return {
|
|
||||||
start: subDays(now, 7).toISOString(),
|
|
||||||
end,
|
|
||||||
};
|
|
||||||
case '1D':
|
|
||||||
return {
|
|
||||||
start: subDays(now, 1).toISOString(),
|
|
||||||
end,
|
|
||||||
};
|
|
||||||
case '12H':
|
|
||||||
return {
|
|
||||||
start: subHours(now, 12).toISOString(),
|
|
||||||
end,
|
|
||||||
};
|
|
||||||
case '4H':
|
|
||||||
return {
|
|
||||||
start: subHours(now, 4).toISOString(),
|
|
||||||
end,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
import { ANALYTICS_ENDPOINT_TYPE_MAP } from '@/analytics/constants/AnalyticsEndpointTypeMap';
|
|
||||||
import { ANALYTICS_GRAPH_OPTION_MAP } from '@/analytics/constants/AnalyticsGraphOptionMap';
|
|
||||||
import { AnalyticsComponentProps } from '@/analytics/types/AnalyticsComponentProps';
|
|
||||||
import { computeStartEndDate } from '@/analytics/utils/computeStartEndDate';
|
|
||||||
|
|
||||||
type fetchGraphDataOrThrowProps = AnalyticsComponentProps & {
|
|
||||||
windowLength: '7D' | '1D' | '12H' | '4H';
|
|
||||||
tinybirdJwt: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const fetchGraphDataOrThrow = async ({
|
|
||||||
recordId,
|
|
||||||
windowLength,
|
|
||||||
tinybirdJwt,
|
|
||||||
endpointName,
|
|
||||||
}: fetchGraphDataOrThrowProps) => {
|
|
||||||
const recordType = ANALYTICS_ENDPOINT_TYPE_MAP[endpointName];
|
|
||||||
const queryString = new URLSearchParams({
|
|
||||||
...ANALYTICS_GRAPH_OPTION_MAP[windowLength],
|
|
||||||
...computeStartEndDate(windowLength),
|
|
||||||
...{ [`${recordType}Id`]: recordId },
|
|
||||||
}).toString();
|
|
||||||
|
|
||||||
const response = await fetch(
|
|
||||||
`https://api.eu-central-1.aws.tinybird.co/v0/pipes/${endpointName}.json?${queryString}`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: 'Bearer ' + tinybirdJwt,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
const result = await response.json();
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(result.error);
|
|
||||||
}
|
|
||||||
return result.data;
|
|
||||||
};
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
import { NivoLineInput } from '@/analytics/types/NivoLineInput';
|
|
||||||
//DOING: Adding the servelessFunctionDurationGraph to twenty
|
|
||||||
export const mapServerlessFunctionDurationToNivoLineInput = (
|
|
||||||
serverlessFunctionDurationResult: {
|
|
||||||
start: string;
|
|
||||||
minimum: number;
|
|
||||||
maximum: number;
|
|
||||||
average: number;
|
|
||||||
}[],
|
|
||||||
): NivoLineInput[] => {
|
|
||||||
return serverlessFunctionDurationResult
|
|
||||||
.flatMap((dataRow) => [
|
|
||||||
{
|
|
||||||
x: new Date(dataRow.start),
|
|
||||||
y: dataRow.maximum,
|
|
||||||
id: 'Maximum',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
x: new Date(dataRow.start),
|
|
||||||
y: dataRow.minimum,
|
|
||||||
id: 'Minimum',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
x: new Date(dataRow.start),
|
|
||||||
y: dataRow.average,
|
|
||||||
id: 'Average',
|
|
||||||
},
|
|
||||||
])
|
|
||||||
.reduce(
|
|
||||||
(
|
|
||||||
acc: NivoLineInput[],
|
|
||||||
{ id, x, y }: { id: string; x: Date; y: number },
|
|
||||||
) => {
|
|
||||||
const existingGroupIndex = acc.findIndex((group) => group.id === id);
|
|
||||||
const isExistingGroup = existingGroupIndex !== -1;
|
|
||||||
|
|
||||||
if (isExistingGroup) {
|
|
||||||
return acc.map((group, index) =>
|
|
||||||
index === existingGroupIndex
|
|
||||||
? { ...group, data: [...group.data, { x, y }] }
|
|
||||||
: group,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return [...acc, { id, data: [{ x, y }] }];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
import { NivoLineInput } from '@/analytics/types/NivoLineInput';
|
|
||||||
|
|
||||||
export const mapServerlessFunctionErrorsToNivoLineInput = <
|
|
||||||
T extends { start: string },
|
|
||||||
>(
|
|
||||||
serverlessFunctionResult: (T & {
|
|
||||||
error_count?: number;
|
|
||||||
success_rate?: number;
|
|
||||||
})[],
|
|
||||||
type: 'ErrorCount' | 'SuccessRate',
|
|
||||||
): NivoLineInput[] => {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
id: type === 'ErrorCount' ? 'Error' : 'Success Rate',
|
|
||||||
data: serverlessFunctionResult.flatMap((dataRow) => [
|
|
||||||
{
|
|
||||||
x: new Date(dataRow.start),
|
|
||||||
y:
|
|
||||||
type === 'ErrorCount'
|
|
||||||
? (dataRow.error_count ?? 0)
|
|
||||||
: (dataRow.success_rate ?? 0),
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
};
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
import { NivoLineInput } from '@/analytics/types/NivoLineInput';
|
|
||||||
|
|
||||||
export const mapWebhookAnalyticsResultToNivoLineInput = (
|
|
||||||
webhookAnalyticsResult: {
|
|
||||||
start: string;
|
|
||||||
failure_count: number;
|
|
||||||
success_count: number;
|
|
||||||
}[],
|
|
||||||
): NivoLineInput[] => {
|
|
||||||
return webhookAnalyticsResult
|
|
||||||
.flatMap((dataRow) => [
|
|
||||||
{
|
|
||||||
x: new Date(dataRow.start),
|
|
||||||
y: dataRow.failure_count,
|
|
||||||
id: 'Failed',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
x: new Date(dataRow.start),
|
|
||||||
y: dataRow.success_count,
|
|
||||||
id: 'Succeeded',
|
|
||||||
},
|
|
||||||
])
|
|
||||||
.reduce(
|
|
||||||
(
|
|
||||||
acc: NivoLineInput[],
|
|
||||||
{ id, x, y }: { id: string; x: Date; y: number },
|
|
||||||
) => {
|
|
||||||
const existingGroupIndex = acc.findIndex((group) => group.id === id);
|
|
||||||
const isExistingGroup = existingGroupIndex !== -1;
|
|
||||||
|
|
||||||
if (isExistingGroup) {
|
|
||||||
return acc.map((group, index) =>
|
|
||||||
index === existingGroupIndex
|
|
||||||
? { ...group, data: [...group.data, { x, y }] }
|
|
||||||
: group,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return [...acc, { id, data: [{ x, y }] }];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@ -7,7 +7,6 @@ export type CurrentUser = Pick<
|
|||||||
| 'id'
|
| 'id'
|
||||||
| 'email'
|
| 'email'
|
||||||
| 'supportUserHash'
|
| 'supportUserHash'
|
||||||
| 'analyticsTinybirdJwts'
|
|
||||||
| 'canAccessFullAdminPanel'
|
| 'canAccessFullAdminPanel'
|
||||||
| 'canImpersonate'
|
| 'canImpersonate'
|
||||||
| 'onboardingStatus'
|
| 'onboardingStatus'
|
||||||
|
|||||||
@ -132,14 +132,6 @@ export const queries = {
|
|||||||
canAccessFullAdminPanel
|
canAccessFullAdminPanel
|
||||||
canImpersonate
|
canImpersonate
|
||||||
supportUserHash
|
supportUserHash
|
||||||
analyticsTinybirdJwts {
|
|
||||||
getWebhookAnalytics
|
|
||||||
getPageviewsAnalytics
|
|
||||||
getUsersAnalytics
|
|
||||||
getServerlessFunctionDuration
|
|
||||||
getServerlessFunctionSuccessRate
|
|
||||||
getServerlessFunctionErrorCount
|
|
||||||
}
|
|
||||||
onboardingStatus
|
onboardingStatus
|
||||||
workspaceMember {
|
workspaceMember {
|
||||||
...WorkspaceMemberQueryFragment
|
...WorkspaceMemberQueryFragment
|
||||||
@ -289,14 +281,6 @@ export const responseData = {
|
|||||||
canAccessFullAdminPanel: false,
|
canAccessFullAdminPanel: false,
|
||||||
canImpersonate: false,
|
canImpersonate: false,
|
||||||
supportUserHash: null,
|
supportUserHash: null,
|
||||||
analyticsTinybirdJwts: {
|
|
||||||
getWebhookAnalytics: null,
|
|
||||||
getPageviewsAnalytics: null,
|
|
||||||
getUsersAnalytics: null,
|
|
||||||
getServerlessFunctionDuration: null,
|
|
||||||
getServerlessFunctionSuccessRate: null,
|
|
||||||
getServerlessFunctionErrorCount: null,
|
|
||||||
},
|
|
||||||
onboardingStatus: 'completed',
|
onboardingStatus: 'completed',
|
||||||
workspaceMember: {
|
workspaceMember: {
|
||||||
id: 'test-workspace-member-id',
|
id: 'test-workspace-member-id',
|
||||||
|
|||||||
@ -19,7 +19,6 @@ const mockCurrentUser = {
|
|||||||
id: 'fake-user-id',
|
id: 'fake-user-id',
|
||||||
email: 'fake@email.com',
|
email: 'fake@email.com',
|
||||||
supportUserHash: null,
|
supportUserHash: null,
|
||||||
analyticsTinybirdJwts: null,
|
|
||||||
canAccessFullAdminPanel: false,
|
canAccessFullAdminPanel: false,
|
||||||
canImpersonate: false,
|
canImpersonate: false,
|
||||||
onboardingStatus: OnboardingStatus.COMPLETED,
|
onboardingStatus: OnboardingStatus.COMPLETED,
|
||||||
|
|||||||
@ -1,74 +0,0 @@
|
|||||||
import { AnalyticsActivityGraph } from '@/analytics/components/AnalyticsActivityGraph';
|
|
||||||
import { AnalyticsGraphEffect } from '@/analytics/components/AnalyticsGraphEffect';
|
|
||||||
import { AnalyticsGraphDataInstanceContext } from '@/analytics/states/contexts/AnalyticsGraphDataInstanceContext';
|
|
||||||
import { SettingsServerlessFunctionHotkeyScope } from '@/settings/serverless-functions/types/SettingsServerlessFunctionHotKeyScope';
|
|
||||||
import { SettingsPath } from '@/types/SettingsPath';
|
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
|
||||||
import { Key } from 'ts-key-enum';
|
|
||||||
import { useHotkeyScopeOnMount } from '~/hooks/useHotkeyScopeOnMount';
|
|
||||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
|
||||||
|
|
||||||
export const SettingsServerlessFunctionMonitoringTab = ({
|
|
||||||
serverlessFunctionId,
|
|
||||||
}: {
|
|
||||||
serverlessFunctionId: string;
|
|
||||||
}) => {
|
|
||||||
const navigate = useNavigateSettings();
|
|
||||||
|
|
||||||
useHotkeyScopeOnMount(
|
|
||||||
SettingsServerlessFunctionHotkeyScope.ServerlessFunctionSettingsTab,
|
|
||||||
);
|
|
||||||
|
|
||||||
useScopedHotkeys(
|
|
||||||
[Key.Escape],
|
|
||||||
() => {
|
|
||||||
navigate(SettingsPath.ServerlessFunctions);
|
|
||||||
},
|
|
||||||
SettingsServerlessFunctionHotkeyScope.ServerlessFunctionSettingsTab,
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<AnalyticsGraphDataInstanceContext.Provider
|
|
||||||
value={{
|
|
||||||
instanceId: `function-${serverlessFunctionId}-errorCount`,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<AnalyticsGraphEffect
|
|
||||||
recordId={serverlessFunctionId}
|
|
||||||
endpointName="getServerlessFunctionErrorCount"
|
|
||||||
/>
|
|
||||||
<AnalyticsActivityGraph
|
|
||||||
recordId={serverlessFunctionId}
|
|
||||||
endpointName="getServerlessFunctionErrorCount"
|
|
||||||
/>
|
|
||||||
</AnalyticsGraphDataInstanceContext.Provider>
|
|
||||||
|
|
||||||
<AnalyticsGraphDataInstanceContext.Provider
|
|
||||||
value={{ instanceId: `function-${serverlessFunctionId}-duration` }}
|
|
||||||
>
|
|
||||||
<AnalyticsGraphEffect
|
|
||||||
recordId={serverlessFunctionId}
|
|
||||||
endpointName="getServerlessFunctionDuration"
|
|
||||||
/>
|
|
||||||
<AnalyticsActivityGraph
|
|
||||||
recordId={serverlessFunctionId}
|
|
||||||
endpointName="getServerlessFunctionDuration"
|
|
||||||
/>
|
|
||||||
</AnalyticsGraphDataInstanceContext.Provider>
|
|
||||||
|
|
||||||
<AnalyticsGraphDataInstanceContext.Provider
|
|
||||||
value={{ instanceId: `function-${serverlessFunctionId}-successRate` }}
|
|
||||||
>
|
|
||||||
<AnalyticsGraphEffect
|
|
||||||
recordId={serverlessFunctionId}
|
|
||||||
endpointName="getServerlessFunctionSuccessRate"
|
|
||||||
/>
|
|
||||||
<AnalyticsActivityGraph
|
|
||||||
recordId={serverlessFunctionId}
|
|
||||||
endpointName="getServerlessFunctionSuccessRate"
|
|
||||||
/>
|
|
||||||
</AnalyticsGraphDataInstanceContext.Provider>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@ -12,14 +12,6 @@ export const USER_QUERY_FRAGMENT = gql`
|
|||||||
canAccessFullAdminPanel
|
canAccessFullAdminPanel
|
||||||
canImpersonate
|
canImpersonate
|
||||||
supportUserHash
|
supportUserHash
|
||||||
analyticsTinybirdJwts {
|
|
||||||
getWebhookAnalytics
|
|
||||||
getPageviewsAnalytics
|
|
||||||
getUsersAnalytics
|
|
||||||
getServerlessFunctionDuration
|
|
||||||
getServerlessFunctionSuccessRate
|
|
||||||
getServerlessFunctionErrorCount
|
|
||||||
}
|
|
||||||
onboardingStatus
|
onboardingStatus
|
||||||
workspaceMember {
|
workspaceMember {
|
||||||
...WorkspaceMemberQueryFragment
|
...WorkspaceMemberQueryFragment
|
||||||
|
|||||||
@ -15,10 +15,6 @@ import {
|
|||||||
useIcons,
|
useIcons,
|
||||||
} from 'twenty-ui';
|
} from 'twenty-ui';
|
||||||
|
|
||||||
import { AnalyticsActivityGraph } from '@/analytics/components/AnalyticsActivityGraph';
|
|
||||||
import { AnalyticsGraphEffect } from '@/analytics/components/AnalyticsGraphEffect';
|
|
||||||
import { AnalyticsGraphDataInstanceContext } from '@/analytics/states/contexts/AnalyticsGraphDataInstanceContext';
|
|
||||||
import { isAnalyticsEnabledState } from '@/client-config/states/isAnalyticsEnabledState';
|
|
||||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||||
import { useWebhookUpdateForm } from '@/settings/developers/hooks/useWebhookUpdateForm';
|
import { useWebhookUpdateForm } from '@/settings/developers/hooks/useWebhookUpdateForm';
|
||||||
@ -28,10 +24,7 @@ import { TextArea } from '@/ui/input/components/TextArea';
|
|||||||
import { TextInput } from '@/ui/input/components/TextInput';
|
import { TextInput } from '@/ui/input/components/TextInput';
|
||||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
||||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
|
||||||
import { Trans, useLingui } from '@lingui/react/macro';
|
import { Trans, useLingui } from '@lingui/react/macro';
|
||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
import { FeatureFlagKey } from '~/generated/graphql';
|
|
||||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||||
import { isDefined } from 'twenty-shared/utils';
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
|
|
||||||
@ -61,8 +54,6 @@ export const SettingsDevelopersWebhooksDetail = () => {
|
|||||||
|
|
||||||
const { objectMetadataItems } = useObjectMetadataItems();
|
const { objectMetadataItems } = useObjectMetadataItems();
|
||||||
|
|
||||||
const isAnalyticsEnabled = useRecoilValue(isAnalyticsEnabledState);
|
|
||||||
|
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
|
||||||
const { getIcon } = useIcons();
|
const { getIcon } = useIcons();
|
||||||
@ -90,10 +81,6 @@ export const SettingsDevelopersWebhooksDetail = () => {
|
|||||||
const [isDeleteWebhookModalOpen, setIsDeleteWebhookModalOpen] =
|
const [isDeleteWebhookModalOpen, setIsDeleteWebhookModalOpen] =
|
||||||
useState(false);
|
useState(false);
|
||||||
|
|
||||||
const isAnalyticsV2Enabled = useIsFeatureEnabled(
|
|
||||||
FeatureFlagKey.IsAnalyticsV2Enabled,
|
|
||||||
);
|
|
||||||
|
|
||||||
const fieldTypeOptions: SelectOption<string>[] = useMemo(
|
const fieldTypeOptions: SelectOption<string>[] = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{ value: '*', label: t`All Objects`, Icon: IconNorthStar },
|
{ value: '*', label: t`All Objects`, Icon: IconNorthStar },
|
||||||
@ -223,20 +210,6 @@ export const SettingsDevelopersWebhooksDetail = () => {
|
|||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
</Section>
|
</Section>
|
||||||
{!isCreationMode && isAnalyticsEnabled && isAnalyticsV2Enabled && (
|
|
||||||
<AnalyticsGraphDataInstanceContext.Provider
|
|
||||||
value={{ instanceId: `webhook-${webhookId}-analytics` }}
|
|
||||||
>
|
|
||||||
<AnalyticsGraphEffect
|
|
||||||
recordId={webhookId}
|
|
||||||
endpointName="getWebhookAnalytics"
|
|
||||||
/>
|
|
||||||
<AnalyticsActivityGraph
|
|
||||||
recordId={webhookId}
|
|
||||||
endpointName="getWebhookAnalytics"
|
|
||||||
/>
|
|
||||||
</AnalyticsGraphDataInstanceContext.Provider>
|
|
||||||
)}
|
|
||||||
<Section>
|
<Section>
|
||||||
<H2Title
|
<H2Title
|
||||||
title={t`Danger zone`}
|
title={t`Danger zone`}
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
import { isAnalyticsEnabledState } from '@/client-config/states/isAnalyticsEnabledState';
|
|
||||||
import { useTestServerlessFunction } from '@/serverless-functions/hooks/useTestServerlessFunction';
|
import { useTestServerlessFunction } from '@/serverless-functions/hooks/useTestServerlessFunction';
|
||||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||||
import { SettingsServerlessFunctionCodeEditorTab } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionCodeEditorTab';
|
import { SettingsServerlessFunctionCodeEditorTab } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionCodeEditorTab';
|
||||||
import { SettingsServerlessFunctionMonitoringTab } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionMonitoringTab';
|
|
||||||
import { SettingsServerlessFunctionSettingsTab } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionSettingsTab';
|
import { SettingsServerlessFunctionSettingsTab } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionSettingsTab';
|
||||||
import { SettingsServerlessFunctionTestTab } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTestTab';
|
import { SettingsServerlessFunctionTestTab } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTestTab';
|
||||||
import { useGetOneServerlessFunctionSourceCode } from '@/settings/serverless-functions/hooks/useGetOneServerlessFunctionSourceCode';
|
import { useGetOneServerlessFunctionSourceCode } from '@/settings/serverless-functions/hooks/useGetOneServerlessFunctionSourceCode';
|
||||||
@ -16,13 +14,10 @@ import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBa
|
|||||||
import { TabList } from '@/ui/layout/tab/components/TabList';
|
import { TabList } from '@/ui/layout/tab/components/TabList';
|
||||||
import { activeTabIdComponentState } from '@/ui/layout/tab/states/activeTabIdComponentState';
|
import { activeTabIdComponentState } from '@/ui/layout/tab/states/activeTabIdComponentState';
|
||||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { IconCode, IconSettings, IconTestPipe } from 'twenty-ui';
|
||||||
import { IconCode, IconGauge, IconSettings, IconTestPipe } from 'twenty-ui';
|
|
||||||
import { useDebouncedCallback } from 'use-debounce';
|
import { useDebouncedCallback } from 'use-debounce';
|
||||||
import { FeatureFlagKey } from '~/generated/graphql';
|
|
||||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||||
import { isDefined } from 'twenty-shared/utils';
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
@ -126,19 +121,10 @@ export const SettingsServerlessFunctionDetail = () => {
|
|||||||
setActiveTabId('test');
|
setActiveTabId('test');
|
||||||
};
|
};
|
||||||
|
|
||||||
const isAnalyticsEnabled = useRecoilValue(isAnalyticsEnabledState);
|
|
||||||
|
|
||||||
const isAnalyticsV2Enabled = useIsFeatureEnabled(
|
|
||||||
FeatureFlagKey.IsAnalyticsV2Enabled,
|
|
||||||
);
|
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{ id: 'editor', title: 'Editor', Icon: IconCode },
|
{ id: 'editor', title: 'Editor', Icon: IconCode },
|
||||||
{ id: 'test', title: 'Test', Icon: IconTestPipe },
|
{ id: 'test', title: 'Test', Icon: IconTestPipe },
|
||||||
{ id: 'settings', title: 'Settings', Icon: IconSettings },
|
{ id: 'settings', title: 'Settings', Icon: IconSettings },
|
||||||
...(isAnalyticsEnabled && isAnalyticsV2Enabled
|
|
||||||
? [{ id: 'monitoring', title: 'Monitoring', Icon: IconGauge }]
|
|
||||||
: []),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const files = formValues.code
|
const files = formValues.code
|
||||||
@ -184,12 +170,6 @@ export const SettingsServerlessFunctionDetail = () => {
|
|||||||
onCodeChange={onCodeChange}
|
onCodeChange={onCodeChange}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case 'monitoring':
|
|
||||||
return (
|
|
||||||
<SettingsServerlessFunctionMonitoringTab
|
|
||||||
serverlessFunctionId={serverlessFunctionId}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
default:
|
default:
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,6 @@ type MockedUser = Pick<
|
|||||||
| 'supportUserHash'
|
| 'supportUserHash'
|
||||||
| 'onboardingStatus'
|
| 'onboardingStatus'
|
||||||
| 'userVars'
|
| 'userVars'
|
||||||
| 'analyticsTinybirdJwts'
|
|
||||||
> & {
|
> & {
|
||||||
workspaceMember: WorkspaceMember | null;
|
workspaceMember: WorkspaceMember | null;
|
||||||
locale: string;
|
locale: string;
|
||||||
@ -138,7 +137,6 @@ export const mockedUserData: MockedUser = {
|
|||||||
workspaceMembers: [mockedWorkspaceMemberData],
|
workspaceMembers: [mockedWorkspaceMemberData],
|
||||||
onboardingStatus: OnboardingStatus.COMPLETED,
|
onboardingStatus: OnboardingStatus.COMPLETED,
|
||||||
userVars: {},
|
userVars: {},
|
||||||
analyticsTinybirdJwts: null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mockedOnboardingUserData = (
|
export const mockedOnboardingUserData = (
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { HttpModule } from '@nestjs/axios';
|
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { JwtModule } from 'src/engine/core-modules/jwt/jwt.module';
|
import { JwtModule } from 'src/engine/core-modules/jwt/jwt.module';
|
||||||
@ -6,16 +5,9 @@ import { JwtModule } from 'src/engine/core-modules/jwt/jwt.module';
|
|||||||
import { AnalyticsResolver } from './analytics.resolver';
|
import { AnalyticsResolver } from './analytics.resolver';
|
||||||
import { AnalyticsService } from './analytics.service';
|
import { AnalyticsService } from './analytics.service';
|
||||||
|
|
||||||
const TINYBIRD_BASE_URL = 'https://api.eu-central-1.aws.tinybird.co/v0';
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [AnalyticsResolver, AnalyticsService],
|
providers: [AnalyticsResolver, AnalyticsService],
|
||||||
imports: [
|
imports: [JwtModule],
|
||||||
JwtModule,
|
|
||||||
HttpModule.register({
|
|
||||||
baseURL: TINYBIRD_BASE_URL,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
exports: [AnalyticsService],
|
exports: [AnalyticsService],
|
||||||
})
|
})
|
||||||
export class AnalyticsModule {}
|
export class AnalyticsModule {}
|
||||||
|
|||||||
@ -1,11 +1,6 @@
|
|||||||
import { HttpService } from '@nestjs/axios';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { Injectable, Logger } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { AxiosRequestConfig } from 'axios';
|
|
||||||
|
|
||||||
import { AnalyticsTinybirdJwtMap } from 'src/engine/core-modules/analytics/entities/analytics-tinybird-jwts.entity';
|
|
||||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||||
import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service';
|
|
||||||
|
|
||||||
type CreateEventInput = {
|
type CreateEventInput = {
|
||||||
action: string;
|
action: string;
|
||||||
@ -14,14 +9,7 @@ type CreateEventInput = {
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AnalyticsService {
|
export class AnalyticsService {
|
||||||
private readonly logger = new Logger(AnalyticsService.name);
|
constructor(private readonly environmentService: EnvironmentService) {}
|
||||||
private readonly defaultDatasource = 'event';
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private readonly jwtWrapperService: JwtWrapperService,
|
|
||||||
private readonly environmentService: EnvironmentService,
|
|
||||||
private readonly httpService: HttpService,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async create(
|
async create(
|
||||||
createEventInput: CreateEventInput,
|
createEventInput: CreateEventInput,
|
||||||
@ -32,11 +20,11 @@ export class AnalyticsService {
|
|||||||
return { success: true };
|
return { success: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
let data;
|
let _data;
|
||||||
|
|
||||||
switch (createEventInput.action) {
|
switch (createEventInput.action) {
|
||||||
case 'pageview':
|
case 'pageview':
|
||||||
data = {
|
_data = {
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
version: '1',
|
version: '1',
|
||||||
userId: userId,
|
userId: userId,
|
||||||
@ -45,7 +33,7 @@ export class AnalyticsService {
|
|||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
data = {
|
_data = {
|
||||||
action: createEventInput.action,
|
action: createEventInput.action,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
version: '1',
|
version: '1',
|
||||||
@ -58,88 +46,8 @@ export class AnalyticsService {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const config: AxiosRequestConfig = {
|
// TODO: send event to clickhouse
|
||||||
headers: {
|
|
||||||
Authorization:
|
|
||||||
'Bearer ' + this.environmentService.get('TINYBIRD_INGEST_TOKEN'),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const datasource =
|
|
||||||
createEventInput.action === 'pageview'
|
|
||||||
? 'pageview'
|
|
||||||
: this.defaultDatasource;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.httpService.axiosRef.post(
|
|
||||||
`/events?name=${datasource}`,
|
|
||||||
data,
|
|
||||||
config,
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
this.logger.error('Error occurred:', error);
|
|
||||||
if (error.response) {
|
|
||||||
this.logger.error(
|
|
||||||
`Error response body: ${JSON.stringify(error.response.data)}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return { success: false };
|
|
||||||
}
|
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
generateWorkspaceJwt(
|
|
||||||
workspaceId: string | undefined,
|
|
||||||
): AnalyticsTinybirdJwtMap | null {
|
|
||||||
if (!this.environmentService.get('ANALYTICS_ENABLED')) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const jwtPayload = {
|
|
||||||
name: 'analytics_jwt',
|
|
||||||
workspace_id: this.environmentService.get('TINYBIRD_WORKSPACE_UUID'),
|
|
||||||
scopes: [
|
|
||||||
{
|
|
||||||
type: 'PIPES:READ',
|
|
||||||
resource: '',
|
|
||||||
fixed_params: { workspaceId },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const jwtOptions = {
|
|
||||||
secret: this.environmentService.get('TINYBIRD_GENERATE_JWT_TOKEN'),
|
|
||||||
expiresIn: '7d',
|
|
||||||
};
|
|
||||||
|
|
||||||
const analyticsProperties = [
|
|
||||||
'getWebhookAnalytics',
|
|
||||||
'getPageviewsAnalytics',
|
|
||||||
'getUsersAnalytics',
|
|
||||||
'getServerlessFunctionDuration',
|
|
||||||
'getServerlessFunctionSuccessRate',
|
|
||||||
'getServerlessFunctionErrorCount',
|
|
||||||
];
|
|
||||||
|
|
||||||
return analyticsProperties.reduce(
|
|
||||||
(acc, property) => ({
|
|
||||||
...acc,
|
|
||||||
[property]: this.jwtWrapperService.sign(
|
|
||||||
{
|
|
||||||
...jwtPayload,
|
|
||||||
scopes: [
|
|
||||||
{
|
|
||||||
...jwtPayload.scopes[0],
|
|
||||||
resource: property,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
jwtOptions,
|
|
||||||
),
|
|
||||||
}),
|
|
||||||
{},
|
|
||||||
) as AnalyticsTinybirdJwtMap;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,22 +0,0 @@
|
|||||||
import { Field, ObjectType } from '@nestjs/graphql';
|
|
||||||
|
|
||||||
@ObjectType()
|
|
||||||
export class AnalyticsTinybirdJwtMap {
|
|
||||||
@Field(() => String)
|
|
||||||
getWebhookAnalytics: string;
|
|
||||||
|
|
||||||
@Field(() => String)
|
|
||||||
getPageviewsAnalytics: string;
|
|
||||||
|
|
||||||
@Field(() => String)
|
|
||||||
getUsersAnalytics: string;
|
|
||||||
|
|
||||||
@Field(() => String)
|
|
||||||
getServerlessFunctionDuration: string;
|
|
||||||
|
|
||||||
@Field(() => String)
|
|
||||||
getServerlessFunctionSuccessRate: string;
|
|
||||||
|
|
||||||
@Field(() => String)
|
|
||||||
getServerlessFunctionErrorCount: string;
|
|
||||||
}
|
|
||||||
@ -101,7 +101,7 @@ export const ENVIRONMENT_VARIABLES_GROUP_METADATA: Record<
|
|||||||
'We use this to setup a small support chat on the bottom left. Currently powered by Front.',
|
'We use this to setup a small support chat on the bottom left. Currently powered by Front.',
|
||||||
isHiddenOnLoad: true,
|
isHiddenOnLoad: true,
|
||||||
},
|
},
|
||||||
[EnvironmentVariablesGroup.TinybirdConfig]: {
|
[EnvironmentVariablesGroup.AnalyticsConfig]: {
|
||||||
position: 1700,
|
position: 1700,
|
||||||
description:
|
description:
|
||||||
'We’re running a test to perform analytics within the app. This will evolve.',
|
'We’re running a test to perform analytics within the app. This will evolve.',
|
||||||
|
|||||||
@ -15,6 +15,6 @@ export enum EnvironmentVariablesGroup {
|
|||||||
ServerlessConfig = 'serverless-config',
|
ServerlessConfig = 'serverless-config',
|
||||||
SSL = 'ssl',
|
SSL = 'ssl',
|
||||||
SupportChatConfig = 'support-chat-config',
|
SupportChatConfig = 'support-chat-config',
|
||||||
TinybirdConfig = 'tinybird-config',
|
AnalyticsConfig = 'analytics-config',
|
||||||
TokensDuration = 'tokens-duration',
|
TokensDuration = 'tokens-duration',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -453,7 +453,7 @@ export class EnvironmentVariables {
|
|||||||
SERVERLESS_LAMBDA_SECRET_ACCESS_KEY: string;
|
SERVERLESS_LAMBDA_SECRET_ACCESS_KEY: string;
|
||||||
|
|
||||||
@EnvironmentVariablesMetadata({
|
@EnvironmentVariablesMetadata({
|
||||||
group: EnvironmentVariablesGroup.TinybirdConfig,
|
group: EnvironmentVariablesGroup.AnalyticsConfig,
|
||||||
description: 'Enable or disable analytics for telemetry',
|
description: 'Enable or disable analytics for telemetry',
|
||||||
})
|
})
|
||||||
@CastToBoolean()
|
@CastToBoolean()
|
||||||
@ -470,33 +470,6 @@ export class EnvironmentVariables {
|
|||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
TELEMETRY_ENABLED = true;
|
TELEMETRY_ENABLED = true;
|
||||||
|
|
||||||
@EnvironmentVariablesMetadata({
|
|
||||||
group: EnvironmentVariablesGroup.TinybirdConfig,
|
|
||||||
sensitive: true,
|
|
||||||
description: 'Ingest token for Tinybird analytics',
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@ValidateIf((env) => env.ANALYTICS_ENABLED)
|
|
||||||
TINYBIRD_INGEST_TOKEN: string;
|
|
||||||
|
|
||||||
@EnvironmentVariablesMetadata({
|
|
||||||
group: EnvironmentVariablesGroup.TinybirdConfig,
|
|
||||||
sensitive: true,
|
|
||||||
description: 'Workspace UUID for Tinybird analytics',
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@ValidateIf((env) => env.ANALYTICS_ENABLED)
|
|
||||||
TINYBIRD_WORKSPACE_UUID: string;
|
|
||||||
|
|
||||||
@EnvironmentVariablesMetadata({
|
|
||||||
group: EnvironmentVariablesGroup.TinybirdConfig,
|
|
||||||
sensitive: true,
|
|
||||||
description: 'JWT token for Tinybird analytics',
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@ValidateIf((env) => env.ANALYTICS_ENABLED)
|
|
||||||
TINYBIRD_GENERATE_JWT_TOKEN: string;
|
|
||||||
|
|
||||||
@EnvironmentVariablesMetadata({
|
@EnvironmentVariablesMetadata({
|
||||||
group: EnvironmentVariablesGroup.BillingConfig,
|
group: EnvironmentVariablesGroup.BillingConfig,
|
||||||
description: 'Enable or disable billing features',
|
description: 'Enable or disable billing features',
|
||||||
|
|||||||
@ -20,7 +20,6 @@ import { SupportDriver } from 'src/engine/core-modules/environment/interfaces/su
|
|||||||
import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.interface';
|
import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.interface';
|
||||||
|
|
||||||
import { AnalyticsService } from 'src/engine/core-modules/analytics/analytics.service';
|
import { AnalyticsService } from 'src/engine/core-modules/analytics/analytics.service';
|
||||||
import { AnalyticsTinybirdJwtMap } from 'src/engine/core-modules/analytics/entities/analytics-tinybird-jwts.entity';
|
|
||||||
import {
|
import {
|
||||||
AuthException,
|
AuthException,
|
||||||
AuthExceptionCode,
|
AuthExceptionCode,
|
||||||
@ -280,11 +279,6 @@ export class UserResolver {
|
|||||||
return getHMACKey(parent.email, key);
|
return getHMACKey(parent.email, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ResolveField(() => AnalyticsTinybirdJwtMap, { nullable: true })
|
|
||||||
analyticsTinybirdJwts(@AuthWorkspace() workspace: Workspace | undefined) {
|
|
||||||
return this.analyticsService.generateWorkspaceJwt(workspace?.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Mutation(() => String)
|
@Mutation(() => String)
|
||||||
async uploadProfilePicture(
|
async uploadProfilePicture(
|
||||||
@AuthUser() { id }: User,
|
@AuthUser() { id }: User,
|
||||||
|
|||||||
2
packages/twenty-tinybird/.gitignore
vendored
2
packages/twenty-tinybird/.gitignore
vendored
@ -1,2 +0,0 @@
|
|||||||
.tinyb
|
|
||||||
.venv
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
|
|
||||||
VERSION=0.0.0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##########
|
|
||||||
# OPTIONAL env vars
|
|
||||||
|
|
||||||
# Don't print CLI version warning message if there's a new available version
|
|
||||||
# TB_VERSION_WARNING=0
|
|
||||||
|
|
||||||
# Skip regression tests
|
|
||||||
# TB_SKIP_REGRESSION=0
|
|
||||||
|
|
||||||
# Use `OBFUSCATE_REGEX_PATTERN` and `OBFUSCATE_PATTERN_SEPARATOR` environment variables to define a regex pattern and a separator (in case of a single string with multiple regex) to obfuscate secrets in the CLI output.
|
|
||||||
# OBFUSCATE_REGEX_PATTERN="https://(www\.)?[^/]+||^Follow these instructions =>"
|
|
||||||
# OBFUSCATE_PATTERN_SEPARATOR=||
|
|
||||||
##########
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
|
|
||||||
## How to use
|
|
||||||
Create a virtual enviroment and install tinybird
|
|
||||||
```sh
|
|
||||||
python3 -m venv .venv
|
|
||||||
source .venv/bin/activate
|
|
||||||
pip install tinybird-cli
|
|
||||||
```
|
|
||||||
Authenticate using your admin token from your workspace (twenty_analytics_cli_playground)
|
|
||||||
```sh
|
|
||||||
tb auth -i
|
|
||||||
|
|
||||||
** List of available regions:
|
|
||||||
[1] us-east4 (gcp) (https://app.us-east.tinybird.co)
|
|
||||||
[2] europe-west3 (gcp) (https://app.tinybird.co/gcp/europe-west3)
|
|
||||||
[3] us-east-1 (aws) (https://app.tinybird.co/aws/us-east-1)
|
|
||||||
[4] us-west-2 (aws) (https://app.tinybird.co/aws/us-west-2)
|
|
||||||
[5] eu-central-1 (aws) (https://app.tinybird.co/aws/eu-central-1) <- this
|
|
||||||
[0] Cancel
|
|
||||||
|
|
||||||
Use region [5]:
|
|
||||||
Copy the "admin your@email" token from from https://app.tinybird.co/tokens and paste it here: <pasted Token>
|
|
||||||
** Auth successful!
|
|
||||||
** Configuration written to .tinyb file, consider adding it to .gitignore
|
|
||||||
```
|
|
||||||
You can also log in using your twenty_analytics_token without passing into the interactive mode:
|
|
||||||
```sh
|
|
||||||
tb auth --token <your twenty_analytics_token >
|
|
||||||
** Auth successful!
|
|
||||||
** Configuration written to .tinyb file, consider adding it to .gitignore
|
|
||||||
```
|
|
||||||
To sync your changes to Tinybird use:
|
|
||||||
```sh
|
|
||||||
tb push --force --push-deps
|
|
||||||
```
|
|
||||||
To pull data from Tinybird use:
|
|
||||||
```sh
|
|
||||||
tb pull
|
|
||||||
```
|
|
||||||
Things I learned:
|
|
||||||
|
|
||||||
* When creating Materialied Views think about populating it first using the files from the fixtures
|
|
||||||
* When pushing your pipes prefer to push one by one so you can have more coherent error messages
|
|
||||||
* The Include files will be nodes that will be added at the start of your node in Tinybird UI
|
|
||||||
* It's best to stick only with only the CLI or the UI when developping in Tinybird
|
|
||||||
* If you want to format the data us the tb fmt command, perhaps we can add it to the linter in a next pull request.
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
SCHEMA >
|
|
||||||
`action` LowCardinality(String) `json:$.action`,
|
|
||||||
`timestamp` DateTime64(3) `json:$.timestamp`,
|
|
||||||
`version` LowCardinality(String) `json:$.version`,
|
|
||||||
`userId` String `json:$.userId` DEFAULT '',
|
|
||||||
`workspaceId` String `json:$.workspaceId` DEFAULT '',
|
|
||||||
`payload` String `json:$.payload`
|
|
||||||
|
|
||||||
ENGINE MergeTree
|
|
||||||
ENGINE_PARTITION_KEY toYear(timestamp)
|
|
||||||
ENGINE_SORTING_KEY action, workspaceId, timestamp
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
SCHEMA >
|
|
||||||
`href` String `json:$.href`,
|
|
||||||
`locale` LowCardinality(String) `json:$.locale`,
|
|
||||||
`pathname` String `json:$.pathname`,
|
|
||||||
`referrer` String `json:$.referrer`,
|
|
||||||
`sessionId` String `json:$.sessionId`,
|
|
||||||
`timeZone` LowCardinality(String) `json:$.timeZone`,
|
|
||||||
`timestamp` DateTime64(3) `json:$.timestamp`,
|
|
||||||
`userAgent` String `json:$.userAgent`,
|
|
||||||
`userId` String `json:$.userId` DEFAULT '',
|
|
||||||
`version` LowCardinality(String) `json:$.version`,
|
|
||||||
`workspaceId` String `json:$.workspaceId` DEFAULT ''
|
|
||||||
|
|
||||||
ENGINE MergeTree
|
|
||||||
ENGINE_PARTITION_KEY toYear(timestamp)
|
|
||||||
ENGINE_SORTING_KEY workspaceId, userId, timestamp
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
SCHEMA >
|
|
||||||
`timestamp` DateTime64(3) `json:$.timestamp`,
|
|
||||||
`workspaceId` String `json:$.workspaceId`,
|
|
||||||
`functionId` String `json:$.functionId`,
|
|
||||||
`durationInMs` Int64 `json:$.durationInMs`,
|
|
||||||
`success` Bool `json:$.success`,
|
|
||||||
`errorType` LowCardinality(String) `json:$.errorType`,
|
|
||||||
`version` LowCardinality(String) `json:$.version`
|
|
||||||
|
|
||||||
ENGINE MergeTree
|
|
||||||
ENGINE_PARTITION_KEY toYYYYMM(timestamp)
|
|
||||||
ENGINE_SORTING_KEY workspaceId, functionId, timestamp
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
SCHEMA >
|
|
||||||
`timestamp` DateTime64(3) `json:$.timestamp`,
|
|
||||||
`workspaceId` String `json:$.workspaceId`,
|
|
||||||
`webhookId` String `json:$.webhookId`,
|
|
||||||
`url` String `json:$.url`,
|
|
||||||
`success` Bool `json:$.success`,
|
|
||||||
`status` Int64 `json:$.status`,
|
|
||||||
`eventName` LowCardinality(String) `json:$.eventName`,
|
|
||||||
`version` LowCardinality(String) `json:$.version`
|
|
||||||
|
|
||||||
ENGINE MergeTree
|
|
||||||
ENGINE_PARTITION_KEY toYYYYMM(timestamp)
|
|
||||||
ENGINE_SORTING_KEY workspaceId, webhookId, timestamp
|
|
||||||
@ -1,282 +0,0 @@
|
|||||||
{"action": "apiKey.created", "timestamp": "2024-10-24 15:55:35.177", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "apiKey.created", "timestamp": "2024-10-24 15:55:35.178", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "apiKey.created", "timestamp": "2024-10-24 15:55:35.212", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "apiKey.created", "timestamp": "2024-10-24 15:57:42.810", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "apiKey.created", "timestamp": "2024-10-24 15:57:42.812", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "apiKey.created", "timestamp": "2024-10-24 15:57:42.989", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "apiKey.created", "timestamp": "2024-10-24 16:03:18.134", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "apiKey.created", "timestamp": "2024-10-24 16:03:18.135", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "apiKey.created", "timestamp": "2024-10-24 16:03:18.205", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "attachment.created", "timestamp": "2024-10-24 15:55:31.949", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "attachment.created", "timestamp": "2024-10-24 15:55:31.950", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "attachment.created", "timestamp": "2024-10-24 15:55:32.027", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "attachment.created", "timestamp": "2024-10-24 15:57:31.970", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "attachment.created", "timestamp": "2024-10-24 15:57:31.979", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "attachment.created", "timestamp": "2024-10-24 15:57:34.033", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "attachment.created", "timestamp": "2024-10-24 16:03:17.602", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "attachment.created", "timestamp": "2024-10-24 16:03:17.602", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "attachment.created", "timestamp": "2024-10-24 16:03:17.755", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "auditLog.created", "timestamp": "2024-10-24 15:55:33.498", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "auditLog.created", "timestamp": "2024-10-24 15:55:33.499", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "auditLog.created", "timestamp": "2024-10-24 15:55:33.602", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "auditLog.created", "timestamp": "2024-10-24 15:57:42.984", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "auditLog.created", "timestamp": "2024-10-24 15:57:42.986", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "auditLog.created", "timestamp": "2024-10-24 15:57:43.219", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "auditLog.created", "timestamp": "2024-10-24 16:03:19.139", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "auditLog.created", "timestamp": "2024-10-24 16:03:19.141", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "auditLog.created", "timestamp": "2024-10-24 16:03:19.289", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "blocklist.created", "timestamp": "2024-10-24 15:55:33.732", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "blocklist.created", "timestamp": "2024-10-24 15:55:33.733", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "blocklist.created", "timestamp": "2024-10-24 15:55:33.836", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "blocklist.created", "timestamp": "2024-10-24 15:57:43.255", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "blocklist.created", "timestamp": "2024-10-24 15:57:43.257", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "blocklist.created", "timestamp": "2024-10-24 15:57:43.454", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "blocklist.created", "timestamp": "2024-10-24 16:03:18.813", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "blocklist.created", "timestamp": "2024-10-24 16:03:18.814", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "blocklist.created", "timestamp": "2024-10-24 16:03:19.148", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannel.created", "timestamp": "2024-10-24 15:55:31.547", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannel.created", "timestamp": "2024-10-24 15:55:32.156", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannel.created", "timestamp": "2024-10-24 15:55:32.158", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannel.created", "timestamp": "2024-10-24 15:55:32.279", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannel.created", "timestamp": "2024-10-24 15:57:26.908", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannel.created", "timestamp": "2024-10-24 15:57:26.914", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannel.created", "timestamp": "2024-10-24 15:57:26.914", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannel.created", "timestamp": "2024-10-24 15:57:27.059", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannel.created", "timestamp": "2024-10-24 16:03:16.523", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannel.created", "timestamp": "2024-10-24 16:03:16.524", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannel.created", "timestamp": "2024-10-24 16:03:16.525", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannel.created", "timestamp": "2024-10-24 16:03:16.686", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannelEventAssociation.created", "timestamp": "2024-10-24 15:55:32.230", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannelEventAssociation.created", "timestamp": "2024-10-24 15:55:32.231", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannelEventAssociation.created", "timestamp": "2024-10-24 15:55:32.334", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannelEventAssociation.created", "timestamp": "2024-10-24 15:57:27.238", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannelEventAssociation.created", "timestamp": "2024-10-24 15:57:27.238", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannelEventAssociation.created", "timestamp": "2024-10-24 15:57:27.611", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannelEventAssociation.created", "timestamp": "2024-10-24 16:03:16.756", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannelEventAssociation.created", "timestamp": "2024-10-24 16:03:16.757", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarChannelEventAssociation.created", "timestamp": "2024-10-24 16:03:16.861", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarEvent.created", "timestamp": "2024-10-24 15:55:31.420", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarEvent.created", "timestamp": "2024-10-24 15:55:32.015", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarEvent.created", "timestamp": "2024-10-24 15:57:26.778", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarEvent.created", "timestamp": "2024-10-24 15:57:27.090", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarEvent.created", "timestamp": "2024-10-24 16:03:16.377", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarEvent.created", "timestamp": "2024-10-24 16:03:16.692", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarEventParticipant.created", "timestamp": "2024-10-24 15:55:31.728", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarEventParticipant.created", "timestamp": "2024-10-24 15:55:31.730", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarEventParticipant.created", "timestamp": "2024-10-24 15:55:32.060", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarEventParticipant.created", "timestamp": "2024-10-24 15:57:26.901", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarEventParticipant.created", "timestamp": "2024-10-24 15:57:26.902", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarEventParticipant.created", "timestamp": "2024-10-24 15:57:27.045", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarEventParticipant.created", "timestamp": "2024-10-24 16:03:16.517", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarEventParticipant.created", "timestamp": "2024-10-24 16:03:16.517", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "calendarEventParticipant.created", "timestamp": "2024-10-24 16:03:16.682", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "company.created", "timestamp": "2024-10-22 09:31:13.563", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "company.created", "timestamp": "2024-10-22 10:17:00.671", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "company.created", "timestamp": "2024-10-22 13:16:50.935", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "company.created", "timestamp": "2024-10-24 15:55:36.922", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "company.created", "timestamp": "2024-10-24 15:55:36.927", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "company.created", "timestamp": "2024-10-24 15:55:38.123", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "company.created", "timestamp": "2024-10-24 15:57:34.430", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "company.created", "timestamp": "2024-10-24 15:57:34.443", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "company.created", "timestamp": "2024-10-24 15:57:37.343", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "company.created", "timestamp": "2024-10-24 16:03:17.741", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "company.created", "timestamp": "2024-10-24 16:03:17.742", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "company.created", "timestamp": "2024-10-24 16:03:17.854", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "connectedAccount.created", "timestamp": "2024-10-24 15:55:31.333", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "connectedAccount.created", "timestamp": "2024-10-24 15:55:33.225", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "connectedAccount.created", "timestamp": "2024-10-24 15:55:33.226", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "connectedAccount.created", "timestamp": "2024-10-24 15:55:33.271", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "connectedAccount.created", "timestamp": "2024-10-24 15:57:26.651", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "connectedAccount.created", "timestamp": "2024-10-24 15:57:44.533", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "connectedAccount.created", "timestamp": "2024-10-24 15:57:44.534", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "connectedAccount.created", "timestamp": "2024-10-24 15:57:44.621", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "connectedAccount.created", "timestamp": "2024-10-24 16:03:16.374", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "connectedAccount.created", "timestamp": "2024-10-24 16:03:18.781", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "connectedAccount.created", "timestamp": "2024-10-24 16:03:18.782", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "connectedAccount.created", "timestamp": "2024-10-24 16:03:18.922", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "favorite.created", "timestamp": "2024-10-24 15:55:34.589", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "favorite.created", "timestamp": "2024-10-24 15:55:34.590", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "favorite.created", "timestamp": "2024-10-24 15:55:34.651", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "favorite.created", "timestamp": "2024-10-24 15:57:44.022", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "favorite.created", "timestamp": "2024-10-24 15:57:44.023", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "favorite.created", "timestamp": "2024-10-24 15:57:44.183", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "favorite.created", "timestamp": "2024-10-24 16:03:20.770", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "favorite.created", "timestamp": "2024-10-24 16:03:20.772", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "favorite.created", "timestamp": "2024-10-24 16:03:20.964", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "function.execute", "timestamp": "2024-10-22 14:51:25.149", "version": "1", "userId": "serverless-function", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"duration\":37,\"status\":\"SUCCESS\",\"functionId\":\"a9fd87c0-af86-4e17-be3a-a6d3d961678a\",\"functionName\":\"testingMiVida\"}"}
|
|
||||||
{"action": "function.execute", "timestamp": "2024-10-22 14:54:59.296", "version": "1", "userId": "serverless-function", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"duration\":38,\"status\":\"ERROR\",\"errorType\":\"ReferenceError\",\"functionId\":\"a9fd87c0-af86-4e17-be3a-a6d3d961678a\",\"functionName\":\"testingMiVida\"}"}
|
|
||||||
{"action": "function.execute", "timestamp": "2024-10-22 14:55:00.677", "version": "1", "userId": "serverless-function", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"duration\":32,\"status\":\"ERROR\",\"errorType\":\"ReferenceError\",\"functionId\":\"a9fd87c0-af86-4e17-be3a-a6d3d961678a\",\"functionName\":\"testingMiVida\"}"}
|
|
||||||
{"action": "function.execute", "timestamp": "2024-10-22 14:55:03.512", "version": "1", "userId": "serverless-function", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"duration\":34,\"status\":\"ERROR\",\"errorType\":\"ReferenceError\",\"functionId\":\"a9fd87c0-af86-4e17-be3a-a6d3d961678a\",\"functionName\":\"testingMiVida\"}"}
|
|
||||||
{"action": "message.created", "timestamp": "2024-10-24 15:55:32.004", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "message.created", "timestamp": "2024-10-24 15:57:26.780", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "message.created", "timestamp": "2024-10-24 16:03:16.384", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannel.created", "timestamp": "2024-10-24 15:55:32.169", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannel.created", "timestamp": "2024-10-24 15:55:32.170", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannel.created", "timestamp": "2024-10-24 15:55:32.281", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannel.created", "timestamp": "2024-10-24 15:57:26.872", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannel.created", "timestamp": "2024-10-24 15:57:26.872", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannel.created", "timestamp": "2024-10-24 15:57:27.035", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannel.created", "timestamp": "2024-10-24 16:03:16.506", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannel.created", "timestamp": "2024-10-24 16:03:16.507", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannel.created", "timestamp": "2024-10-24 16:03:16.661", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannelMessageAssociation.created", "timestamp": "2024-10-24 15:55:32.184", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannelMessageAssociation.created", "timestamp": "2024-10-24 15:55:32.185", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannelMessageAssociation.created", "timestamp": "2024-10-24 15:55:32.303", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannelMessageAssociation.created", "timestamp": "2024-10-24 15:57:26.714", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannelMessageAssociation.created", "timestamp": "2024-10-24 15:57:26.717", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannelMessageAssociation.created", "timestamp": "2024-10-24 15:57:26.869", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannelMessageAssociation.created", "timestamp": "2024-10-24 16:03:16.385", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannelMessageAssociation.created", "timestamp": "2024-10-24 16:03:16.386", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageChannelMessageAssociation.created", "timestamp": "2024-10-24 16:03:16.553", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageParticipant.created", "timestamp": "2024-10-24 15:55:32.236", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageParticipant.created", "timestamp": "2024-10-24 15:55:32.237", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageParticipant.created", "timestamp": "2024-10-24 15:55:32.310", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageParticipant.created", "timestamp": "2024-10-24 15:57:26.944", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageParticipant.created", "timestamp": "2024-10-24 15:57:26.945", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageParticipant.created", "timestamp": "2024-10-24 15:57:27.114", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageParticipant.created", "timestamp": "2024-10-24 16:03:16.499", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageParticipant.created", "timestamp": "2024-10-24 16:03:16.499", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageParticipant.created", "timestamp": "2024-10-24 16:03:16.684", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageThread.created", "timestamp": "2024-10-24 15:55:34.758", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageThread.created", "timestamp": "2024-10-24 15:55:34.759", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageThread.created", "timestamp": "2024-10-24 15:55:34.877", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageThread.created", "timestamp": "2024-10-24 15:57:35.725", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageThread.created", "timestamp": "2024-10-24 15:57:35.803", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageThread.created", "timestamp": "2024-10-24 15:57:37.351", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageThread.created", "timestamp": "2024-10-24 16:03:17.807", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageThread.created", "timestamp": "2024-10-24 16:03:17.808", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "messageThread.created", "timestamp": "2024-10-24 16:03:17.879", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "note.created", "timestamp": "2024-10-24 15:55:35.486", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "note.created", "timestamp": "2024-10-24 15:55:35.486", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "note.created", "timestamp": "2024-10-24 15:55:35.671", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "note.created", "timestamp": "2024-10-24 15:57:36.207", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "note.created", "timestamp": "2024-10-24 15:57:36.209", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "note.created", "timestamp": "2024-10-24 15:57:37.487", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "note.created", "timestamp": "2024-10-24 16:03:17.594", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "note.created", "timestamp": "2024-10-24 16:03:17.594", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "note.created", "timestamp": "2024-10-24 16:03:17.762", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "noteTarget.created", "timestamp": "2024-10-24 15:55:33.621", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "noteTarget.created", "timestamp": "2024-10-24 15:55:33.622", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "noteTarget.created", "timestamp": "2024-10-24 15:55:33.734", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "noteTarget.created", "timestamp": "2024-10-24 15:57:42.859", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "noteTarget.created", "timestamp": "2024-10-24 15:57:42.859", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "noteTarget.created", "timestamp": "2024-10-24 15:57:43.174", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "noteTarget.created", "timestamp": "2024-10-24 16:03:18.800", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "noteTarget.created", "timestamp": "2024-10-24 16:03:18.802", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "noteTarget.created", "timestamp": "2024-10-24 16:03:19.118", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "opportunity.created", "timestamp": "2024-10-24 15:55:33.606", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "opportunity.created", "timestamp": "2024-10-24 15:55:33.607", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "opportunity.created", "timestamp": "2024-10-24 15:55:33.736", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "opportunity.created", "timestamp": "2024-10-24 15:57:42.937", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "opportunity.created", "timestamp": "2024-10-24 15:57:42.938", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "opportunity.created", "timestamp": "2024-10-24 15:57:43.166", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "opportunity.created", "timestamp": "2024-10-24 16:03:19.409", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "opportunity.created", "timestamp": "2024-10-24 16:03:19.410", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "opportunity.created", "timestamp": "2024-10-24 16:03:21.884", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "person.created", "timestamp": "2024-10-24 15:55:33.525", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "person.created", "timestamp": "2024-10-24 15:55:33.526", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "person.created", "timestamp": "2024-10-24 15:55:35.037", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "person.created", "timestamp": "2024-10-24 15:55:35.038", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "person.created", "timestamp": "2024-10-24 15:55:35.228", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "person.created", "timestamp": "2024-10-24 15:57:34.269", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "person.created", "timestamp": "2024-10-24 15:57:34.273", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "person.created", "timestamp": "2024-10-24 15:57:37.353", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "person.created", "timestamp": "2024-10-24 15:57:41.933", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "person.created", "timestamp": "2024-10-24 15:57:41.935", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "person.created", "timestamp": "2024-10-24 16:03:17.781", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "person.created", "timestamp": "2024-10-24 16:03:17.782", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "person.created", "timestamp": "2024-10-24 16:03:17.871", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "person.created", "timestamp": "2024-10-24 16:03:18.137", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "person.created", "timestamp": "2024-10-24 16:03:18.137", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "serverlessFunction.executed", "timestamp": "2024-10-22 16:08:22.853", "version": "1", "userId": "serverless-function", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"duration\":49,\"status\":\"SUCCESS\",\"functionId\":\"a9fd87c0-af86-4e17-be3a-a6d3d961678a\",\"functionName\":\"\"}"}
|
|
||||||
{"action": "serverlessFunction.executed", "timestamp": "2024-10-22 16:08:25.262", "version": "1", "userId": "serverless-function", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"duration\":33,\"status\":\"SUCCESS\",\"functionId\":\"a9fd87c0-af86-4e17-be3a-a6d3d961678a\",\"functionName\":\"\"}"}
|
|
||||||
{"action": "serverlessFunction.executed", "timestamp": "2024-10-22 16:08:38.831", "version": "1", "userId": "serverless-function", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"duration\":1008,\"status\":\"SUCCESS\",\"functionId\":\"a9fd87c0-af86-4e17-be3a-a6d3d961678a\",\"functionName\":\"\"}"}
|
|
||||||
{"action": "serverlessFunction.executed", "timestamp": "2024-10-22 16:08:40.553", "version": "1", "userId": "serverless-function", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"duration\":35,\"status\":\"ERROR\",\"errorType\":\"ReferenceError\",\"functionId\":\"a9fd87c0-af86-4e17-be3a-a6d3d961678a\",\"functionName\":\"\"}"}
|
|
||||||
{"action": "serverlessFunction.executed", "timestamp": "2024-10-22 16:17:42.534", "version": "1", "userId": "serverless-function", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"duration\":42,\"status\":\"SUCCESS\",\"functionId\":\"01963805-b9e9-47c5-8bf0-b815c6ba5e1c\",\"functionName\":\"jjjj\"}"}
|
|
||||||
{"action": "task.created", "timestamp": "2024-10-24 15:55:35.469", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "task.created", "timestamp": "2024-10-24 15:55:35.469", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "task.created", "timestamp": "2024-10-24 15:55:35.672", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "task.created", "timestamp": "2024-10-24 15:57:32.646", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "task.created", "timestamp": "2024-10-24 15:57:32.649", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "task.created", "timestamp": "2024-10-24 15:57:33.949", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "task.created", "timestamp": "2024-10-24 16:03:17.587", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "task.created", "timestamp": "2024-10-24 16:03:17.589", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "task.created", "timestamp": "2024-10-24 16:03:17.738", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "taskTarget.created", "timestamp": "2024-10-24 15:55:33.705", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "taskTarget.created", "timestamp": "2024-10-24 15:55:33.706", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "taskTarget.created", "timestamp": "2024-10-24 15:55:33.781", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "taskTarget.created", "timestamp": "2024-10-24 15:57:42.390", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "taskTarget.created", "timestamp": "2024-10-24 15:57:42.392", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "taskTarget.created", "timestamp": "2024-10-24 15:57:42.749", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "taskTarget.created", "timestamp": "2024-10-24 16:03:18.274", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "taskTarget.created", "timestamp": "2024-10-24 16:03:18.275", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "taskTarget.created", "timestamp": "2024-10-24 16:03:18.362", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "timelineActivity.created", "timestamp": "2024-10-24 15:55:32.239", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "timelineActivity.created", "timestamp": "2024-10-24 15:55:32.239", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "timelineActivity.created", "timestamp": "2024-10-24 15:55:32.319", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "timelineActivity.created", "timestamp": "2024-10-24 15:57:26.541", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "timelineActivity.created", "timestamp": "2024-10-24 15:57:26.581", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "timelineActivity.created", "timestamp": "2024-10-24 15:57:26.836", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "timelineActivity.created", "timestamp": "2024-10-24 16:03:16.284", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "timelineActivity.created", "timestamp": "2024-10-24 16:03:16.310", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "timelineActivity.created", "timestamp": "2024-10-24 16:03:16.469", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "view.created", "timestamp": "2024-10-24 15:55:33.555", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "view.created", "timestamp": "2024-10-24 15:55:33.557", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "view.created", "timestamp": "2024-10-24 15:55:33.665", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "view.created", "timestamp": "2024-10-24 15:57:42.752", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "view.created", "timestamp": "2024-10-24 15:57:42.753", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "view.created", "timestamp": "2024-10-24 15:57:42.864", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "view.created", "timestamp": "2024-10-24 16:03:18.825", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "view.created", "timestamp": "2024-10-24 16:03:18.826", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "view.created", "timestamp": "2024-10-24 16:03:18.968", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewField.created", "timestamp": "2024-10-24 15:55:33.519", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewField.created", "timestamp": "2024-10-24 15:55:33.520", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewField.created", "timestamp": "2024-10-24 15:55:33.604", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewField.created", "timestamp": "2024-10-24 15:57:44.535", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewField.created", "timestamp": "2024-10-24 15:57:44.535", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewField.created", "timestamp": "2024-10-24 15:57:44.649", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewField.created", "timestamp": "2024-10-24 16:03:19.752", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewField.created", "timestamp": "2024-10-24 16:03:19.754", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewField.created", "timestamp": "2024-10-24 16:03:19.872", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewFilter.created", "timestamp": "2024-10-24 15:55:33.521", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewFilter.created", "timestamp": "2024-10-24 15:55:33.522", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewFilter.created", "timestamp": "2024-10-24 15:55:33.652", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewFilter.created", "timestamp": "2024-10-24 15:57:43.289", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewFilter.created", "timestamp": "2024-10-24 15:57:43.290", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewFilter.created", "timestamp": "2024-10-24 15:57:43.419", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewFilter.created", "timestamp": "2024-10-24 16:03:21.314", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewFilter.created", "timestamp": "2024-10-24 16:03:21.315", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewFilter.created", "timestamp": "2024-10-24 16:03:23.508", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewSort.created", "timestamp": "2024-10-24 15:55:35.156", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewSort.created", "timestamp": "2024-10-24 15:55:35.158", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewSort.created", "timestamp": "2024-10-24 15:55:35.205", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewSort.created", "timestamp": "2024-10-24 15:57:40.833", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewSort.created", "timestamp": "2024-10-24 15:57:40.840", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewSort.created", "timestamp": "2024-10-24 15:57:41.421", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewSort.created", "timestamp": "2024-10-24 16:03:17.860", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewSort.created", "timestamp": "2024-10-24 16:03:17.860", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "viewSort.created", "timestamp": "2024-10-24 16:03:17.966", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "webhook.created", "timestamp": "2024-10-24 15:57:26.784", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "webhook.created", "timestamp": "2024-10-24 15:57:26.787", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "webhook.created", "timestamp": "2024-10-24 15:57:26.947", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "webhook.created", "timestamp": "2024-10-24 16:03:16.340", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "webhook.created", "timestamp": "2024-10-24 16:03:16.341", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "webhook.created", "timestamp": "2024-10-24 16:03:16.555", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "webhook.response", "timestamp": "2024-10-22 09:31:14.307", "version": "1", "userId": "webhook", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"status\":200,\"success\":true,\"url\":\"https://enfcx639bne28.x.pipedream.net\",\"webhookId\":\"90f12aed-0276-4bea-bcaa-c21ea2763d7d\",\"eventName\":\"company.create\"}"}
|
|
||||||
{"action": "webhook.response", "timestamp": "2024-10-22 09:31:14.447", "version": "1", "userId": "webhook", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"status\":405,\"success\":false,\"url\":\"https://google.com\",\"webhookId\":\"57995a1c-7429-4846-ab9a-3073ddec7865\",\"eventName\":\"company.create\"}"}
|
|
||||||
{"action": "webhook.response", "timestamp": "2024-10-22 09:31:14.453", "version": "1", "userId": "webhook", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"success\":false,\"url\":\"a.com\",\"webhookId\":\"c19ea782-417e-4d44-a486-fd794fc44a27\",\"eventName\":\"company.create\"}"}
|
|
||||||
{"action": "webhook.response", "timestamp": "2024-10-22 10:17:01.108", "version": "1", "userId": "webhook", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"status\":200,\"success\":true,\"url\":\"https://enfcx639bne28.x.pipedream.net\",\"webhookId\":\"90f12aed-0276-4bea-bcaa-c21ea2763d7d\",\"eventName\":\"company.create\"}"}
|
|
||||||
{"action": "webhook.response", "timestamp": "2024-10-22 10:17:01.271", "version": "1", "userId": "webhook", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"status\":405,\"success\":false,\"url\":\"https://google.com\",\"webhookId\":\"57995a1c-7429-4846-ab9a-3073ddec7865\",\"eventName\":\"company.create\"}"}
|
|
||||||
{"action": "webhook.response", "timestamp": "2024-10-22 10:17:01.277", "version": "1", "userId": "webhook", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"success\":false,\"url\":\"a.com\",\"webhookId\":\"c19ea782-417e-4d44-a486-fd794fc44a27\",\"eventName\":\"company.create\"}"}
|
|
||||||
{"action": "webhook.response", "timestamp": "2024-10-22 13:16:51.473", "version": "1", "userId": "webhook", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"status\":200,\"success\":true,\"url\":\"https://enfcx639bne28.x.pipedream.net\",\"webhookId\":\"90f12aed-0276-4bea-bcaa-c21ea2763d7d\",\"eventName\":\"company.create\"}"}
|
|
||||||
{"action": "webhook.response", "timestamp": "2024-10-22 13:16:51.617", "version": "1", "userId": "webhook", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"success\":false,\"url\":\"https://google.com\",\"webhookId\":\"57995a1c-7429-4846-ab9a-3073ddec7865\",\"eventName\":\"company.create\",\"status\":405}"}
|
|
||||||
{"action": "webhook.response", "timestamp": "2024-10-22 13:16:51.621", "version": "1", "userId": "webhook", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{\"success\":false,\"url\":\"a.com\",\"webhookId\":\"c19ea782-417e-4d44-a486-fd794fc44a27\",\"eventName\":\"company.create\"}"}
|
|
||||||
{"action": "workspaceMember.created", "timestamp": "2024-10-24 15:55:32.038", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "workspaceMember.created", "timestamp": "2024-10-24 15:55:32.039", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "workspaceMember.created", "timestamp": "2024-10-24 15:55:32.223", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "workspaceMember.created", "timestamp": "2024-10-24 15:57:26.646", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "workspaceMember.created", "timestamp": "2024-10-24 15:57:26.647", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "workspaceMember.created", "timestamp": "2024-10-24 15:57:26.854", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "workspaceMember.created", "timestamp": "2024-10-24 16:03:16.337", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "workspaceMember.created", "timestamp": "2024-10-24 16:03:16.337", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
{"action": "workspaceMember.created", "timestamp": "2024-10-24 16:03:16.490", "version": "1", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419", "payload": "{}"}
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
DESCRIPTION >
|
|
||||||
Inspired by DUB implementation
|
|
||||||
|
|
||||||
NODE dayIntervals
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
WITH
|
|
||||||
toStartOfDay(
|
|
||||||
parseDateTime64BestEffort({{ String(start, '2024-11-01T00:00:00.000Z') }}, 3)
|
|
||||||
) AS start,
|
|
||||||
toStartOfDay(parseDateTime64BestEffort({{ String(end, '2024-11-02T00:00:00.000Z') }}, 3)) AS
|
|
||||||
end
|
|
||||||
SELECT
|
|
||||||
arrayJoin(
|
|
||||||
arrayMap(
|
|
||||||
x -> toDateTime64(toStartOfDay(toDateTime64(x, 3)), 3),
|
|
||||||
range(toUInt32(start + 86400), toUInt32(end + 86400),
|
|
||||||
86400
|
|
||||||
)
|
|
||||||
)
|
|
||||||
) as interval
|
|
||||||
|
|
||||||
NODE hourIntervals
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
WITH
|
|
||||||
toStartOfHour(
|
|
||||||
parseDateTime64BestEffort({{ String(start, '2024-11-01T00:00:00.000Z') }}, 3)
|
|
||||||
) AS start,
|
|
||||||
toStartOfHour(parseDateTime64BestEffort({{ String(end, '2024-11-02T00:00:00.000Z') }}, 3)) AS
|
|
||||||
end
|
|
||||||
SELECT
|
|
||||||
arrayJoin(
|
|
||||||
arrayMap(x -> toDateTime64(x, 3), range(toUInt32(start + 3600), toUInt32(end + 3600), 3600)
|
|
||||||
)
|
|
||||||
) as interval
|
|
||||||
|
|
||||||
NODE selectIntervalByGranularity
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
SELECT * FROM {% if granularity == "hour" %} hourIntervals {% else %} dayIntervals {% end %}
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
DESCRIPTION >
|
|
||||||
Inspired by DUB implementation
|
|
||||||
|
|
||||||
NODE dayIntervals
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
WITH
|
|
||||||
toStartOfDay(
|
|
||||||
parseDateTime64BestEffort({{ String(start, '2024-11-01T00:00:00.000Z') }}, 3)
|
|
||||||
) AS start,
|
|
||||||
toStartOfDay(parseDateTime64BestEffort({{ String(end, '2024-11-02T00:00:00.000Z') }}, 3)) AS
|
|
||||||
end
|
|
||||||
SELECT
|
|
||||||
arrayJoin(
|
|
||||||
arrayMap(
|
|
||||||
x -> toDateTime64(toStartOfDay(toDateTime64(x, 3)), 3),
|
|
||||||
range(toUInt32(start + 86400), toUInt32(end + 86400),
|
|
||||||
86400
|
|
||||||
)
|
|
||||||
)
|
|
||||||
) as interval
|
|
||||||
|
|
||||||
NODE hourIntervals
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
WITH
|
|
||||||
toStartOfHour(
|
|
||||||
parseDateTime64BestEffort({{ String(start, '2024-11-01T00:00:00.000Z') }}, 3)
|
|
||||||
) AS start,
|
|
||||||
toStartOfHour(parseDateTime64BestEffort({{ String(end, '2024-11-02T00:00:00.000Z') }}, 3)) AS
|
|
||||||
end
|
|
||||||
SELECT
|
|
||||||
arrayJoin(
|
|
||||||
arrayMap(x -> toDateTime64(x, 3), range(toUInt32(start + 3600), toUInt32(end + 3600), 3600)
|
|
||||||
)
|
|
||||||
) as interval
|
|
||||||
|
|
||||||
NODE selectIntervalByGranularity
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
SELECT * FROM {% if granularity == "hour" %} hourIntervals {% else %} dayIntervals {% end %}
|
|
||||||
|
|
||||||
|
|
||||||
NODE timeSeriesServerlessFunctionDurationData
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
SELECT
|
|
||||||
{% if granularity == "hour" %} toStartOfHour(timestamp)
|
|
||||||
{% else %} toDateTime64(toStartOfDay(timestamp), 3)
|
|
||||||
{% end %} AS interval,
|
|
||||||
avg(CAST(durationInMs AS Float64)) as average,
|
|
||||||
min(durationInMs) as minimum,
|
|
||||||
max(durationInMs) as maximum
|
|
||||||
FROM serverlessFunctionEventMV
|
|
||||||
WHERE
|
|
||||||
true
|
|
||||||
AND workspaceId
|
|
||||||
={{ String(workspaceId, '20202020-1c25-4d02-bf25-6aeccf7ea419', required=True) }}
|
|
||||||
AND functionId = {{ String(functionId, 'a9fd87c0-af86-4e17-be3a-a6d3d961678a', required=True) }}
|
|
||||||
AND timestamp >= parseDateTime64BestEffort({{ String(start, '2024-11-01T00:00:00.000Z') }}, 3)
|
|
||||||
AND timestamp < parseDateTime64BestEffort({{ String(end, '2024-11-02T00:00:00.000Z') }}, 3)
|
|
||||||
GROUP BY interval
|
|
||||||
ORDER BY interval
|
|
||||||
|
|
||||||
NODE endpoint
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
SELECT formatDateTime(interval, '%FT%T.000%z') as start, minimum, maximum, average
|
|
||||||
FROM selectIntervalByGranularity
|
|
||||||
LEFT JOIN timeSeriesServerlessFunctionDurationData USING interval
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
DESCRIPTION >
|
|
||||||
Inspired by DUB implementation
|
|
||||||
|
|
||||||
NODE dayIntervals
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
WITH
|
|
||||||
toStartOfDay(
|
|
||||||
parseDateTime64BestEffort({{ String(start, '2024-11-01T00:00:00.000Z') }}, 3)
|
|
||||||
) AS start,
|
|
||||||
toStartOfDay(parseDateTime64BestEffort({{ String(end, '2024-11-02T00:00:00.000Z') }}, 3)) AS
|
|
||||||
end
|
|
||||||
SELECT
|
|
||||||
arrayJoin(
|
|
||||||
arrayMap(
|
|
||||||
x -> toDateTime64(toStartOfDay(toDateTime64(x, 3)), 3),
|
|
||||||
range(toUInt32(start + 86400), toUInt32(end + 86400),
|
|
||||||
86400
|
|
||||||
)
|
|
||||||
)
|
|
||||||
) as interval
|
|
||||||
|
|
||||||
NODE hourIntervals
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
WITH
|
|
||||||
toStartOfHour(
|
|
||||||
parseDateTime64BestEffort({{ String(start, '2024-11-01T00:00:00.000Z') }}, 3)
|
|
||||||
) AS start,
|
|
||||||
toStartOfHour(parseDateTime64BestEffort({{ String(end, '2024-11-02T00:00:00.000Z') }}, 3)) AS
|
|
||||||
end
|
|
||||||
SELECT
|
|
||||||
arrayJoin(
|
|
||||||
arrayMap(x -> toDateTime64(x, 3), range(toUInt32(start + 3600), toUInt32(end + 3600), 3600)
|
|
||||||
)
|
|
||||||
) as interval
|
|
||||||
|
|
||||||
NODE selectIntervalByGranularity
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
SELECT * FROM {% if granularity == "hour" %} hourIntervals {% else %} dayIntervals {% end %}
|
|
||||||
|
|
||||||
-- I decided to separate the error count and the success rate because I think we should maintain the bijection
|
|
||||||
-- between an endpoint and a graph in the front-end.
|
|
||||||
NODE timeSeriesServerlessFunctionErrorCountData
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
SELECT
|
|
||||||
{% if granularity == "hour" %} toStartOfHour(timestamp)
|
|
||||||
{% else %} toDateTime64(toStartOfDay(timestamp), 3)
|
|
||||||
{% end %} AS interval,
|
|
||||||
uniqIf(*, success = false) as error_count
|
|
||||||
FROM serverlessFunctionEventMV
|
|
||||||
WHERE
|
|
||||||
true
|
|
||||||
AND workspaceId
|
|
||||||
={{ String(workspaceId, '20202020-1c25-4d02-bf25-6aeccf7ea419', required=True) }}
|
|
||||||
AND functionId = {{ String(functionId, 'ad018fc5-eace-4f7e-942f-929560a16459', required=True) }}
|
|
||||||
AND timestamp >= parseDateTime64BestEffort({{ String(start, '2024-11-01T00:00:00.000Z') }}, 3)
|
|
||||||
AND timestamp < parseDateTime64BestEffort({{ String(end, '2024-11-02T00:00:00.000Z') }}, 3)
|
|
||||||
GROUP BY interval
|
|
||||||
ORDER BY interval
|
|
||||||
|
|
||||||
NODE endpoint
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
SELECT formatDateTime(interval, '%FT%T.000%z') as start, error_count
|
|
||||||
FROM selectIntervalByGranularity
|
|
||||||
LEFT JOIN timeSeriesServerlessFunctionErrorCountData USING interval
|
|
||||||
TYPE ENDPOINT
|
|
||||||
@ -1,75 +0,0 @@
|
|||||||
DESCRIPTION >
|
|
||||||
Inspired by DUB implementation
|
|
||||||
|
|
||||||
NODE dayIntervals
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
WITH
|
|
||||||
toStartOfDay(
|
|
||||||
parseDateTime64BestEffort({{ String(start, '2024-11-01T00:00:00.000Z') }}, 3)
|
|
||||||
) AS start,
|
|
||||||
toStartOfDay(parseDateTime64BestEffort({{ String(end, '2024-11-02T00:00:00.000Z') }}, 3)) AS
|
|
||||||
end
|
|
||||||
SELECT
|
|
||||||
arrayJoin(
|
|
||||||
arrayMap(
|
|
||||||
x -> toDateTime64(toStartOfDay(toDateTime64(x, 3)), 3),
|
|
||||||
range(toUInt32(start + 86400), toUInt32(end + 86400),
|
|
||||||
86400
|
|
||||||
)
|
|
||||||
)
|
|
||||||
) as interval
|
|
||||||
|
|
||||||
NODE hourIntervals
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
WITH
|
|
||||||
toStartOfHour(
|
|
||||||
parseDateTime64BestEffort({{ String(start, '2024-11-01T00:00:00.000Z') }}, 3)
|
|
||||||
) AS start,
|
|
||||||
toStartOfHour(parseDateTime64BestEffort({{ String(end, '2024-11-02T00:00:00.000Z') }}, 3)) AS
|
|
||||||
end
|
|
||||||
SELECT
|
|
||||||
arrayJoin(
|
|
||||||
arrayMap(x -> toDateTime64(x, 3), range(toUInt32(start + 3600), toUInt32(end + 3600), 3600)
|
|
||||||
)
|
|
||||||
) as interval
|
|
||||||
|
|
||||||
NODE selectIntervalByGranularity
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
SELECT * FROM {% if granularity == "hour" %} hourIntervals {% else %} dayIntervals {% end %}
|
|
||||||
|
|
||||||
|
|
||||||
NODE timeSeriesServerlessFunctionSuccessRateData
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
SELECT
|
|
||||||
{% if granularity == "hour" %} toStartOfHour(timestamp)
|
|
||||||
{% else %} toDateTime64(toStartOfDay(timestamp), 3)
|
|
||||||
{% end %} AS interval,
|
|
||||||
round(
|
|
||||||
if(
|
|
||||||
uniqIf(*, success = true) = 0,
|
|
||||||
0,
|
|
||||||
(uniqIf(*, success = true) - uniqIf(*, success = false)) / uniqIf(*, success = true)
|
|
||||||
),
|
|
||||||
2
|
|
||||||
) as success_rate
|
|
||||||
FROM serverlessFunctionEventMV
|
|
||||||
WHERE
|
|
||||||
true
|
|
||||||
AND workspaceId
|
|
||||||
={{ String(workspaceId, '20202020-1c25-4d02-bf25-6aeccf7ea419', required=True) }}
|
|
||||||
AND functionId = {{ String(functionId, 'ad018fc5-eace-4f7e-942f-929560a16459', required=True) }}
|
|
||||||
AND timestamp >= parseDateTime64BestEffort({{ String(start, '2024-11-01T00:00:00.000Z') }}, 3)
|
|
||||||
AND timestamp < parseDateTime64BestEffort({{ String(end, '2024-11-02T00:00:00.000Z') }}, 3)
|
|
||||||
GROUP BY interval
|
|
||||||
ORDER BY interval
|
|
||||||
|
|
||||||
NODE endpoint
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
SELECT formatDateTime(interval, '%FT%T.000%z') as start, success_rate
|
|
||||||
FROM selectIntervalByGranularity
|
|
||||||
LEFT JOIN timeSeriesServerlessFunctionSuccessRateData USING interval
|
|
||||||
@ -1,69 +0,0 @@
|
|||||||
DESCRIPTION >
|
|
||||||
Inspired by DUB implementation
|
|
||||||
|
|
||||||
NODE dayIntervals
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
WITH
|
|
||||||
toStartOfDay(
|
|
||||||
parseDateTime64BestEffort({{ String(start, '2024-11-01T00:00:00.000Z') }}, 3)
|
|
||||||
) AS start,
|
|
||||||
toStartOfDay(parseDateTime64BestEffort({{ String(end, '2024-11-02T00:00:00.000Z') }}, 3)) AS
|
|
||||||
end
|
|
||||||
SELECT
|
|
||||||
arrayJoin(
|
|
||||||
arrayMap(
|
|
||||||
x -> toDateTime64(toStartOfDay(toDateTime64(x, 3)), 3),
|
|
||||||
range(toUInt32(start + 86400), toUInt32(end + 86400),
|
|
||||||
86400
|
|
||||||
)
|
|
||||||
)
|
|
||||||
) as interval
|
|
||||||
|
|
||||||
NODE hourIntervals
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
WITH
|
|
||||||
toStartOfHour(
|
|
||||||
parseDateTime64BestEffort({{ String(start, '2024-11-01T00:00:00.000Z') }}, 3)
|
|
||||||
) AS start,
|
|
||||||
toStartOfHour(parseDateTime64BestEffort({{ String(end, '2024-11-02T00:00:00.000Z') }}, 3)) AS
|
|
||||||
end
|
|
||||||
SELECT
|
|
||||||
arrayJoin(
|
|
||||||
arrayMap(x -> toDateTime64(x, 3), range(toUInt32(start + 3600), toUInt32(end + 3600), 3600)
|
|
||||||
)
|
|
||||||
) as interval
|
|
||||||
|
|
||||||
NODE selectIntervalByGranularity
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
SELECT * FROM {% if granularity == "hour" %} hourIntervals {% else %} dayIntervals {% end %}
|
|
||||||
|
|
||||||
|
|
||||||
NODE timeSeriesWebhookData
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
SELECT
|
|
||||||
{% if granularity == "hour" %} toStartOfHour(timestamp)
|
|
||||||
{% else %} toDateTime64(toStartOfDay(timestamp), 3)
|
|
||||||
{% end %} AS interval,
|
|
||||||
uniqIf(*, success = true) as success_count,
|
|
||||||
uniqIf(*, success = false) as failure_count
|
|
||||||
FROM webhookEventMV
|
|
||||||
WHERE
|
|
||||||
true
|
|
||||||
AND workspaceId
|
|
||||||
={{ String(workspaceId, '20202020-1c25-4d02-bf25-6aeccf7ea419', required=True) }}
|
|
||||||
AND webhookId = {{ String(webhookId, '5237a3bc-566d-4290-b951-96e91051f968', required=True) }}
|
|
||||||
AND timestamp >= parseDateTime64BestEffort({{ String(start, '2024-11-01T00:00:00.000Z') }}, 3)
|
|
||||||
AND timestamp < parseDateTime64BestEffort({{ String(end, '2024-11-02T00:00:00.000Z') }}, 3)
|
|
||||||
GROUP BY interval
|
|
||||||
ORDER BY interval
|
|
||||||
|
|
||||||
NODE endpoint
|
|
||||||
SQL >
|
|
||||||
%
|
|
||||||
SELECT formatDateTime(interval, '%FT%T.000%z') as start, success_count, failure_count
|
|
||||||
FROM selectIntervalByGranularity
|
|
||||||
LEFT JOIN timeSeriesWebhookData USING interval
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
NODE mv
|
|
||||||
SQL >
|
|
||||||
SELECT
|
|
||||||
timestamp,
|
|
||||||
workspaceId,
|
|
||||||
JSONExtractString(payload, 'functionId') as functionId,
|
|
||||||
JSONExtractInt(payload, 'duration') as durationInMs,
|
|
||||||
if(JSONExtractString(payload, 'status') = 'SUCCESS', TRUE, FALSE) as success,
|
|
||||||
JSONExtractString(payload, 'errorType') as errorType,
|
|
||||||
version
|
|
||||||
FROM event
|
|
||||||
WHERE action = 'serverlessFunction.executed'
|
|
||||||
|
|
||||||
TYPE MATERIALIZED
|
|
||||||
DATASOURCE serverlessFunctionEventMV
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
NODE mv
|
|
||||||
SQL >
|
|
||||||
SELECT
|
|
||||||
timestamp,
|
|
||||||
workspaceId,
|
|
||||||
JSONExtractString(payload, 'webhookId') as webhookId,
|
|
||||||
JSONExtractString(payload, 'url') as url,
|
|
||||||
JSONExtractBool(payload, 'success') as success,
|
|
||||||
JSONExtractInt(payload, 'status') as status,
|
|
||||||
JSONExtractString(payload, 'eventName') as eventName,
|
|
||||||
version
|
|
||||||
FROM 'event'
|
|
||||||
WHERE action = 'webhook.response'
|
|
||||||
|
|
||||||
TYPE MATERIALIZED
|
|
||||||
DATASOURCE webhookEventMV
|
|
||||||
@ -1 +0,0 @@
|
|||||||
tinybird-cli==5.10.1
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -euxo pipefail
|
|
||||||
|
|
||||||
directory="datasources/fixtures"
|
|
||||||
extensions=("csv" "ndjson")
|
|
||||||
|
|
||||||
absolute_directory=$(realpath "$directory")
|
|
||||||
|
|
||||||
for extension in "${extensions[@]}"; do
|
|
||||||
file_list=$(find "$absolute_directory" -type f -name "*.$extension")
|
|
||||||
|
|
||||||
for file_path in $file_list; do
|
|
||||||
file_name=$(basename "$file_path")
|
|
||||||
file_name_without_extension="${file_name%.*}"
|
|
||||||
|
|
||||||
command="tb datasource append $file_name_without_extension datasources/fixtures/$file_name"
|
|
||||||
echo $command
|
|
||||||
$command
|
|
||||||
done
|
|
||||||
done
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -euxo pipefail
|
|
||||||
|
|
||||||
export TB_VERSION_WARNING=0
|
|
||||||
|
|
||||||
run_test() {
|
|
||||||
t=$1
|
|
||||||
echo "** Running $t **"
|
|
||||||
echo "** $(cat $t)"
|
|
||||||
tmpfile=$(mktemp)
|
|
||||||
retries=0
|
|
||||||
TOTAL_RETRIES=3
|
|
||||||
|
|
||||||
# When appending fixtures, we need to retry in case of the data is not replicated in time
|
|
||||||
while [ $retries -lt $TOTAL_RETRIES ]; do
|
|
||||||
# Run the test and store the output in a temporary file
|
|
||||||
bash $t $2 >$tmpfile
|
|
||||||
exit_code=$?
|
|
||||||
if [ "$exit_code" -eq 0 ]; then
|
|
||||||
# If the test passed, break the loop
|
|
||||||
if diff -B ${t}.result $tmpfile >/dev/null 2>&1; then
|
|
||||||
break
|
|
||||||
# If the test failed, increment the retries counter and try again
|
|
||||||
else
|
|
||||||
retries=$((retries+1))
|
|
||||||
fi
|
|
||||||
# If the bash command failed, print an error message and break the loop
|
|
||||||
else
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if diff -B ${t}.result $tmpfile >/dev/null 2>&1; then
|
|
||||||
echo "✅ Test $t passed"
|
|
||||||
rm $tmpfile
|
|
||||||
return 0
|
|
||||||
elif [ $retries -eq $TOTAL_RETRIES ]; then
|
|
||||||
echo "🚨 ERROR: Test $t failed, diff:";
|
|
||||||
diff -B ${t}.result $tmpfile
|
|
||||||
rm $tmpfile
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
echo "🚨 ERROR: Test $t failed with bash command exit code $?"
|
|
||||||
cat $tmpfile
|
|
||||||
rm $tmpfile
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
}
|
|
||||||
export -f run_test
|
|
||||||
|
|
||||||
fail=0
|
|
||||||
find ./tests -name "*.test" -print0 | xargs -0 -I {} -P 4 bash -c 'run_test "$@"' _ {} || fail=1
|
|
||||||
|
|
||||||
if [ $fail == 1 ]; then
|
|
||||||
exit -1;
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
echo "DELETE ME - I'M HERE TO TRIGGER THE CI - 1"
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
- name: daily_error_count_default
|
|
||||||
description: Test error count with daily granularity using default dates
|
|
||||||
parameters: workspaceId=20202020-1c25-4d02-bf25-6aeccf7ea419&functionId=ad018fc5-eace-4f7e-942f-929560a16459&granularity=day
|
|
||||||
expected_result: |
|
|
||||||
{"start":"2024-11-02T00:00:00.000+0000","error_count":0}
|
|
||||||
|
|
||||||
- name: hourly_error_count_custom_range
|
|
||||||
description: Test error count with hourly granularity for a custom date range
|
|
||||||
parameters: workspaceId=20202020-1c25-4d02-bf25-6aeccf7ea419&functionId=a9fd87c0-af86-4e17-be3a-a6d3d961678a&granularity=hour&start=2024-10-22T00:00:00.000Z&end=2024-10-23T00:00:00.000Z
|
|
||||||
expected_result: |
|
|
||||||
{"start":"2024-10-22T01:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T02:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T03:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T04:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T05:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T06:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T07:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T08:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T09:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T10:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T11:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T12:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T13:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T14:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T15:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T16:00:00.000+0000","error_count":1}
|
|
||||||
{"start":"2024-10-22T17:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T18:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T19:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T20:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T21:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T22:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-22T23:00:00.000+0000","error_count":0}
|
|
||||||
{"start":"2024-10-23T00:00:00.000+0000","error_count":0}
|
|
||||||
|
|
||||||
- name: different_workspace_function
|
|
||||||
description: Test error count with different workspace and function IDs
|
|
||||||
parameters: workspaceId=30303030-1c25-4d02-bf25-6aeccf7ea419&functionId=bd018fc5-eace-4f7e-942f-929560a16459&granularity=day
|
|
||||||
expected_result: |
|
|
||||||
{"start":"2024-11-02T00:00:00.000+0000","error_count":0}
|
|
||||||
Reference in New Issue
Block a user