From ae857d3fcd11f74b702ac882b829518e5e0abae2 Mon Sep 17 00:00:00 2001 From: Sudeep MP Date: Fri, 6 Sep 2024 14:26:13 +0100 Subject: [PATCH] feat(paywall blocker): improvements for trial end blocker screen (#5756) * feat: add view templates option to dashboard menu * feat: increase dropdown overlay width Set the dropdown overlay width to 200px to provide breathing space for the dropdown button. Added flex to wrap the dropdown button to create space between the right icon and the left elements. * feat(paywall blocker): improvements for trial end blocker screen - added new components locally for rendering static contents - fixed SCSS code for better readablity - seperated data to specific file - added alert info style for the non admin users message * chore: fixed few conditions * feat(paywall title): added contact us to modal title * feat: non admin users communication styles * chore: added useState for the sidebar collapse state to be false * test(WorkspaceLocked): update Jest test to sync with recent UX copy changes * feat(workspaceLocked): added locale added English and English-GB translations for workspace locked messages * feat: reverted the translation for and sidebar collapse fix - I have removed the scope for unitest having locale support - remove the useEffect way to set sidebar collapse, instead added it in app layout - removed the opacity effect on tabs * refactor(workspaceLocked): refactor appLayout component to simplify the isWorkspaceLocked function * refactor(workspaceLocked): simplify isWorkspaceLocked by converting it to a constant expression * refactor(workspaceLocked): refactor modal classname and variable --------- Co-authored-by: Pranay Prateek --- .../public/locales/en-GB/workspaceLocked.json | 22 ++ .../public/locales/en/workspaceLocked.json | 22 ++ frontend/src/container/AppLayout/index.tsx | 11 +- .../WorkspaceLocked/CustomerStoryCard.tsx | 35 ++ .../src/pages/WorkspaceLocked/InfoBlocks.tsx | 30 ++ .../WorkspaceLocked.styles.scss | 159 ++++++++- .../WorkspaceLocked/WorkspaceLocked.test.tsx | 16 +- .../pages/WorkspaceLocked/WorkspaceLocked.tsx | 301 ++++++++++++++---- .../customerStoryCard.styles.scss | 33 ++ .../WorkspaceLocked/workspaceLocked.data.ts | 156 +++++++++ 10 files changed, 714 insertions(+), 71 deletions(-) create mode 100644 frontend/public/locales/en-GB/workspaceLocked.json create mode 100644 frontend/public/locales/en/workspaceLocked.json create mode 100644 frontend/src/pages/WorkspaceLocked/CustomerStoryCard.tsx create mode 100644 frontend/src/pages/WorkspaceLocked/InfoBlocks.tsx create mode 100644 frontend/src/pages/WorkspaceLocked/customerStoryCard.styles.scss create mode 100644 frontend/src/pages/WorkspaceLocked/workspaceLocked.data.ts diff --git a/frontend/public/locales/en-GB/workspaceLocked.json b/frontend/public/locales/en-GB/workspaceLocked.json new file mode 100644 index 000000000000..1eb6a0da1c7d --- /dev/null +++ b/frontend/public/locales/en-GB/workspaceLocked.json @@ -0,0 +1,22 @@ +{ + "trialPlanExpired": "Trial Plan Expired", + "gotQuestions": "Got Questions?", + "contactUs": "Contact Us", + "upgradeToContinue": "Upgrade to Continue", + "upgradeNow": "Upgrade now to keep enjoying all the great features you’ve been using.", + "yourDataIsSafe": "Your data is safe with us until", + "actNow": "Act now to avoid any disruptions and continue where you left off.", + "contactAdmin": "Contact your admin to proceed with the upgrade.", + "continueMyJourney": "Continue My Journey", + "needMoreTime": "Need More Time?", + "extendTrial": "Extend Trial", + "extendTrialMsgPart1": "If you have a specific reason why you were not able to finish your PoC in the trial period, please write to us on", + "extendTrialMsgPart2": "with the reason. Sometimes we can extend trial by a few days on a case by case basis", + "whyChooseSignoz": "Why choose Signoz", + "enterpriseGradeObservability": "Enterprise-grade Observability", + "observabilityDescription": "Get access to observability at any scale with advanced security and compliance.", + "continueToUpgrade": "Continue to Upgrade", + "youAreInGoodCompany": "You are in good company", + "faqs": "FAQs", + "somethingWentWrong": "Something went wrong" +} diff --git a/frontend/public/locales/en/workspaceLocked.json b/frontend/public/locales/en/workspaceLocked.json new file mode 100644 index 000000000000..1eb6a0da1c7d --- /dev/null +++ b/frontend/public/locales/en/workspaceLocked.json @@ -0,0 +1,22 @@ +{ + "trialPlanExpired": "Trial Plan Expired", + "gotQuestions": "Got Questions?", + "contactUs": "Contact Us", + "upgradeToContinue": "Upgrade to Continue", + "upgradeNow": "Upgrade now to keep enjoying all the great features you’ve been using.", + "yourDataIsSafe": "Your data is safe with us until", + "actNow": "Act now to avoid any disruptions and continue where you left off.", + "contactAdmin": "Contact your admin to proceed with the upgrade.", + "continueMyJourney": "Continue My Journey", + "needMoreTime": "Need More Time?", + "extendTrial": "Extend Trial", + "extendTrialMsgPart1": "If you have a specific reason why you were not able to finish your PoC in the trial period, please write to us on", + "extendTrialMsgPart2": "with the reason. Sometimes we can extend trial by a few days on a case by case basis", + "whyChooseSignoz": "Why choose Signoz", + "enterpriseGradeObservability": "Enterprise-grade Observability", + "observabilityDescription": "Get access to observability at any scale with advanced security and compliance.", + "continueToUpgrade": "Continue to Upgrade", + "youAreInGoodCompany": "You are in good company", + "faqs": "FAQs", + "somethingWentWrong": "Something went wrong" +} diff --git a/frontend/src/container/AppLayout/index.tsx b/frontend/src/container/AppLayout/index.tsx index 60b26b8db259..4cf2e0f5bb93 100644 --- a/frontend/src/container/AppLayout/index.tsx +++ b/frontend/src/container/AppLayout/index.tsx @@ -214,7 +214,6 @@ function AppLayout(props: AppLayoutProps): JSX.Element { const pageTitle = t(routeKey); const renderFullScreen = pathname === ROUTES.GET_STARTED || - pathname === ROUTES.WORKSPACE_LOCKED || pathname === ROUTES.GET_STARTED_APPLICATION_MONITORING || pathname === ROUTES.GET_STARTED_INFRASTRUCTURE_MONITORING || pathname === ROUTES.GET_STARTED_LOGS_MANAGEMENT || @@ -282,6 +281,14 @@ function AppLayout(props: AppLayoutProps): JSX.Element { const isSideNavCollapsed = getLocalStorageKey(IS_SIDEBAR_COLLAPSED); + /** + * Note: Right now we don't have a page-level method to pass the sidebar collapse state. + * Since the use case for overriding is not widely needed, we are setting it here + * so that the workspace locked page will have an expanded sidebar regardless of how users + * have set it or what is stored in localStorage. This will not affect the localStorage config. + */ + const isWorkspaceLocked = pathname === ROUTES.WORKSPACE_LOCKED; + return ( )}
+ + + } + title={personName} + description={role} + /> + {message} + + + + ); +} +export default CustomerStoryCard; diff --git a/frontend/src/pages/WorkspaceLocked/InfoBlocks.tsx b/frontend/src/pages/WorkspaceLocked/InfoBlocks.tsx new file mode 100644 index 000000000000..90bec521d7f3 --- /dev/null +++ b/frontend/src/pages/WorkspaceLocked/InfoBlocks.tsx @@ -0,0 +1,30 @@ +import { Col, Row, Space, Typography } from 'antd'; + +interface InfoItem { + title: string; + description: string; + id: string; // Add a unique identifier +} + +interface InfoBlocksProps { + items: InfoItem[]; +} + +function InfoBlocks({ items }: InfoBlocksProps): JSX.Element { + return ( + + {items.map((item) => ( + + + {item.title} + + + {item.description} + + + ))} + + ); +} + +export default InfoBlocks; diff --git a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.styles.scss b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.styles.scss index c35284241a62..131601bfb060 100644 --- a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.styles.scss +++ b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.styles.scss @@ -1,16 +1,161 @@ -.workspace-locked-container { - text-align: center; - padding: 48px; - margin: 24px; +$light-theme: 'lightMode'; + +@keyframes gradientFlow { + 0% { + background-position: 0% 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0% 50%; + } } -.workpace-locked-details { - width: 50%; - margin: 0 auto; +.workspace-locked { + &__modal { + .ant-modal-mask { + backdrop-filter: blur(2px); + } + } + + &__tabs { + margin-top: 148px; + + .ant-tabs { + &-nav { + &::before { + border-color: var(--bg-slate-500); + + .#{$light-theme} & { + border-color: var(--bg-vanilla-300); + } + } + } + &-nav-wrap { + justify-content: center; + } + } + } + + &__modal { + &__header { + display: flex; + justify-content: space-between; + align-items: center; + + &__actions { + display: flex; + align-items: center; + gap: 16px; + } + } + .ant-modal-content { + border-radius: 4px; + border: 1px solid var(--bg-slate-400); + background: linear-gradient( + 139deg, + rgba(18, 19, 23, 0.8) 0%, + rgba(18, 19, 23, 0.9) 98.68% + ); + box-shadow: 4px 10px 16px 2px rgba(0, 0, 0, 0.2); + backdrop-filter: blur(20px); + + .#{$light-theme} & { + border: 1px solid var(--bg-vanilla-300); + background: var(--bg-vanilla-100); + } + } + + .ant-modal-header { + background: transparent; + } + + .ant-list { + &-item { + border-color: var(--bg-slate-500); + + .#{$light-theme} & { + border-color: var(--bg-vanilla-300); + } + + &-meta { + align-items: center !important; + + &-title { + margin-bottom: 0 !important; + } + + &-avatar { + display: flex; + } + } + } + } + &__title { + font-weight: 400; + color: var(--text-vanilla-400); + + .#{$light-theme} & { + color: var(--text-ink-200); + } + } + &__cta { + margin-top: 54px; + } + } + &__container { + padding-top: 64px; + } + &__details { + width: 80%; + margin: 0 auto; + color: var(--text-vanilla-400, #c0c1c3); + text-align: center; + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 24px; /* 150% */ + + .#{$light-theme} & { + color: var(--text-ink-200); + } + + &__highlight { + color: var(--text-vanilla-100, #fff); + font-style: normal; + font-weight: 700; + line-height: 24px; + + .#{$light-theme} & { + color: var(--text-ink-100); + } + } + } + &__title { + background: linear-gradient( + 99deg, + #ead8fd 0%, + #7a97fa 33%, + #fd5ab2 66%, + #ead8fd 100% + ); + background-size: 300% 300%; + background-clip: text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + animation: gradientFlow 24s ease infinite; + margin-bottom: 18px; + } } .contact-us { margin-top: 48px; + color: var(--text-vanilla-400); + + .#{$light-theme} & { + color: var(--text-ink-200); + } } .cta { diff --git a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.test.tsx b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.test.tsx index bc6885ae6519..e45900366598 100644 --- a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.test.tsx +++ b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.test.tsx @@ -20,17 +20,17 @@ describe('WorkspaceLocked', () => { }); const workspaceLocked = await screen.findByRole('heading', { - name: /workspace locked/i, + name: /upgrade to continue/i, }); expect(workspaceLocked).toBeInTheDocument(); const gotQuestionText = await screen.findByText(/got question?/i); expect(gotQuestionText).toBeInTheDocument(); - const contactUsLink = await screen.findByRole('link', { - name: /contact us/i, + const contactUsBtn = await screen.findByRole('button', { + name: /Contact Us/i, }); - expect(contactUsLink).toBeInTheDocument(); + expect(contactUsBtn).toBeInTheDocument(); }); test('Render for Admin', async () => { @@ -42,11 +42,11 @@ describe('WorkspaceLocked', () => { render(); const contactAdminMessage = await screen.queryByText( - /please contact your administrator for further help/i, + /contact your admin to proceed with the upgrade./i, ); expect(contactAdminMessage).not.toBeInTheDocument(); const updateCreditCardBtn = await screen.findByRole('button', { - name: /update credit card/i, + name: /continue my journey/i, }); expect(updateCreditCardBtn).toBeInTheDocument(); }); @@ -60,12 +60,12 @@ describe('WorkspaceLocked', () => { render(, {}, 'VIEWER'); const updateCreditCardBtn = await screen.queryByRole('button', { - name: /update credit card/i, + name: /Continue My Journey/i, }); expect(updateCreditCardBtn).not.toBeInTheDocument(); const contactAdminMessage = await screen.findByText( - /please contact your administrator for further help/i, + /contact your admin to proceed with the upgrade./i, ); expect(contactAdminMessage).toBeInTheDocument(); }); diff --git a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx index 0cc3990af75b..84d977ae819f 100644 --- a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx +++ b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx @@ -1,21 +1,30 @@ /* eslint-disable react/no-unescaped-entities */ import './WorkspaceLocked.styles.scss'; +import type { TabsProps } from 'antd'; import { - CreditCardOutlined, - LockOutlined, - SendOutlined, -} from '@ant-design/icons'; -import { Button, Card, Skeleton, Typography } from 'antd'; + Alert, + Button, + Col, + Collapse, + Flex, + List, + Modal, + Row, + Skeleton, + Space, + Tabs, + Typography, +} from 'antd'; import updateCreditCardApi from 'api/billing/checkout'; import logEvent from 'api/common/logEvent'; -import { SOMETHING_WENT_WRONG } from 'constants/api'; import ROUTES from 'constants/routes'; -import FullScreenHeader from 'container/FullScreenHeader/FullScreenHeader'; import useLicense from 'hooks/useLicense'; import { useNotifications } from 'hooks/useNotifications'; import history from 'lib/history'; +import { CircleArrowRight } from 'lucide-react'; import { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { useMutation } from 'react-query'; import { useSelector } from 'react-redux'; import { AppState } from 'store/reducers'; @@ -23,13 +32,22 @@ import { License } from 'types/api/licenses/def'; import AppReducer from 'types/reducer/app'; import { getFormattedDate } from 'utils/timeUtils'; +import CustomerStoryCard from './CustomerStoryCard'; +import InfoBlocks from './InfoBlocks'; +import { + customerStoriesData, + enterpriseGradeValuesData, + faqData, + infoData, +} from './workspaceLocked.data'; + export default function WorkspaceBlocked(): JSX.Element { const { role } = useSelector((state) => state.app); const isAdmin = role === 'ADMIN'; const [activeLicense, setActiveLicense] = useState(null); - const { notifications } = useNotifications(); + const { t } = useTranslation(['workspaceLocked']); const { isFetching: isFetchingLicenseData, isLoading: isLoadingLicenseData, @@ -67,7 +85,7 @@ export default function WorkspaceBlocked(): JSX.Element { }, onError: () => notifications.error({ - message: SOMETHING_WENT_WRONG, + message: t('somethingWentWrong'), }), }, ); @@ -87,73 +105,248 @@ export default function WorkspaceBlocked(): JSX.Element { logEvent('Workspace Blocked: User Clicked Extend Trial', {}); notifications.info({ - message: 'Extend Trial', + message: t('extendTrial'), + duration: 0, description: ( - If you have a specific reason why you were not able to finish your PoC in - the trial period, please write to us on - cloud-support@signoz.io - with the reason. Sometimes we can extend trial by a few days on a case by - case basis + {t('extendTrialMsgPart1')}{' '} + cloud-support@signoz.io{' '} + {t('extendTrialMsgPart2')} ), }); }; - return ( - <> - + const renderCustomerStories = ( + filterCondition: (index: number) => boolean, + ): JSX.Element[] => + customerStoriesData + .filter((_, index) => filterCondition(index)) + .map((story) => ( + + )); - - {isLoadingLicenseData || !licensesData?.payload?.workSpaceBlock ? ( - - ) : ( - <> - - Workspace Locked - - You have been locked out of your workspace because your trial ended - without an upgrade to a paid plan. Your data will continue to be ingested - till{' '} - {getFormattedDate(licensesData?.payload?.gracePeriodEnd || Date.now())} , - at which point we will drop all the ingested data and terminate the - account. - {!isAdmin && 'Please contact your administrator for further help'} - - -
+ const tabItems: TabsProps['items'] = [ + { + key: '1', + label: t('whyChooseSignoz'), + children: ( + + + + + + + + + + + {t('enterpriseGradeObservability')} + + {t('observabilityDescription')} + + ( + + } title={item.title} /> + + )} + /> + + {isAdmin && ( + + + + )} + + + + ), + }, + { + key: '2', + label: t('youAreInGoodCompany'), + children: ( + + {/* #FIXME: please suggest if there is any better way to loop in different columns to get the masonry layout */} + {renderCustomerStories((index) => index % 2 === 0)} + {renderCustomerStories((index) => index % 2 !== 0)} + {isAdmin && ( + + + + + )} + + ), + }, + // #TODO: comming soon + // { + // key: '3', + // label: 'Our Pricing', + // children: 'Our Pricing', + // }, + { + key: '4', + label: t('faqs'), + children: ( + + + + + {isAdmin && ( + )} + + + + ), + }, + ]; + return ( +
+ + + {t('trialPlanExpired')} + + + + Got Questions? + -
-
- Got Questions? - - Contact Us - -
- - )} - - + +
+ } + open + closable={false} + footer={null} + width="65%" + > +
+ {isLoadingLicenseData || !licensesData ? ( + + ) : ( + <> + + + + +
Upgrade to Continue
+
+ + {t('upgradeNow')} +
+ {t('yourDataIsSafe')}{' '} + + {getFormattedDate( + licensesData.payload?.gracePeriodEnd || Date.now(), + )} + {' '} + {t('actNow')} +
+
+ +
+ {!isAdmin && ( + + + + + + )} + {isAdmin && ( + + + + + + + + + )} + + + + + + )} +
+ +
); } diff --git a/frontend/src/pages/WorkspaceLocked/customerStoryCard.styles.scss b/frontend/src/pages/WorkspaceLocked/customerStoryCard.styles.scss new file mode 100644 index 000000000000..7abddada3a54 --- /dev/null +++ b/frontend/src/pages/WorkspaceLocked/customerStoryCard.styles.scss @@ -0,0 +1,33 @@ +$component-name: 'customer-story-card'; +$ant-card-override: 'ant-card'; +$light-theme: 'lightMode'; + +.#{$component-name} { + max-width: 385px; + margin: 0 auto; // Center the card within the column + margin-bottom: 24px; + border-radius: 6px; + transition: transform 0.3s ease, box-shadow 0.3s ease; + background-color: var(--bg-ink-400); + border: 1px solid var(--bg-ink-300); + + .#{$light-theme} & { + border: 1px solid var(--bg-vanilla-300); + background: var(--bg-vanilla-100); + } + + .#{$ant-card-override}-meta-title { + margin-bottom: 2px !important; + } + + &:hover { + transform: translateY(-2px); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + background-color: var(--bg-ink-300); + + .#{$light-theme} & { + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + background-color: var(--bg-vanilla-100); + } + } +} diff --git a/frontend/src/pages/WorkspaceLocked/workspaceLocked.data.ts b/frontend/src/pages/WorkspaceLocked/workspaceLocked.data.ts new file mode 100644 index 000000000000..0f4d07b96ea0 --- /dev/null +++ b/frontend/src/pages/WorkspaceLocked/workspaceLocked.data.ts @@ -0,0 +1,156 @@ +export const infoData = [ + { + id: 'infoBlock-1', + title: 'Built for scale', + description: + 'Our powerful ingestion engine has a proven track record of handling 10TB+ data ingestion per day.', + }, + { + id: 'infoBlock-2', + title: 'Trusted across the globe', + description: + 'Used by teams in all 5 continents ⎯ across the mountains, rivers, and the high seas.', + }, + { + id: 'infoBlock-3', + title: 'Powering observability for teams of all sizes', + description: + 'Hundreds of companies ⎯from early-stage start-ups to public enterprises use SigNoz to build more reliable products.', + }, +]; + +export const enterpriseGradeValuesData = [ + { + title: 'SSO and SAML support', + }, + { + title: 'Query API keys', + }, + { + title: 'Advanced security with SOC 2 Type I certification', + }, + { + title: 'AWS Private Link', + }, + { + title: 'VPC peering', + }, + { + title: 'Custom integrations', + }, +]; + +export const customerStoriesData = [ + { + key: 'c-story-1', + avatar: 'https://signoz.io/img/users/subomi-oluwalana.webp', + personName: 'Subomi Oluwalana', + role: 'Founder & CEO at Convoy', + customerName: 'Convoy', + message: + "We use OTel with SigNoz to spot redundant database connect calls. For example, we found that our database driver wasn't using the connection pool even though the documentation claimed otherwise.", + link: + 'https://www.linkedin.com/feed/update/urn:li:activity:7212117589068591105/', + }, + { + key: 'c-story-2', + avatar: 'https://signoz.io/img/users/dhruv-garg.webp', + personName: 'Dhruv Garg', + role: 'Tech Lead at Nudge', + customerName: 'Nudge', + message: + 'SigNoz is one of the best observability tools you can self-host hands down. And they are always there to help on their slack channel when needed.', + link: + 'https://www.linkedin.com/posts/dhruv-garg79_signoz-docker-kubernetes-activity-7205163679028240384-Otlb/', + }, + { + key: 'c-story-3', + avatar: 'https://signoz.io/img/users/vivek-bhakta.webp', + personName: 'Vivek Bhakta', + role: 'CTO at Wombo AI', + customerName: 'Wombo AI', + message: + 'We use SigNoz and have been loving it - can definitely handle scale.', + link: 'https://x.com/notorious_VB/status/1701773119696904242', + }, + { + key: 'c-story-4', + avatar: 'https://signoz.io/img/users/pranay-narang.webp', + personName: 'Pranay Narang', + role: 'Engineering at Azodha', + customerName: 'Azodha', + message: + 'Recently moved metrics and logging to SigNoz. Gotta say, absolutely loving the tool.', + link: 'https://x.com/PranayNarang/status/1676247073396752387', + }, + { + key: 'c-story-4', + avatar: 'https://signoz.io/img/users/shey.webp', + personName: 'Sheheryar Sewani', + role: 'Seasoned Rails Dev & Founder', + customerName: '', + message: + "But wow, I'm glad I tried SigNoz. Setting up SigNoz was easy—they provide super helpful instructions along with a docker-compose file.", + link: + 'https://www.linkedin.com/feed/update/urn:li:activity:7181011853915926528/', + }, + { + key: 'c-story-5', + avatar: 'https://signoz.io/img/users/daniel.webp', + personName: 'Daniel Schell', + role: 'Founder & CTO at Airlockdigital', + customerName: 'Airlockdigital', + message: + 'Have been deep diving Signoz. Seems like the new hotness for an "all-in-one".', + link: 'https://x.com/danonit/status/1749256583157284919', + }, + { + key: 'c-story-6', + avatar: 'https://signoz.io/img/users/go-frendi.webp', + personName: 'Go Frendi Gunawan', + role: 'Data Engineer at Ctlyst.id', + customerName: 'Ctlyst.id', + message: + 'Monitoring done. Thanks to SigNoz, I don’t have to deal with Grafana, Loki, Prometheus, and Jaeger separately.', + link: 'https://x.com/gofrendiasgard/status/1680139003658641408', + }, + { + key: 'c-story-7', + avatar: 'https://signoz.io/img/users/anselm.jpg', + personName: 'Anselm Eickhoff', + role: 'Software Architect', + customerName: '', + message: + 'NewRelic: receiving OpenTelemetry at all takes me 1/2 day to grok, docs are a mess. Traces show up after 5min. I burn the free 100GB/mo in 1 day of light testing. @SignozHQ: can run it locally (∞GB), has a special tutorial for OpenTelemetry + Rust! Traces show up immediately.', + link: + 'https://twitter.com/ae_play/status/1572993932094472195?s=20&t=LWWrW5EP_k5q6_mwbFN4jQ', + }, +]; + +export const faqData = [ + { + key: '1', + label: + 'What is the difference between SigNoz Cloud(Teams) and Community Edition?', + children: + 'You can self-host and manage the community edition yourself. You should choose SigNoz Cloud if you don’t want to worry about managing the SigNoz cluster. There are some exclusive features like SSO & SAML support, which come with SigNoz cloud offering. Our team also offers support on the initial configuration of dashboards & alerts and advises on best practices for setting up your observability stack in the SigNoz cloud offering.', + }, + { + key: '2', + label: 'How are number of samples calculated for metrics pricing?', + children: + "If a timeseries sends data every 30s, then it will generate 2 samples per min. So, if you have 10,000 time series sending data every 30s then you will be sending 20,000 samples per min to SigNoz. This will be around 864 mn samples per month and would cost 86.4 USD/month. Here's an explainer video on how metrics pricing is calculated - Link: https://vimeo.com/973012522", + }, + { + key: '3', + label: 'Do you offer enterprise support plans?', + children: + 'Yes, feel free to reach out to us on hello@signoz.io if you need a dedicated support plan or paid support for setting up your initial SigNoz setup.', + }, + { + key: '4', + label: 'Who should use Enterprise plans?', + children: + 'Teams which need enterprise support or features like SSO, Audit logs, etc. may find our enterprise plans valuable.', + }, +];