From 7a125e31ecf8c9733370ac62d9449598a3de66cf Mon Sep 17 00:00:00 2001 From: Vishal Sharma Date: Thu, 26 Sep 2024 17:33:21 +0530 Subject: [PATCH 01/20] chore: remove slack connect and call help (#6044) * chore: remove slack connect and call help --- frontend/src/pages/Support/Support.tsx | 36 -------------------------- 1 file changed, 36 deletions(-) diff --git a/frontend/src/pages/Support/Support.tsx b/frontend/src/pages/Support/Support.tsx index 9d3d8fff8f..668ac34143 100644 --- a/frontend/src/pages/Support/Support.tsx +++ b/frontend/src/pages/Support/Support.tsx @@ -10,8 +10,6 @@ import useLicense from 'hooks/useLicense'; import { useNotifications } from 'hooks/useNotifications'; import { Book, - Cable, - Calendar, CreditCard, Github, MessageSquare, @@ -78,22 +76,6 @@ const supportChannels = [ url: '', btnText: 'Launch chat', }, - { - key: 'schedule_call', - name: 'Schedule a call', - icon: , - title: 'Schedule a call with the founders.', - url: 'https://calendly.com/vishal-signoz/30min', - btnText: 'Schedule call', - }, - { - key: 'slack_connect', - name: 'Slack Connect', - icon: , - title: 'Get a dedicated support channel for your team.', - url: '', - btnText: 'Request Slack connect', - }, ]; export default function Support(): JSX.Element { @@ -122,20 +104,6 @@ export default function Support(): JSX.Element { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const handleSlackConnectRequest = (): void => { - const recipient = 'support@signoz.io'; - const subject = 'Slack Connect Request'; - const body = `I'd like to request a dedicated Slack Connect channel for me and my team. Users (emails) to include besides mine:`; - - // Create the mailto link - const mailtoLink = `mailto:${recipient}?subject=${encodeURIComponent( - subject, - )}&body=${encodeURIComponent(body)}`; - - // Open the default email client - window.location.href = mailtoLink; - }; - const isPremiumChatSupportEnabled = useFeatureFlags(FeatureKeys.PREMIUM_SUPPORT)?.active || false; @@ -214,15 +182,11 @@ export default function Support(): JSX.Element { case channelsMap.documentation: case channelsMap.github: case channelsMap.slack_community: - case channelsMap.schedule_call: handleChannelWithRedirects(channel.url); break; case channelsMap.chat: handleChat(); break; - case channelsMap.slack_connect: - handleSlackConnectRequest(); - break; default: handleChannelWithRedirects('https://signoz.io/slack'); break; From ef4b70f67b014393483c0adb079a2c732c323d9e Mon Sep 17 00:00:00 2001 From: Vikrant Gupta Date: Thu, 26 Sep 2024 19:06:22 +0530 Subject: [PATCH 02/20] fix: intermittent undefined page in trace details page (#6084) --- .../TracesExplorer/ListView/index.tsx | 21 ++----------------- .../TracesExplorer/ListView/utils.tsx | 18 ++++++++-------- 2 files changed, 11 insertions(+), 28 deletions(-) diff --git a/frontend/src/container/TracesExplorer/ListView/index.tsx b/frontend/src/container/TracesExplorer/ListView/index.tsx index 810ffb8241..c22623772b 100644 --- a/frontend/src/container/TracesExplorer/ListView/index.tsx +++ b/frontend/src/container/TracesExplorer/ListView/index.tsx @@ -14,9 +14,8 @@ import { Pagination } from 'hooks/queryPagination'; import useDragColumns from 'hooks/useDragColumns'; import { getDraggedColumns } from 'hooks/useDragColumns/utils'; import useUrlQueryData from 'hooks/useUrlQueryData'; -import history from 'lib/history'; import { RowData } from 'lib/query/createTableColumnsFromQuery'; -import { HTMLAttributes, memo, useCallback, useMemo } from 'react'; +import { memo, useCallback, useMemo } from 'react'; import { useSelector } from 'react-redux'; import { AppState } from 'store/reducers'; import { DataSource } from 'types/common/queryBuilder'; @@ -25,7 +24,7 @@ import { GlobalReducer } from 'types/reducer/globalTime'; import { TracesLoading } from '../TraceLoading/TraceLoading'; import { defaultSelectedColumns, PER_PAGE_OPTIONS } from './configs'; import { Container, ErrorText, tableStyles } from './styles'; -import { getListColumns, getTraceLink, transformDataWithDate } from './utils'; +import { getListColumns, transformDataWithDate } from './utils'; interface ListViewProps { isFilterApplied: boolean; @@ -108,21 +107,6 @@ function ListView({ isFilterApplied }: ListViewProps): JSX.Element { [queryTableData], ); - const handleRow = useCallback( - (record: RowData): HTMLAttributes => ({ - onClick: (event): void => { - event.preventDefault(); - event.stopPropagation(); - if (event.metaKey || event.ctrlKey) { - window.open(getTraceLink(record), '_blank'); - } else { - history.push(getTraceLink(record)); - } - }, - }), - [], - ); - const handleDragColumn = useCallback( (fromIndex: number, toIndex: number) => onDragColumns(columns, fromIndex, toIndex), @@ -169,7 +153,6 @@ function ListView({ isFilterApplied }: ListViewProps): JSX.Element { style={tableStyles} dataSource={transformedQueryTableData} columns={columns} - onRow={handleRow} onDragColumn={handleDragColumn} /> )} diff --git a/frontend/src/container/TracesExplorer/ListView/utils.tsx b/frontend/src/container/TracesExplorer/ListView/utils.tsx index a6201436d1..dc0e3808ae 100644 --- a/frontend/src/container/TracesExplorer/ListView/utils.tsx +++ b/frontend/src/container/TracesExplorer/ListView/utils.tsx @@ -47,11 +47,11 @@ export const getListColumns = ( key: 'date', title: 'Timestamp', width: 145, - render: (item): JSX.Element => { + render: (value, item): JSX.Element => { const date = - typeof item === 'string' - ? dayjs(item).format('YYYY-MM-DD HH:mm:ss.SSS') - : dayjs(item / 1e6).format('YYYY-MM-DD HH:mm:ss.SSS'); + typeof value === 'string' + ? dayjs(value).format('YYYY-MM-DD HH:mm:ss.SSS') + : dayjs(value / 1e6).format('YYYY-MM-DD HH:mm:ss.SSS'); return ( {date} @@ -67,10 +67,10 @@ export const getListColumns = ( dataIndex: key, key: `${key}-${dataType}-${type}`, width: 145, - render: (value): JSX.Element => { + render: (value, item): JSX.Element => { if (value === '') { return ( - + N/A ); @@ -78,7 +78,7 @@ export const getListColumns = ( if (key === 'httpMethod' || key === 'responseStatusCode') { return ( - + {value} @@ -88,14 +88,14 @@ export const getListColumns = ( if (key === 'durationNano') { return ( - + {getMs(value)}ms ); } return ( - + {value} ); From 44a3469b9b974f188019ba4c37d2966452171371 Mon Sep 17 00:00:00 2001 From: Sudeep MP Date: Thu, 26 Sep 2024 16:14:34 +0100 Subject: [PATCH 03/20] =?UTF-8?q?style:=20enhance=20FAQ=20container=20styl?= =?UTF-8?q?ing=20and=20adjust=20layout=20for=20customer=20s=E2=80=A6=20(#5?= =?UTF-8?q?999)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * style: enhance FAQ container styling and adjust layout for customer stories fixed the button casing faq layout shift issue due to parent flex centered * style: add dark theme support to WorkspaceLocked styles * refactor: moved inline styles to class --- .../WorkspaceLocked.styles.scss | 29 +++++++++++++++++++ .../pages/WorkspaceLocked/WorkspaceLocked.tsx | 28 +++++++++++++----- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.styles.scss b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.styles.scss index 131601bfb0..d2317c8c68 100644 --- a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.styles.scss +++ b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.styles.scss @@ -1,4 +1,5 @@ $light-theme: 'lightMode'; +$dark-theme: 'darkMode'; @keyframes gradientFlow { 0% { @@ -147,6 +148,34 @@ $light-theme: 'lightMode'; animation: gradientFlow 24s ease infinite; margin-bottom: 18px; } + + &__faq-container { + width: 100%; + + .ant-collapse, + .ant-collapse-item, + .ant-collapse-content-active { + .#{$dark-theme} & { + border-color: var(--bg-slate-400); + } + } + } + + &__customer-stories { + &__left-container, + &__right-container { + display: flex; + flex-direction: column; + } + + &__left-container { + align-items: flex-end; + } + + &__right-container { + align-items: flex-start; + } + } } .contact-us { diff --git a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx index 84d977ae81..052d8dcbc5 100644 --- a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx +++ b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx @@ -187,8 +187,18 @@ export default function WorkspaceBlocked(): JSX.Element { 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)} + + {renderCustomerStories((index) => index % 2 === 0)} + + + {renderCustomerStories((index) => index % 2 !== 0)} + {isAdmin && ( @@ -218,8 +228,12 @@ export default function WorkspaceBlocked(): JSX.Element { label: t('faqs'), children: ( - - + + {isAdmin && ( @@ -340,9 +354,9 @@ export default function WorkspaceBlocked(): JSX.Element { )} - +
- +
)} From 9b42326f80d7e92a1486e7829524f5e2735b88af Mon Sep 17 00:00:00 2001 From: Sudeep MP Date: Thu, 26 Sep 2024 19:00:58 +0100 Subject: [PATCH 04/20] chore(trial end): analytics events added (#6048) --- .../WorkspaceLocked/CustomerStoryCard.tsx | 1 + .../pages/WorkspaceLocked/WorkspaceLocked.tsx | 36 ++++++++++++++++--- .../WorkspaceLocked/workspaceLocked.data.ts | 22 ++++++------ 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/frontend/src/pages/WorkspaceLocked/CustomerStoryCard.tsx b/frontend/src/pages/WorkspaceLocked/CustomerStoryCard.tsx index c22401f7c4..68df0f5d7c 100644 --- a/frontend/src/pages/WorkspaceLocked/CustomerStoryCard.tsx +++ b/frontend/src/pages/WorkspaceLocked/CustomerStoryCard.tsx @@ -32,4 +32,5 @@ function CustomerStoryCard({ ); } + export default CustomerStoryCard; diff --git a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx index 052d8dcbc5..7b6b5af294 100644 --- a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx +++ b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx @@ -54,6 +54,23 @@ export default function WorkspaceBlocked(): JSX.Element { data: licensesData, } = useLicense(); + useEffect((): void => { + logEvent('Trial: Blocker Screen Viewed', {}); + }, []); + + const handleContactUsClick = (): void => { + logEvent('Trial: Contact Us CTA Clicked', {}); + }; + + const handleTabClick = (key: string): void => { + logEvent('Trial: Blocked Screen Tabs Clicked', { tabKey: key }); + }; + + const handleCollapseChange = (key: string | string[]): void => { + const lastKey = Array.isArray(key) ? key.slice(-1)[0] : key; + logEvent('Trial: Blocker Screen Tab FAQ Item Clicked', { panelKey: lastKey }); + }; + useEffect(() => { if (!isFetchingLicenseData) { const shouldBlockWorkspace = licensesData?.payload?.workSpaceBlock; @@ -135,7 +152,7 @@ export default function WorkspaceBlocked(): JSX.Element { const tabItems: TabsProps['items'] = [ { - key: '1', + key: 'whyChooseSignoz', label: t('whyChooseSignoz'), children: ( @@ -182,7 +199,7 @@ export default function WorkspaceBlocked(): JSX.Element { ), }, { - key: '2', + key: 'youAreInGoodCompany', label: t('youAreInGoodCompany'), children: ( @@ -224,7 +241,7 @@ export default function WorkspaceBlocked(): JSX.Element { // children: 'Our Pricing', // }, { - key: '4', + key: 'faqs', label: t('faqs'), children: ( @@ -234,7 +251,11 @@ export default function WorkspaceBlocked(): JSX.Element { direction="vertical" className="workspace-locked__faq-container" > - + {isAdmin && ( @@ -355,7 +377,11 @@ export default function WorkspaceBlocked(): JSX.Element { )}
- +
)} diff --git a/frontend/src/pages/WorkspaceLocked/workspaceLocked.data.ts b/frontend/src/pages/WorkspaceLocked/workspaceLocked.data.ts index 0f4d07b96e..bebcdaf64a 100644 --- a/frontend/src/pages/WorkspaceLocked/workspaceLocked.data.ts +++ b/frontend/src/pages/WorkspaceLocked/workspaceLocked.data.ts @@ -42,7 +42,7 @@ export const enterpriseGradeValuesData = [ export const customerStoriesData = [ { - key: 'c-story-1', + key: 'story-subomi-oluwalana', avatar: 'https://signoz.io/img/users/subomi-oluwalana.webp', personName: 'Subomi Oluwalana', role: 'Founder & CEO at Convoy', @@ -53,7 +53,7 @@ export const customerStoriesData = [ 'https://www.linkedin.com/feed/update/urn:li:activity:7212117589068591105/', }, { - key: 'c-story-2', + key: 'story-dhruv-garg', avatar: 'https://signoz.io/img/users/dhruv-garg.webp', personName: 'Dhruv Garg', role: 'Tech Lead at Nudge', @@ -64,7 +64,7 @@ export const customerStoriesData = [ 'https://www.linkedin.com/posts/dhruv-garg79_signoz-docker-kubernetes-activity-7205163679028240384-Otlb/', }, { - key: 'c-story-3', + key: 'story-vivek-bhakta', avatar: 'https://signoz.io/img/users/vivek-bhakta.webp', personName: 'Vivek Bhakta', role: 'CTO at Wombo AI', @@ -74,7 +74,7 @@ export const customerStoriesData = [ link: 'https://x.com/notorious_VB/status/1701773119696904242', }, { - key: 'c-story-4', + key: 'story-pranay-narang', avatar: 'https://signoz.io/img/users/pranay-narang.webp', personName: 'Pranay Narang', role: 'Engineering at Azodha', @@ -84,7 +84,7 @@ export const customerStoriesData = [ link: 'https://x.com/PranayNarang/status/1676247073396752387', }, { - key: 'c-story-4', + key: 'story-Sheheryar-Sewani', avatar: 'https://signoz.io/img/users/shey.webp', personName: 'Sheheryar Sewani', role: 'Seasoned Rails Dev & Founder', @@ -95,7 +95,7 @@ export const customerStoriesData = [ 'https://www.linkedin.com/feed/update/urn:li:activity:7181011853915926528/', }, { - key: 'c-story-5', + key: 'story-daniel-schell', avatar: 'https://signoz.io/img/users/daniel.webp', personName: 'Daniel Schell', role: 'Founder & CTO at Airlockdigital', @@ -115,7 +115,7 @@ export const customerStoriesData = [ link: 'https://x.com/gofrendiasgard/status/1680139003658641408', }, { - key: 'c-story-7', + key: 'story-anselm-eickhoff', avatar: 'https://signoz.io/img/users/anselm.jpg', personName: 'Anselm Eickhoff', role: 'Software Architect', @@ -129,26 +129,26 @@ export const customerStoriesData = [ export const faqData = [ { - key: '1', + key: 'signoz-cloud-vs-community', 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', + key: 'calc-for-metrics', 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', + key: 'enterprise-support-plans', 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', + key: 'who-should-use-enterprise-plans', 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.', From 88ace79a644a12a3b32684c524ec81eca1cb137f Mon Sep 17 00:00:00 2001 From: rahulkeswani101 Date: Fri, 27 Sep 2024 00:22:42 +0530 Subject: [PATCH 05/20] feat: added meta tag to prevent page indexing (#5793) * feat: added meta tag to prevent page indexing * chore: revert to previous version --------- Co-authored-by: Pranay Prateek --- frontend/src/index.html.ejs | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/index.html.ejs b/frontend/src/index.html.ejs index f77e50f2b2..d08079587b 100644 --- a/frontend/src/index.html.ejs +++ b/frontend/src/index.html.ejs @@ -49,6 +49,7 @@ /> + From e4d1452f5ff63483b95c913cae37442b286e9aae Mon Sep 17 00:00:00 2001 From: Raj Kamal Singh <1133322+raj-k-singh@users.noreply.github.com> Date: Fri, 27 Sep 2024 10:40:02 +0530 Subject: [PATCH 06/20] Feat: use new logspipelineprocessor for generating logs pipeline collector conf (#6080) * chore: update logs pipeline prefix for generated collector config * chore: some cleanup * chore: some more cleanup * chore: some more cleanup --- .../logparsingpipeline/collector_config.go | 67 +++++++++++-------- .../collector_config_test.go | 4 +- .../app/logparsingpipeline/preview.go | 4 +- pkg/query-service/constants/constants.go | 4 +- 4 files changed, 46 insertions(+), 33 deletions(-) diff --git a/pkg/query-service/app/logparsingpipeline/collector_config.go b/pkg/query-service/app/logparsingpipeline/collector_config.go index 49f697fbd3..4b8da7b18a 100644 --- a/pkg/query-service/app/logparsingpipeline/collector_config.go +++ b/pkg/query-service/app/logparsingpipeline/collector_config.go @@ -19,24 +19,28 @@ var lockLogsPipelineSpec sync.RWMutex // check if the processors already exist // if yes then update the processor. // if something doesn't exists then remove it. -func buildLogParsingProcessors(agentConf, parsingProcessors map[string]interface{}) error { +func updateProcessorConfigsInCollectorConf( + collectorConf map[string]interface{}, + signozPipelineProcessors map[string]interface{}, +) error { agentProcessors := map[string]interface{}{} - if agentConf["processors"] != nil { - agentProcessors = (agentConf["processors"]).(map[string]interface{}) + if collectorConf["processors"] != nil { + agentProcessors = (collectorConf["processors"]).(map[string]interface{}) } exists := map[string]struct{}{} - for key, params := range parsingProcessors { + for key, params := range signozPipelineProcessors { agentProcessors[key] = params exists[key] = struct{}{} } - // remove the old unwanted processors + // remove the old unwanted pipeline processors for k := range agentProcessors { - if _, ok := exists[k]; !ok && strings.HasPrefix(k, constants.LogsPPLPfx) { + _, isInDesiredPipelineProcs := exists[k] + if hasSignozPipelineProcessorPrefix(k) && !isInDesiredPipelineProcs { delete(agentProcessors, k) } } - agentConf["processors"] = agentProcessors + collectorConf["processors"] = agentProcessors return nil } @@ -65,21 +69,24 @@ func getOtelPipelineFromConfig(config map[string]interface{}) (*otelPipeline, er return &p, nil } -func buildLogsProcessors(current []string, logsParserPipeline []string) ([]string, error) { +func buildCollectorPipelineProcessorsList( + currentCollectorProcessors []string, + signozPipelineProcessorNames []string, +) ([]string, error) { lockLogsPipelineSpec.Lock() defer lockLogsPipelineSpec.Unlock() exists := map[string]struct{}{} - for _, v := range logsParserPipeline { + for _, v := range signozPipelineProcessorNames { exists[v] = struct{}{} } // removed the old processors which are not used var pipeline []string - for _, v := range current { - k := v - if _, ok := exists[k]; ok || !strings.HasPrefix(k, constants.LogsPPLPfx) { - pipeline = append(pipeline, v) + for _, procName := range currentCollectorProcessors { + _, isInDesiredPipelineProcs := exists[procName] + if isInDesiredPipelineProcs || !hasSignozPipelineProcessorPrefix(procName) { + pipeline = append(pipeline, procName) } } @@ -96,7 +103,7 @@ func buildLogsProcessors(current []string, logsParserPipeline []string) ([]strin existingVsSpec := map[int]int{} // go through plan and map its elements to current positions in effective config - for i, m := range logsParserPipeline { + for i, m := range signozPipelineProcessorNames { if loc, ok := existing[m]; ok { specVsExistingMap[i] = loc existingVsSpec[loc] = i @@ -106,11 +113,11 @@ func buildLogsProcessors(current []string, logsParserPipeline []string) ([]strin lastMatched := 0 newPipeline := []string{} - for i := 0; i < len(logsParserPipeline); i++ { - m := logsParserPipeline[i] + for i := 0; i < len(signozPipelineProcessorNames); i++ { + m := signozPipelineProcessorNames[i] if loc, ok := specVsExistingMap[i]; ok { for j := lastMatched; j < loc; j++ { - if strings.HasPrefix(pipeline[j], constants.LogsPPLPfx) { + if hasSignozPipelineProcessorPrefix(pipeline[j]) { delete(specVsExistingMap, existingVsSpec[j]) } else { newPipeline = append(newPipeline, pipeline[j]) @@ -159,13 +166,13 @@ func GenerateCollectorConfigWithPipelines( config []byte, pipelines []Pipeline, ) ([]byte, *coreModel.ApiError) { - var c map[string]interface{} - err := yaml.Unmarshal([]byte(config), &c) + var collectorConf map[string]interface{} + err := yaml.Unmarshal([]byte(config), &collectorConf) if err != nil { return nil, coreModel.BadRequest(err) } - processors, procNames, err := PreparePipelineProcessor(pipelines) + signozPipelineProcessors, signozPipelineProcNames, err := PreparePipelineProcessor(pipelines) if err != nil { return nil, coreModel.BadRequest(errors.Wrap( err, "could not prepare otel collector processors for log pipelines", @@ -174,8 +181,8 @@ func GenerateCollectorConfigWithPipelines( // Escape any `$`s as `$$` in config generated for pipelines, to ensure any occurrences // like $data do not end up being treated as env vars when loading collector config. - for _, procName := range procNames { - procConf := processors[procName] + for _, procName := range signozPipelineProcNames { + procConf := signozPipelineProcessors[procName] serializedProcConf, err := yaml.Marshal(procConf) if err != nil { return nil, coreModel.InternalError(fmt.Errorf( @@ -194,14 +201,14 @@ func GenerateCollectorConfigWithPipelines( )) } - processors[procName] = escapedConf + signozPipelineProcessors[procName] = escapedConf } // Add processors to unmarshaled collector config `c` - buildLogParsingProcessors(c, processors) + updateProcessorConfigsInCollectorConf(collectorConf, signozPipelineProcessors) // build the new processor list in service.pipelines.logs - p, err := getOtelPipelineFromConfig(c) + p, err := getOtelPipelineFromConfig(collectorConf) if err != nil { return nil, coreModel.BadRequest(err) } @@ -211,16 +218,20 @@ func GenerateCollectorConfigWithPipelines( )) } - updatedProcessorList, _ := buildLogsProcessors(p.Pipelines.Logs.Processors, procNames) + updatedProcessorList, _ := buildCollectorPipelineProcessorsList(p.Pipelines.Logs.Processors, signozPipelineProcNames) p.Pipelines.Logs.Processors = updatedProcessorList // add the new processor to the data ( no checks required as the keys will exists) - c["service"].(map[string]interface{})["pipelines"].(map[string]interface{})["logs"] = p.Pipelines.Logs + collectorConf["service"].(map[string]interface{})["pipelines"].(map[string]interface{})["logs"] = p.Pipelines.Logs - updatedConf, err := yaml.Marshal(c) + updatedConf, err := yaml.Marshal(collectorConf) if err != nil { return nil, coreModel.BadRequest(err) } return updatedConf, nil } + +func hasSignozPipelineProcessorPrefix(procName string) bool { + return strings.HasPrefix(procName, constants.LogsPPLPfx) || strings.HasPrefix(procName, constants.OldLogsPPLPfx) +} diff --git a/pkg/query-service/app/logparsingpipeline/collector_config_test.go b/pkg/query-service/app/logparsingpipeline/collector_config_test.go index f5ba7a352b..2f2d898416 100644 --- a/pkg/query-service/app/logparsingpipeline/collector_config_test.go +++ b/pkg/query-service/app/logparsingpipeline/collector_config_test.go @@ -94,7 +94,7 @@ var buildProcessorTestData = []struct { func TestBuildLogParsingProcessors(t *testing.T) { for _, test := range buildProcessorTestData { Convey(test.Name, t, func() { - err := buildLogParsingProcessors(test.agentConf, test.pipelineProcessor) + err := updateProcessorConfigsInCollectorConf(test.agentConf, test.pipelineProcessor) So(err, ShouldBeNil) So(test.agentConf, ShouldResemble, test.outputConf) }) @@ -200,7 +200,7 @@ var BuildLogsPipelineTestData = []struct { func TestBuildLogsPipeline(t *testing.T) { for _, test := range BuildLogsPipelineTestData { Convey(test.Name, t, func() { - v, err := buildLogsProcessors(test.currentPipeline, test.logsPipeline) + v, err := buildCollectorPipelineProcessorsList(test.currentPipeline, test.logsPipeline) So(err, ShouldBeNil) fmt.Println(test.Name, "\n", test.currentPipeline, "\n", v, "\n", test.expectedPipeline) So(v, ShouldResemble, test.expectedPipeline) diff --git a/pkg/query-service/app/logparsingpipeline/preview.go b/pkg/query-service/app/logparsingpipeline/preview.go index b37295eb96..548c1ee2f5 100644 --- a/pkg/query-service/app/logparsingpipeline/preview.go +++ b/pkg/query-service/app/logparsingpipeline/preview.go @@ -7,7 +7,7 @@ import ( "time" _ "github.com/SigNoz/signoz-otel-collector/pkg/parser/grok" - "github.com/open-telemetry/opentelemetry-collector-contrib/processor/logstransformprocessor" + "github.com/SigNoz/signoz-otel-collector/processor/signozlogspipelineprocessor" "github.com/pkg/errors" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/plog" @@ -42,7 +42,7 @@ func SimulatePipelinesProcessing( simulatorInputPLogs := SignozLogsToPLogs(logs) processorFactories, err := processor.MakeFactoryMap( - logstransformprocessor.NewFactory(), + signozlogspipelineprocessor.NewFactory(), ) if err != nil { return nil, nil, model.InternalError(errors.Wrap( diff --git a/pkg/query-service/constants/constants.go b/pkg/query-service/constants/constants.go index 78ee31e1a1..541d46d5ca 100644 --- a/pkg/query-service/constants/constants.go +++ b/pkg/query-service/constants/constants.go @@ -341,7 +341,9 @@ var ReservedColumnTargetAliases = map[string]struct{}{ } // logsPPLPfx is a short constant for logsPipelinePrefix -const LogsPPLPfx = "logstransform/pipeline_" +// TODO(Raj): Remove old prefix after new processor based pipelines have been rolled out +const LogsPPLPfx = "signozlogspipeline/pipeline_" +const OldLogsPPLPfx = "logstransform/pipeline_" const IntegrationPipelineIdPrefix = "integration" From 717545e14c06195e497411314b1f80a938f87867 Mon Sep 17 00:00:00 2001 From: Yunus M Date: Fri, 27 Sep 2024 12:08:25 +0530 Subject: [PATCH 07/20] feat: remove sidebar dock option (#6083) * feat: remove sidebar doc option * feat: remove all references of sidebar collapse --- frontend/src/constants/app.ts | 1 - .../constants/shortcuts/globalShortcuts.ts | 6 -- .../container/AppLayout/AppLayout.styles.scss | 6 -- frontend/src/container/AppLayout/index.tsx | 62 ++-------------- .../src/container/SideNav/SideNav.styles.scss | 37 ---------- frontend/src/container/SideNav/SideNav.tsx | 37 ++-------- .../TracesExplorer/TracesExplorer.styles.scss | 1 + frontend/src/store/actions/app/index.ts | 1 - .../src/store/actions/app/sideBarCollapse.ts | 16 ----- frontend/src/store/actions/index.ts | 1 - frontend/src/store/reducers/app.ts | 10 --- frontend/src/types/actions/app.ts | 6 -- frontend/src/types/reducer/app.ts | 1 - frontend/tests/auth.json | 70 +++++++++---------- 14 files changed, 43 insertions(+), 212 deletions(-) delete mode 100644 frontend/src/store/actions/app/index.ts delete mode 100644 frontend/src/store/actions/app/sideBarCollapse.ts diff --git a/frontend/src/constants/app.ts b/frontend/src/constants/app.ts index d260806856..c82e2a34e8 100644 --- a/frontend/src/constants/app.ts +++ b/frontend/src/constants/app.ts @@ -6,7 +6,6 @@ export const AUTH0_REDIRECT_PATH = '/redirect'; export const DEFAULT_AUTH0_APP_REDIRECTION_PATH = ROUTES.APPLICATION; -export const IS_SIDEBAR_COLLAPSED = 'isSideBarCollapsed'; export const INVITE_MEMBERS_HASH = '#invite-team-members'; export const SIGNOZ_UPGRADE_PLAN_URL = diff --git a/frontend/src/constants/shortcuts/globalShortcuts.ts b/frontend/src/constants/shortcuts/globalShortcuts.ts index 4ab7752fac..8b68b7195e 100644 --- a/frontend/src/constants/shortcuts/globalShortcuts.ts +++ b/frontend/src/constants/shortcuts/globalShortcuts.ts @@ -1,8 +1,4 @@ -import { getUserOperatingSystem, UserOperatingSystem } from 'utils/getUserOS'; - -const userOS = getUserOperatingSystem(); export const GlobalShortcuts = { - SidebarCollapse: '\\+meta', NavigateToServices: 's+shift', NavigateToTraces: 't+shift', NavigateToLogs: 'l+shift', @@ -13,7 +9,6 @@ export const GlobalShortcuts = { }; export const GlobalShortcutsName = { - SidebarCollapse: `${userOS === UserOperatingSystem.MACOS ? 'cmd' : 'ctrl'}+\\`, NavigateToServices: 'shift+s', NavigateToTraces: 'shift+t', NavigateToLogs: 'shift+l', @@ -24,7 +19,6 @@ export const GlobalShortcutsName = { }; export const GlobalShortcutsDescription = { - SidebarCollapse: 'Collpase the sidebar', NavigateToServices: 'Navigate to Services page', NavigateToTraces: 'Navigate to Traces page', NavigateToLogs: 'Navigate to logs page', diff --git a/frontend/src/container/AppLayout/AppLayout.styles.scss b/frontend/src/container/AppLayout/AppLayout.styles.scss index 2ae1531c79..a991f08351 100644 --- a/frontend/src/container/AppLayout/AppLayout.styles.scss +++ b/frontend/src/container/AppLayout/AppLayout.styles.scss @@ -16,12 +16,6 @@ width: 100%; } } - - &.docked { - .app-content { - width: calc(100% - 240px); - } - } } .chat-support-gateway { diff --git a/frontend/src/container/AppLayout/index.tsx b/frontend/src/container/AppLayout/index.tsx index 4cf2e0f5bb..4f5a3c43d7 100644 --- a/frontend/src/container/AppLayout/index.tsx +++ b/frontend/src/container/AppLayout/index.tsx @@ -5,13 +5,11 @@ import './AppLayout.styles.scss'; import * as Sentry from '@sentry/react'; import { Flex } from 'antd'; -import getLocalStorageKey from 'api/browser/localstorage/get'; import getUserLatestVersion from 'api/user/getLatestVersion'; import getUserVersion from 'api/user/getVersion'; import cx from 'classnames'; import ChatSupportGateway from 'components/ChatSupportGateway/ChatSupportGateway'; import OverlayScrollbar from 'components/OverlayScrollbar/OverlayScrollbar'; -import { IS_SIDEBAR_COLLAPSED } from 'constants/app'; import { FeatureKeys } from 'constants/features'; import ROUTES from 'constants/routes'; import SideNav from 'container/SideNav'; @@ -22,22 +20,13 @@ import useLicense from 'hooks/useLicense'; import { useNotifications } from 'hooks/useNotifications'; import history from 'lib/history'; import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; -import { - ReactNode, - useCallback, - useEffect, - useLayoutEffect, - useMemo, - useRef, - useState, -} from 'react'; +import { ReactNode, useEffect, useMemo, useRef, useState } from 'react'; import { Helmet } from 'react-helmet-async'; import { useTranslation } from 'react-i18next'; import { useQueries } from 'react-query'; import { useDispatch, useSelector } from 'react-redux'; import { useLocation } from 'react-router-dom'; import { Dispatch } from 'redux'; -import { sideBarCollapse } from 'store/actions'; import { AppState } from 'store/reducers'; import AppActions from 'types/actions'; import { @@ -59,10 +48,6 @@ function AppLayout(props: AppLayoutProps): JSX.Element { (state) => state.app, ); - const [collapsed, setCollapsed] = useState( - getLocalStorageKey(IS_SIDEBAR_COLLAPSED) === 'true', - ); - const { notifications } = useNotifications(); const isDarkMode = useIsDarkMode(); @@ -117,14 +102,6 @@ function AppLayout(props: AppLayoutProps): JSX.Element { const latestCurrentCounter = useRef(0); const latestVersionCounter = useRef(0); - const onCollapse = useCallback(() => { - setCollapsed((collapsed) => !collapsed); - }, []); - - useLayoutEffect(() => { - dispatch(sideBarCollapse(collapsed)); - }, [collapsed, dispatch]); - useEffect(() => { if ( getUserLatestVersionResponse.isFetched && @@ -279,23 +256,8 @@ function AppLayout(props: AppLayoutProps): JSX.Element { } }, [isDarkMode]); - 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 ( - + {pageTitle} @@ -321,25 +283,11 @@ function AppLayout(props: AppLayoutProps): JSX.Element { )} - + {isToDisplayLayout && !renderFullScreen && ( - + )} -
+
}> diff --git a/frontend/src/container/SideNav/SideNav.styles.scss b/frontend/src/container/SideNav/SideNav.styles.scss index 2f5167f104..1a148e2469 100644 --- a/frontend/src/container/SideNav/SideNav.styles.scss +++ b/frontend/src/container/SideNav/SideNav.styles.scss @@ -3,10 +3,6 @@ height: 100%; position: relative; z-index: 1; - - &.docked { - width: 240px; - } } .sideNav { @@ -229,39 +225,6 @@ display: block; } } - - &.docked { - flex: 0 0 240px; - max-width: 240px; - min-width: 240px; - width: 240px; - - .secondary-nav-items { - width: 240px; - } - - .brand { - justify-content: space-between; - } - - .get-started-nav-items { - .get-started-btn { - justify-content: flex-start; - } - } - - .collapse-expand-handlers { - display: block; - } - - .nav-item-label { - display: block; - } - - .nav-item-beta { - display: block; - } - } } .lightMode { diff --git a/frontend/src/container/SideNav/SideNav.tsx b/frontend/src/container/SideNav/SideNav.tsx index 1ba863d8ec..16787bc3d8 100644 --- a/frontend/src/container/SideNav/SideNav.tsx +++ b/frontend/src/container/SideNav/SideNav.tsx @@ -3,7 +3,7 @@ import './SideNav.styles.scss'; import { Color } from '@signozhq/design-tokens'; -import { Button, Tooltip } from 'antd'; +import { Button } from 'antd'; import logEvent from 'api/common/logEvent'; import cx from 'classnames'; import { FeatureKeys } from 'constants/features'; @@ -16,9 +16,6 @@ import history from 'lib/history'; import { AlertTriangle, CheckSquare, - ChevronLeftCircle, - ChevronRightCircle, - PanelRight, RocketIcon, UserCircle, } from 'lucide-react'; @@ -55,13 +52,9 @@ interface UserManagementMenuItems { function SideNav({ licenseData, isFetching, - onCollapse, - collapsed, }: { licenseData: any; isFetching: boolean; - onCollapse: () => void; - collapsed: boolean; }): JSX.Element { const [menuItems, setMenuItems] = useState(defaultMenuItems); @@ -330,8 +323,6 @@ function SideNav({ }; useEffect(() => { - registerShortcut(GlobalShortcuts.SidebarCollapse, onCollapse); - registerShortcut(GlobalShortcuts.NavigateToServices, () => onClickHandler(ROUTES.APPLICATION, null), ); @@ -359,7 +350,6 @@ function SideNav({ ); return (): void => { - deregisterShortcut(GlobalShortcuts.SidebarCollapse); deregisterShortcut(GlobalShortcuts.NavigateToServices); deregisterShortcut(GlobalShortcuts.NavigateToTraces); deregisterShortcut(GlobalShortcuts.NavigateToLogs); @@ -368,11 +358,11 @@ function SideNav({ deregisterShortcut(GlobalShortcuts.NavigateToExceptions); deregisterShortcut(GlobalShortcuts.NavigateToMessagingQueues); }; - }, [deregisterShortcut, onClickHandler, onCollapse, registerShortcut]); + }, [deregisterShortcut, onClickHandler, registerShortcut]); return ( -
-
+
+
{licenseTag}
)}
- - -
{isCloudUserVal && ( @@ -504,14 +483,6 @@ function SideNav({ }} /> )} - -
- {collapsed ? ( - - ) : ( - - )} -
diff --git a/frontend/src/pages/TracesExplorer/TracesExplorer.styles.scss b/frontend/src/pages/TracesExplorer/TracesExplorer.styles.scss index cf6eb52b10..4323f901d5 100644 --- a/frontend/src/pages/TracesExplorer/TracesExplorer.styles.scss +++ b/frontend/src/pages/TracesExplorer/TracesExplorer.styles.scss @@ -1,6 +1,7 @@ .trace-explorer-header { display: flex; justify-content: space-between; + align-items: center; .trace-explorer-run-query { display: flex; diff --git a/frontend/src/store/actions/app/index.ts b/frontend/src/store/actions/app/index.ts deleted file mode 100644 index cb2a26f9e6..0000000000 --- a/frontend/src/store/actions/app/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './sideBarCollapse'; diff --git a/frontend/src/store/actions/app/sideBarCollapse.ts b/frontend/src/store/actions/app/sideBarCollapse.ts deleted file mode 100644 index c99d79b6fb..0000000000 --- a/frontend/src/store/actions/app/sideBarCollapse.ts +++ /dev/null @@ -1,16 +0,0 @@ -import setLocalStorageKey from 'api/browser/localstorage/set'; -import { IS_SIDEBAR_COLLAPSED } from 'constants/app'; -import { Dispatch } from 'redux'; -import AppActions from 'types/actions'; - -export const sideBarCollapse = ( - collapseState: boolean, -): ((dispatch: Dispatch) => void) => { - setLocalStorageKey(IS_SIDEBAR_COLLAPSED, `${collapseState}`); - return (dispatch: Dispatch): void => { - dispatch({ - type: 'SIDEBAR_COLLAPSE', - payload: collapseState, - }); - }; -}; diff --git a/frontend/src/store/actions/index.ts b/frontend/src/store/actions/index.ts index 3074cdb3a2..f50fb7477c 100644 --- a/frontend/src/store/actions/index.ts +++ b/frontend/src/store/actions/index.ts @@ -1,4 +1,3 @@ -export * from './app'; export * from './global'; export * from './metrics'; export * from './serviceMap'; diff --git a/frontend/src/store/reducers/app.ts b/frontend/src/store/reducers/app.ts index 4db3965cad..bdb80d2565 100644 --- a/frontend/src/store/reducers/app.ts +++ b/frontend/src/store/reducers/app.ts @@ -1,11 +1,9 @@ import getLocalStorageKey from 'api/browser/localstorage/get'; -import { IS_SIDEBAR_COLLAPSED } from 'constants/app'; import { LOCALSTORAGE } from 'constants/localStorage'; import { getInitialUserTokenRefreshToken } from 'store/utils'; import { AppAction, LOGGED_IN, - SIDEBAR_COLLAPSE, UPDATE_CONFIGS, UPDATE_CURRENT_ERROR, UPDATE_CURRENT_VERSION, @@ -44,7 +42,6 @@ const getInitialUser = (): User | null => { const InitialValue: InitialValueTypes = { isLoggedIn: getLocalStorageKey(LOCALSTORAGE.IS_LOGGED_IN) === 'true', - isSideBarCollapsed: getLocalStorageKey(IS_SIDEBAR_COLLAPSED) === 'true', currentVersion: '', latestVersion: '', featureResponse: { @@ -76,13 +73,6 @@ const appReducer = ( }; } - case SIDEBAR_COLLAPSE: { - return { - ...state, - isSideBarCollapsed: action.payload, - }; - } - case UPDATE_FEATURE_FLAG_RESPONSE: { return { ...state, diff --git a/frontend/src/types/actions/app.ts b/frontend/src/types/actions/app.ts index 78a5da72ad..54b1992af2 100644 --- a/frontend/src/types/actions/app.ts +++ b/frontend/src/types/actions/app.ts @@ -34,11 +34,6 @@ export interface LoggedInUser { }; } -export interface SideBarCollapse { - type: typeof SIDEBAR_COLLAPSE; - payload: boolean; -} - export interface UpdateAppVersion { type: typeof UPDATE_CURRENT_VERSION; payload: { @@ -137,7 +132,6 @@ export interface UpdateFeatureFlag { export type AppAction = | LoggedInUser - | SideBarCollapse | UpdateAppVersion | UpdateLatestVersion | UpdateVersionError diff --git a/frontend/src/types/reducer/app.ts b/frontend/src/types/reducer/app.ts index 545cff7156..c51defcfb0 100644 --- a/frontend/src/types/reducer/app.ts +++ b/frontend/src/types/reducer/app.ts @@ -17,7 +17,6 @@ export interface User { export default interface AppReducer { isLoggedIn: boolean; - isSideBarCollapsed: boolean; currentVersion: string; latestVersion: string; isCurrentVersionError: boolean; diff --git a/frontend/tests/auth.json b/frontend/tests/auth.json index 2dd3d40466..0de47618ab 100644 --- a/frontend/tests/auth.json +++ b/frontend/tests/auth.json @@ -1,38 +1,34 @@ { - "cookies": [], - "origins": [ - { - "origin": "http://localhost:3301", - "localStorage": [ - { - "name": "isSideBarCollapsed", - "value": "false" - }, - { - "name": "metricsTimeDurations", - "value": "{}" - }, - { - "name": "i18nextLng", - "value": "en-US" - }, - { - "name": "reactQueryDevtoolsSortFn", - "value": "\"Status > Last Updated\"" - }, - { - "name": "AUTH_TOKEN", - "value": "authtoken" - }, - { - "name": "IS_LOGGED_IN", - "value": "true" - }, - { - "name": "REFRESH_AUTH_TOKEN", - "value": "refreshJwt" - } - ] - } - ] -} \ No newline at end of file + "cookies": [], + "origins": [ + { + "origin": "http://localhost:3301", + "localStorage": [ + { + "name": "metricsTimeDurations", + "value": "{}" + }, + { + "name": "i18nextLng", + "value": "en-US" + }, + { + "name": "reactQueryDevtoolsSortFn", + "value": "\"Status > Last Updated\"" + }, + { + "name": "AUTH_TOKEN", + "value": "authtoken" + }, + { + "name": "IS_LOGGED_IN", + "value": "true" + }, + { + "name": "REFRESH_AUTH_TOKEN", + "value": "refreshJwt" + } + ] + } + ] +} From 4c95df44d5f0edeb48d449778b1c065416465cc6 Mon Sep 17 00:00:00 2001 From: Vishal Sharma Date: Fri, 27 Sep 2024 18:20:17 +0530 Subject: [PATCH 08/20] chore: update trial end workspace event (#6088) --- frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx index 7b6b5af294..602e666137 100644 --- a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx +++ b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx @@ -55,20 +55,22 @@ export default function WorkspaceBlocked(): JSX.Element { } = useLicense(); useEffect((): void => { - logEvent('Trial: Blocker Screen Viewed', {}); + logEvent('Workspace Blocked: Screen Viewed', {}); }, []); const handleContactUsClick = (): void => { - logEvent('Trial: Contact Us CTA Clicked', {}); + logEvent('Workspace Blocked: Contact Us Clicked', {}); }; const handleTabClick = (key: string): void => { - logEvent('Trial: Blocked Screen Tabs Clicked', { tabKey: key }); + logEvent('Workspace Blocked: Screen Tabs Clicked', { tabKey: key }); }; const handleCollapseChange = (key: string | string[]): void => { const lastKey = Array.isArray(key) ? key.slice(-1)[0] : key; - logEvent('Trial: Blocker Screen Tab FAQ Item Clicked', { panelKey: lastKey }); + logEvent('Workspace Blocked: Screen Tab FAQ Item Clicked', { + panelKey: lastKey, + }); }; useEffect(() => { From 794d6fc0cae6bc887935f8657f42f6471dc59c15 Mon Sep 17 00:00:00 2001 From: rahulkeswani101 Date: Mon, 30 Sep 2024 11:30:41 +0530 Subject: [PATCH 09/20] feat: added a new logo for sidebar and login page (#6005) * feat: added a new logo for sidebar and login page * chore: removed the signoz-signup.svg * feat: updated the svg * feat: updated the svg --- frontend/public/Logos/signoz-brand-logo.svg | 18 +++++++----------- frontend/public/favicon.ico | Bin 2218 -> 12870 bytes frontend/public/signoz-signup.svg | 9 --------- .../components/WelcomeLeftContainer/index.tsx | 2 +- 4 files changed, 8 insertions(+), 21 deletions(-) delete mode 100644 frontend/public/signoz-signup.svg diff --git a/frontend/public/Logos/signoz-brand-logo.svg b/frontend/public/Logos/signoz-brand-logo.svg index aaa8a77669..a9cce28993 100644 --- a/frontend/public/Logos/signoz-brand-logo.svg +++ b/frontend/public/Logos/signoz-brand-logo.svg @@ -1,11 +1,7 @@ - - - - - - - - - - - + + + + + + + diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico index 98a6d5f7dc1fa355104d4436132c1df3c5c6d61f..b83e8b561082fe946c7424cecd6babbd0b87b74a 100644 GIT binary patch literal 12870 zcmV-MGP%u(P)l!r*1ZzT8_xCUt78ep7J2ME5#2cX!kjo@^P&WH+%;%AQ!+E48n zP|@jb6&t6={zyQ3Y;6dR_NYW9j?w~tUmG+b;h9Tv^S)=Vsaoq_t7_kSu7c46C+D?y z?W*tqCvlTEmf?|Oda19l?RN>gMCUKRukSorAX+MfUp)yP06j~GS zohwjVg_itB>h!EoP|?4>5$}2E9p4GQ;nMC@HpZK!>sB8`w1(HOpQ4BPcvuQ4irAUb zTXU~3QftT8F0#^}=z4;zIW8dTB__rYmn1d;a5c+#Z{`h2n+o*nxQI1rE%uLBRfcuA zA_SeZ!%U!T$}yLs@GkuBo}`{j&@iRB%8K{!+;Xr`3^V`uQ2u50favlA*RS6|`>T+h zlap^9F~2__xKz6YXwmnjw+u^D%MULwv*&8Ogkyw5m-Y_>64*yb;YB7~SA@4xhMa1v zF4Sfy@DEcCH=x#h;ceqWP)1dy4Gaefn~BBnSQVkCc}GnshJG#NVc7ZYUHSR`3}>IG z-&P^hlan9MFK_MHHb!R(0A4e?rhV#6VBB~~052MGglUdx90E$KBWWP3eo>9u5T2OY z)_QOgUzm_1lGWd#3|Az)r3*uEp{nOWrf3YHm}m|($;{UDOw@R@D)^IGDQ}}kqL2bn zJD9J_Z&&tBiQIbO*Kl|hvWue%z2^}eUJ!<80+)cI@UU4u3uTObG&V@mKd?GgD1m34 z3ihDZ-RUcf)UFv|WL zUr+U~zf02&H3k*$^_rcN5w6A~7^i>7xQ-)&l(8gWUVhE}lsZ;u)2~5J=2V)KL!#@( z$$pMP08^6zw}2(vaT;oAAsD5ajK?c#U)-jr{OWK|G@gt)?7(MjSv33xVM;Bl|QHpQzr=5iQ|M>lc( z<58Mg30e0ZJrABUzo=KtD*hB|X} zOb|-~=2|w(Ex`rJsKcE#Na?X)55pW{s?5xe>(B~L>Y8J91ZF!1KTR;_4sis|q1FUD zGO(#cgKH>wdyXleX!>T4lH_GJwKgAkjH6`7O$G&Pg2nXnjRXOC;s(Wpm0?It2HbLSDX9vRet>V)(n}OwF?xnGi>^s85jh!<;mivJ0A0g% zgoAwr@*`h?b-9?Q_K7^v<4Hi)i0FO!$YVN3K#Lo2;VKtyT(n|0>|YgO@6CnHJc@$^ zB(yQ5V!w^5i4T_Bu*V_}NGiW2jlEQ$&c0)VC$wqM!`7c

H?^HyH1+0#K?Q_5Rkr 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 diff --git a/frontend/public/signoz-signup.svg b/frontend/public/signoz-signup.svg deleted file mode 100644 index 67c45b1c23..0000000000 --- a/frontend/public/signoz-signup.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/frontend/src/components/WelcomeLeftContainer/index.tsx b/frontend/src/components/WelcomeLeftContainer/index.tsx index 3e8ec68e42..ea238723ae 100644 --- a/frontend/src/components/WelcomeLeftContainer/index.tsx +++ b/frontend/src/components/WelcomeLeftContainer/index.tsx @@ -16,7 +16,7 @@ function WelcomeLeftContainer({ - + SigNoz {t('monitor_signup')} From 5a0a7c2c6031d8e69bad334e27973bf6da8a052e Mon Sep 17 00:00:00 2001 From: SagarRajput-7 <162284829+SagarRajput-7@users.noreply.github.com> Date: Mon, 30 Sep 2024 11:48:48 +0530 Subject: [PATCH 10/20] fix: restricted column long value to 3 line and line clamped (#6056) * fix: restricted column long value to 3 line and line clamped * fix: added tooltip prop as prop for generic component and passed style from consumer * fix: comment resolved * fix: refactored styles * fix: updated snapshot * fix: removed console log --- .../GridTableComponent.styles.scss | 5 ++ .../container/GridTableComponent/index.tsx | 28 ++++++- .../LogsPanelComponent.styles.scss | 3 +- .../TablePanelWrapper.test.tsx.snap | 84 +++++++++++++++---- .../TracesTableComponent.styles.scss | 3 +- .../LineClampedText/LineClampedText.tsx | 17 +++- 6 files changed, 118 insertions(+), 22 deletions(-) create mode 100644 frontend/src/container/GridTableComponent/GridTableComponent.styles.scss diff --git a/frontend/src/container/GridTableComponent/GridTableComponent.styles.scss b/frontend/src/container/GridTableComponent/GridTableComponent.styles.scss new file mode 100644 index 0000000000..80491e991a --- /dev/null +++ b/frontend/src/container/GridTableComponent/GridTableComponent.styles.scss @@ -0,0 +1,5 @@ +.long-text-tooltip { + max-width: 500px; + max-height: 500px; + overflow-y: auto; +} diff --git a/frontend/src/container/GridTableComponent/index.tsx b/frontend/src/container/GridTableComponent/index.tsx index fbd3892c48..dfa90b8255 100644 --- a/frontend/src/container/GridTableComponent/index.tsx +++ b/frontend/src/container/GridTableComponent/index.tsx @@ -1,3 +1,5 @@ +import './GridTableComponent.styles.scss'; + import { ExclamationCircleFilled } from '@ant-design/icons'; import { Space, Tooltip } from 'antd'; import { getYAxisFormattedValue } from 'components/Graph/yAxisConfig'; @@ -5,6 +7,7 @@ import { Events } from 'constants/events'; import { QueryTable } from 'container/QueryTable'; import { RowData } from 'lib/query/createTableColumnsFromQuery'; import { cloneDeep, get, isEmpty } from 'lodash-es'; +import LineClampedText from 'periscope/components/LineClampedText/LineClampedText'; import { memo, ReactNode, useCallback, useEffect, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { eventEmitter } from 'utils/getEventEmitter'; @@ -116,7 +119,16 @@ function GridTableComponent({ } > - {text} + + {hasMultipleMatches && ( @@ -127,7 +139,19 @@ function GridTableComponent({ ); } } - return

{text}
; + return ( +
+ +
+ ); }, })); diff --git a/frontend/src/container/LogsPanelTable/LogsPanelComponent.styles.scss b/frontend/src/container/LogsPanelTable/LogsPanelComponent.styles.scss index b355c90551..99f93a7935 100644 --- a/frontend/src/container/LogsPanelTable/LogsPanelComponent.styles.scss +++ b/frontend/src/container/LogsPanelTable/LogsPanelComponent.styles.scss @@ -63,8 +63,7 @@ height: 40px; justify-content: end; padding: 0 8px; - margin-top: 12px; - margin-bottom: 2px; + margin: 12px 0 2px; } } diff --git a/frontend/src/container/PanelWrapper/__tests__/__snapshots__/TablePanelWrapper.test.tsx.snap b/frontend/src/container/PanelWrapper/__tests__/__snapshots__/TablePanelWrapper.test.tsx.snap index 1a930f740c..6de3e82778 100644 --- a/frontend/src/container/PanelWrapper/__tests__/__snapshots__/TablePanelWrapper.test.tsx.snap +++ b/frontend/src/container/PanelWrapper/__tests__/__snapshots__/TablePanelWrapper.test.tsx.snap @@ -266,14 +266,22 @@ exports[`Table panel wrappper tests table should render fine with the query resp class="ant-table-cell" >
- demo-app +
+ demo-app +
- 4.35 s +
+ 4.35 s +
@@ -284,14 +292,22 @@ exports[`Table panel wrappper tests table should render fine with the query resp class="ant-table-cell" >
- customer +
+ customer +
- 431 ms +
+ 431 ms +
@@ -302,14 +318,22 @@ exports[`Table panel wrappper tests table should render fine with the query resp class="ant-table-cell" >
- mysql +
+ mysql +
- 431 ms +
+ 431 ms +
@@ -320,14 +344,22 @@ exports[`Table panel wrappper tests table should render fine with the query resp class="ant-table-cell" >
- frontend +
+ frontend +
- 287 ms +
+ 287 ms +
@@ -338,14 +370,22 @@ exports[`Table panel wrappper tests table should render fine with the query resp class="ant-table-cell" >
- driver +
+ driver +
- 230 ms +
+ 230 ms +
@@ -356,14 +396,22 @@ exports[`Table panel wrappper tests table should render fine with the query resp class="ant-table-cell" >
- route +
+ route +
- 66.4 ms +
+ 66.4 ms +
@@ -374,14 +422,22 @@ exports[`Table panel wrappper tests table should render fine with the query resp class="ant-table-cell" >
- redis +
+ redis +
- 31.3 ms +
+ 31.3 ms +
diff --git a/frontend/src/container/TracesTableComponent/TracesTableComponent.styles.scss b/frontend/src/container/TracesTableComponent/TracesTableComponent.styles.scss index c59bf3c5ad..30f90d4a09 100644 --- a/frontend/src/container/TracesTableComponent/TracesTableComponent.styles.scss +++ b/frontend/src/container/TracesTableComponent/TracesTableComponent.styles.scss @@ -52,8 +52,7 @@ height: 40px; justify-content: end; padding: 0 8px; - margin-top: 12px; - margin-bottom: 2px; + margin: 12px 0 2px; } } diff --git a/frontend/src/periscope/components/LineClampedText/LineClampedText.tsx b/frontend/src/periscope/components/LineClampedText/LineClampedText.tsx index 6b90704b0c..9c77d514e0 100644 --- a/frontend/src/periscope/components/LineClampedText/LineClampedText.tsx +++ b/frontend/src/periscope/components/LineClampedText/LineClampedText.tsx @@ -1,14 +1,16 @@ import './LineClampedText.styles.scss'; -import { Tooltip } from 'antd'; +import { Tooltip, TooltipProps } from 'antd'; import { useEffect, useRef, useState } from 'react'; function LineClampedText({ text, lines, + tooltipProps, }: { text: string; lines?: number; + tooltipProps?: TooltipProps; }): JSX.Element { const [isOverflowing, setIsOverflowing] = useState(false); const textRef = useRef(null); @@ -42,11 +44,22 @@ function LineClampedText({
); - return isOverflowing ? {content} : content; + return isOverflowing ? ( + + {content} + + ) : ( + content + ); } LineClampedText.defaultProps = { lines: 1, + tooltipProps: {}, }; export default LineClampedText; From 3b7455ac4cfbfdac281d4abee2590c70d3861258 Mon Sep 17 00:00:00 2001 From: Yunus M Date: Mon, 30 Sep 2024 12:41:11 +0530 Subject: [PATCH 11/20] fix: wait for licenseData to resolve before the check to show chat support (#6091) --- frontend/src/AppRoutes/index.tsx | 56 +++++++++++++++++--------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/frontend/src/AppRoutes/index.tsx b/frontend/src/AppRoutes/index.tsx index 8400afbde3..846ec02ac4 100644 --- a/frontend/src/AppRoutes/index.tsx +++ b/frontend/src/AppRoutes/index.tsx @@ -12,6 +12,7 @@ import useAnalytics from 'hooks/analytics/useAnalytics'; import { KeyboardHotkeysProvider } from 'hooks/hotkeys/useKeyboardHotkeys'; import { useIsDarkMode, useThemeConfig } from 'hooks/useDarkMode'; import { THEME_MODE } from 'hooks/useDarkMode/constant'; +import useFeatureFlags from 'hooks/useFeatureFlag'; import useGetFeatureFlag from 'hooks/useGetFeatureFlag'; import useLicense, { LICENSE_PLAN_KEY } from 'hooks/useLicense'; import { NotificationProvider } from 'hooks/useNotifications'; @@ -58,23 +59,16 @@ function App(): JSX.Element { const isDarkMode = useIsDarkMode(); + const isOnboardingEnabled = + useFeatureFlags(FeatureKeys.ONBOARDING)?.active || false; + + const isChatSupportEnabled = + useFeatureFlags(FeatureKeys.CHAT_SUPPORT)?.active || false; + + const isPremiumSupportEnabled = + useFeatureFlags(FeatureKeys.PREMIUM_SUPPORT)?.active || false; + const featureResponse = useGetFeatureFlag((allFlags) => { - const isOnboardingEnabled = - allFlags.find((flag) => flag.name === FeatureKeys.ONBOARDING)?.active || - false; - - const isChatSupportEnabled = - allFlags.find((flag) => flag.name === FeatureKeys.CHAT_SUPPORT)?.active || - false; - - const isPremiumSupportEnabled = - allFlags.find((flag) => flag.name === FeatureKeys.PREMIUM_SUPPORT)?.active || - false; - - const showAddCreditCardModal = - !isPremiumSupportEnabled && - !licenseData?.payload?.trialConvertedToSubscription; - dispatch({ type: UPDATE_FEATURE_FLAG_RESPONSE, payload: { @@ -90,16 +84,6 @@ function App(): JSX.Element { setRoutes(newRoutes); } - - if (isLoggedInState && isChatSupportEnabled && !showAddCreditCardModal) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - window.Intercom('boot', { - app_id: process.env.INTERCOM_APP_ID, - email: user?.email || '', - name: user?.name || '', - }); - } }); const isOnBasicPlan = @@ -201,6 +185,26 @@ function App(): JSX.Element { // eslint-disable-next-line react-hooks/exhaustive-deps }, [pathname]); + useEffect(() => { + const showAddCreditCardModal = + !isPremiumSupportEnabled && + !licenseData?.payload?.trialConvertedToSubscription; + + if (isLoggedInState && isChatSupportEnabled && !showAddCreditCardModal) { + window.Intercom('boot', { + app_id: process.env.INTERCOM_APP_ID, + email: user?.email || '', + name: user?.name || '', + }); + } + }, [ + isLoggedInState, + isChatSupportEnabled, + user, + licenseData, + isPremiumSupportEnabled, + ]); + useEffect(() => { if (user && user?.email && user?.userId && user?.name) { try { From bc8891d2f851bcb32e6e622ec66db33e5a3fe4b6 Mon Sep 17 00:00:00 2001 From: Prashant Shahi Date: Mon, 30 Sep 2024 18:02:56 +0530 Subject: [PATCH 12/20] Sync/post release v0.55 (#6092) --- .../clickhouse-setup/docker-compose.yaml | 10 +++++----- .../clickhouse-setup/otel-collector-config.yaml | 1 + .../docker/clickhouse-setup/docker-compose-core.yaml | 4 ++-- .../clickhouse-setup/docker-compose-local.yaml | 2 +- .../clickhouse-setup/docker-compose.testing.yaml | 12 ++++++------ deploy/docker/clickhouse-setup/docker-compose.yaml | 12 ++++++------ .../clickhouse-setup/otel-collector-config.yaml | 1 + go.mod | 2 +- go.sum | 4 ---- .../tests/test-deploy/docker-compose.yaml | 6 +++--- .../tests/test-deploy/otel-collector-config.yaml | 1 + 11 files changed, 27 insertions(+), 28 deletions(-) diff --git a/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml b/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml index c584bb50e7..c8d9e54421 100644 --- a/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml +++ b/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml @@ -146,11 +146,11 @@ services: condition: on-failure query-service: - image: signoz/query-service:0.49.1 + image: signoz/query-service:0.55.0 command: [ "-config=/root/config/prometheus.yml", - # "--prefer-delta=true" + "--use-logs-new-schema=true" ] # ports: # - "6060:6060" # pprof port @@ -186,7 +186,7 @@ services: <<: *db-depend frontend: - image: signoz/frontend:0.48.0 + image: signoz/frontend:0.55.0 deploy: restart_policy: condition: on-failure @@ -199,7 +199,7 @@ services: - ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf otel-collector: - image: signoz/signoz-otel-collector:0.102.2 + image: signoz/signoz-otel-collector:0.102.10 command: [ "--config=/etc/otel-collector-config.yaml", @@ -238,7 +238,7 @@ services: - query-service otel-collector-migrator: - image: signoz/signoz-schema-migrator:0.102.2 + image: signoz/signoz-schema-migrator:0.102.10 deploy: restart_policy: condition: on-failure diff --git a/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml b/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml index afa8291358..a0859ef633 100644 --- a/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml +++ b/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml @@ -144,6 +144,7 @@ exporters: dsn: tcp://clickhouse:9000/signoz_logs docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER} timeout: 10s + use_new_schema: true extensions: health_check: endpoint: 0.0.0.0:13133 diff --git a/deploy/docker/clickhouse-setup/docker-compose-core.yaml b/deploy/docker/clickhouse-setup/docker-compose-core.yaml index 17f7c3e4a3..7a2bcdfa75 100644 --- a/deploy/docker/clickhouse-setup/docker-compose-core.yaml +++ b/deploy/docker/clickhouse-setup/docker-compose-core.yaml @@ -66,7 +66,7 @@ services: - --storage.path=/data otel-collector-migrator: - image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.102.2} + image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.102.10} container_name: otel-migrator command: - "--dsn=tcp://clickhouse:9000" @@ -81,7 +81,7 @@ services: # Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md` otel-collector: container_name: signoz-otel-collector - image: signoz/signoz-otel-collector:0.102.2 + image: signoz/signoz-otel-collector:0.102.10 command: [ "--config=/etc/otel-collector-config.yaml", diff --git a/deploy/docker/clickhouse-setup/docker-compose-local.yaml b/deploy/docker/clickhouse-setup/docker-compose-local.yaml index 248c7bf9f6..7effc129fe 100644 --- a/deploy/docker/clickhouse-setup/docker-compose-local.yaml +++ b/deploy/docker/clickhouse-setup/docker-compose-local.yaml @@ -25,7 +25,7 @@ services: command: [ "-config=/root/config/prometheus.yml", - # "--prefer-delta=true" + "--use-logs-new-schema=true" ] ports: - "6060:6060" diff --git a/deploy/docker/clickhouse-setup/docker-compose.testing.yaml b/deploy/docker/clickhouse-setup/docker-compose.testing.yaml index 8d4564af31..174f0914a9 100644 --- a/deploy/docker/clickhouse-setup/docker-compose.testing.yaml +++ b/deploy/docker/clickhouse-setup/docker-compose.testing.yaml @@ -164,13 +164,13 @@ services: # Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md` query-service: - image: signoz/query-service:${DOCKER_TAG:-0.49.1} + image: signoz/query-service:${DOCKER_TAG:-0.55.0} container_name: signoz-query-service command: [ "-config=/root/config/prometheus.yml", - "-gateway-url=https://api.staging.signoz.cloud" - # "--prefer-delta=true" + "-gateway-url=https://api.staging.signoz.cloud", + "--use-logs-new-schema=true" ] # ports: # - "6060:6060" # pprof port @@ -204,7 +204,7 @@ services: <<: *db-depend frontend: - image: signoz/frontend:${DOCKER_TAG:-0.49.1} + image: signoz/frontend:${DOCKER_TAG:-0.55.0} container_name: signoz-frontend restart: on-failure depends_on: @@ -216,7 +216,7 @@ services: - ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf otel-collector-migrator: - image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.102.2} + image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.102.10} container_name: otel-migrator command: - "--dsn=tcp://clickhouse:9000" @@ -230,7 +230,7 @@ services: otel-collector: - image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.102.2} + image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.102.10} container_name: signoz-otel-collector command: [ diff --git a/deploy/docker/clickhouse-setup/docker-compose.yaml b/deploy/docker/clickhouse-setup/docker-compose.yaml index 17a975e5a6..0c333899aa 100644 --- a/deploy/docker/clickhouse-setup/docker-compose.yaml +++ b/deploy/docker/clickhouse-setup/docker-compose.yaml @@ -164,12 +164,12 @@ services: # Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md` query-service: - image: signoz/query-service:${DOCKER_TAG:-0.49.1} + image: signoz/query-service:${DOCKER_TAG:-0.55.0} container_name: signoz-query-service command: [ - "-config=/root/config/prometheus.yml" - # "--prefer-delta=true" + "-config=/root/config/prometheus.yml", + "--use-logs-new-schema=true" ] # ports: # - "6060:6060" # pprof port @@ -203,7 +203,7 @@ services: <<: *db-depend frontend: - image: signoz/frontend:${DOCKER_TAG:-0.49.1} + image: signoz/frontend:${DOCKER_TAG:-0.55.0} container_name: signoz-frontend restart: on-failure depends_on: @@ -215,7 +215,7 @@ services: - ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf otel-collector-migrator: - image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.102.2} + image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.102.10} container_name: otel-migrator command: - "--dsn=tcp://clickhouse:9000" @@ -229,7 +229,7 @@ services: otel-collector: - image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.102.2} + image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.102.10} container_name: signoz-otel-collector command: [ diff --git a/deploy/docker/clickhouse-setup/otel-collector-config.yaml b/deploy/docker/clickhouse-setup/otel-collector-config.yaml index 6f30d42ad1..72e4f3dcc7 100644 --- a/deploy/docker/clickhouse-setup/otel-collector-config.yaml +++ b/deploy/docker/clickhouse-setup/otel-collector-config.yaml @@ -154,6 +154,7 @@ exporters: dsn: tcp://clickhouse:9000/signoz_logs docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER} timeout: 10s + use_new_schema: true # logging: {} service: diff --git a/go.mod b/go.mod index 6f523045d1..628384c2fe 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,6 @@ require ( github.com/mailru/easyjson v0.7.7 github.com/mattn/go-sqlite3 v2.0.3+incompatible github.com/minio/minio-go/v6 v6.0.57 - github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c github.com/oklog/oklog v0.3.2 github.com/open-telemetry/opamp-go v0.5.0 github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.102.0 @@ -141,6 +140,7 @@ require ( github.com/minio/sha256-simd v0.1.1 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect diff --git a/go.sum b/go.sum index c557bc6f87..332f4507e1 100644 --- a/go.sum +++ b/go.sum @@ -64,8 +64,6 @@ github.com/SigNoz/govaluate v0.0.0-20240203125216-988004ccc7fd h1:Bk43AsDYe0fhkb github.com/SigNoz/govaluate v0.0.0-20240203125216-988004ccc7fd/go.mod h1:nxRcH/OEdM8QxzH37xkGzomr1O0JpYBRS6pwjsWW6Pc= github.com/SigNoz/prometheus v1.11.1 h1:roM8ugYf4UxaeKKujEeBvoX7ybq3IrS+TB26KiRtIJg= github.com/SigNoz/prometheus v1.11.1/go.mod h1:uv4mQwZQtx7y4GQ6EdHOi8Wsk07uHNn2XHd1zM85m6I= -github.com/SigNoz/signoz-otel-collector v0.102.2 h1:SmjsBZjMjTVVpuOlfJXlsDJQbdefQP/9Wz3CyzSuZuU= -github.com/SigNoz/signoz-otel-collector v0.102.2/go.mod h1:ISAXYhZenojCWg6CdDJtPMpfS6Zwc08+uoxH25tc6Y0= github.com/SigNoz/signoz-otel-collector v0.102.10 h1:1zjU31OcRZL6fS0IIag8LA8bdhP4S28dzovDwuOg7Lg= github.com/SigNoz/signoz-otel-collector v0.102.10/go.mod h1:APoBVD4aRu9vIny1vdzZSi2wPY3elyjHA/I/rh1hKfs= github.com/SigNoz/zap_otlp v0.1.0 h1:T7rRcFN87GavY8lDGZj0Z3Xv6OhJA6Pj3I9dNPmqvRc= @@ -716,8 +714,6 @@ github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/srikanthccv/ClickHouse-go-mock v0.8.0 h1:DeeM8XLbTFl6sjYPPwazPEXx7kmRV8TgPFVkt1SqT0Y= -github.com/srikanthccv/ClickHouse-go-mock v0.8.0/go.mod h1:pgJm+apjvi7FHxEdgw1Bt4MRbUYpVxyhKQ/59Wkig24= github.com/srikanthccv/ClickHouse-go-mock v0.9.0 h1:XKr1Tb7GL1HlifKH874QGR3R6l0e6takXasROUiZawU= github.com/srikanthccv/ClickHouse-go-mock v0.9.0/go.mod h1:pgJm+apjvi7FHxEdgw1Bt4MRbUYpVxyhKQ/59Wkig24= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/pkg/query-service/tests/test-deploy/docker-compose.yaml b/pkg/query-service/tests/test-deploy/docker-compose.yaml index 05c3cddf15..1b4cdf6f0d 100644 --- a/pkg/query-service/tests/test-deploy/docker-compose.yaml +++ b/pkg/query-service/tests/test-deploy/docker-compose.yaml @@ -158,7 +158,7 @@ services: command: [ "-config=/root/config/prometheus.yml", - # "--prefer-delta=true" + "--use-logs-new-schema=true" ] # ports: # - "6060:6060" # pprof port @@ -192,7 +192,7 @@ services: <<: *db-depend otel-collector-migrator: - image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.102.2} + image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.102.10} container_name: otel-migrator command: - "--dsn=tcp://clickhouse:9000" @@ -205,7 +205,7 @@ services: # condition: service_healthy otel-collector: - image: signoz/signoz-otel-collector:0.102.2 + image: signoz/signoz-otel-collector:0.102.10 container_name: signoz-otel-collector command: [ diff --git a/pkg/query-service/tests/test-deploy/otel-collector-config.yaml b/pkg/query-service/tests/test-deploy/otel-collector-config.yaml index 589598c383..52f9e2be94 100644 --- a/pkg/query-service/tests/test-deploy/otel-collector-config.yaml +++ b/pkg/query-service/tests/test-deploy/otel-collector-config.yaml @@ -115,6 +115,7 @@ exporters: dsn: tcp://clickhouse:9000/signoz_logs docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER} timeout: 10s + use_new_schema: true # logging: {} service: From 1411ae41c357c42a918be81d7f86f7ff8ab62e56 Mon Sep 17 00:00:00 2001 From: Raj Kamal Singh <1133322+raj-k-singh@users.noreply.github.com> Date: Mon, 30 Sep 2024 23:46:34 +0530 Subject: [PATCH 13/20] =?UTF-8?q?Revert=20"Feat:=20use=20new=20logspipelin?= =?UTF-8?q?eprocessor=20for=20generating=20logs=20pipeline=20coll=E2=80=A6?= =?UTF-8?q?"=20(#6099)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit e4d1452f5ff63483b95c913cae37442b286e9aae. --- .../logparsingpipeline/collector_config.go | 67 ++++++++----------- .../collector_config_test.go | 4 +- .../app/logparsingpipeline/preview.go | 4 +- pkg/query-service/constants/constants.go | 4 +- 4 files changed, 33 insertions(+), 46 deletions(-) diff --git a/pkg/query-service/app/logparsingpipeline/collector_config.go b/pkg/query-service/app/logparsingpipeline/collector_config.go index 4b8da7b18a..49f697fbd3 100644 --- a/pkg/query-service/app/logparsingpipeline/collector_config.go +++ b/pkg/query-service/app/logparsingpipeline/collector_config.go @@ -19,28 +19,24 @@ var lockLogsPipelineSpec sync.RWMutex // check if the processors already exist // if yes then update the processor. // if something doesn't exists then remove it. -func updateProcessorConfigsInCollectorConf( - collectorConf map[string]interface{}, - signozPipelineProcessors map[string]interface{}, -) error { +func buildLogParsingProcessors(agentConf, parsingProcessors map[string]interface{}) error { agentProcessors := map[string]interface{}{} - if collectorConf["processors"] != nil { - agentProcessors = (collectorConf["processors"]).(map[string]interface{}) + if agentConf["processors"] != nil { + agentProcessors = (agentConf["processors"]).(map[string]interface{}) } exists := map[string]struct{}{} - for key, params := range signozPipelineProcessors { + for key, params := range parsingProcessors { agentProcessors[key] = params exists[key] = struct{}{} } - // remove the old unwanted pipeline processors + // remove the old unwanted processors for k := range agentProcessors { - _, isInDesiredPipelineProcs := exists[k] - if hasSignozPipelineProcessorPrefix(k) && !isInDesiredPipelineProcs { + if _, ok := exists[k]; !ok && strings.HasPrefix(k, constants.LogsPPLPfx) { delete(agentProcessors, k) } } - collectorConf["processors"] = agentProcessors + agentConf["processors"] = agentProcessors return nil } @@ -69,24 +65,21 @@ func getOtelPipelineFromConfig(config map[string]interface{}) (*otelPipeline, er return &p, nil } -func buildCollectorPipelineProcessorsList( - currentCollectorProcessors []string, - signozPipelineProcessorNames []string, -) ([]string, error) { +func buildLogsProcessors(current []string, logsParserPipeline []string) ([]string, error) { lockLogsPipelineSpec.Lock() defer lockLogsPipelineSpec.Unlock() exists := map[string]struct{}{} - for _, v := range signozPipelineProcessorNames { + for _, v := range logsParserPipeline { exists[v] = struct{}{} } // removed the old processors which are not used var pipeline []string - for _, procName := range currentCollectorProcessors { - _, isInDesiredPipelineProcs := exists[procName] - if isInDesiredPipelineProcs || !hasSignozPipelineProcessorPrefix(procName) { - pipeline = append(pipeline, procName) + for _, v := range current { + k := v + if _, ok := exists[k]; ok || !strings.HasPrefix(k, constants.LogsPPLPfx) { + pipeline = append(pipeline, v) } } @@ -103,7 +96,7 @@ func buildCollectorPipelineProcessorsList( existingVsSpec := map[int]int{} // go through plan and map its elements to current positions in effective config - for i, m := range signozPipelineProcessorNames { + for i, m := range logsParserPipeline { if loc, ok := existing[m]; ok { specVsExistingMap[i] = loc existingVsSpec[loc] = i @@ -113,11 +106,11 @@ func buildCollectorPipelineProcessorsList( lastMatched := 0 newPipeline := []string{} - for i := 0; i < len(signozPipelineProcessorNames); i++ { - m := signozPipelineProcessorNames[i] + for i := 0; i < len(logsParserPipeline); i++ { + m := logsParserPipeline[i] if loc, ok := specVsExistingMap[i]; ok { for j := lastMatched; j < loc; j++ { - if hasSignozPipelineProcessorPrefix(pipeline[j]) { + if strings.HasPrefix(pipeline[j], constants.LogsPPLPfx) { delete(specVsExistingMap, existingVsSpec[j]) } else { newPipeline = append(newPipeline, pipeline[j]) @@ -166,13 +159,13 @@ func GenerateCollectorConfigWithPipelines( config []byte, pipelines []Pipeline, ) ([]byte, *coreModel.ApiError) { - var collectorConf map[string]interface{} - err := yaml.Unmarshal([]byte(config), &collectorConf) + var c map[string]interface{} + err := yaml.Unmarshal([]byte(config), &c) if err != nil { return nil, coreModel.BadRequest(err) } - signozPipelineProcessors, signozPipelineProcNames, err := PreparePipelineProcessor(pipelines) + processors, procNames, err := PreparePipelineProcessor(pipelines) if err != nil { return nil, coreModel.BadRequest(errors.Wrap( err, "could not prepare otel collector processors for log pipelines", @@ -181,8 +174,8 @@ func GenerateCollectorConfigWithPipelines( // Escape any `$`s as `$$` in config generated for pipelines, to ensure any occurrences // like $data do not end up being treated as env vars when loading collector config. - for _, procName := range signozPipelineProcNames { - procConf := signozPipelineProcessors[procName] + for _, procName := range procNames { + procConf := processors[procName] serializedProcConf, err := yaml.Marshal(procConf) if err != nil { return nil, coreModel.InternalError(fmt.Errorf( @@ -201,14 +194,14 @@ func GenerateCollectorConfigWithPipelines( )) } - signozPipelineProcessors[procName] = escapedConf + processors[procName] = escapedConf } // Add processors to unmarshaled collector config `c` - updateProcessorConfigsInCollectorConf(collectorConf, signozPipelineProcessors) + buildLogParsingProcessors(c, processors) // build the new processor list in service.pipelines.logs - p, err := getOtelPipelineFromConfig(collectorConf) + p, err := getOtelPipelineFromConfig(c) if err != nil { return nil, coreModel.BadRequest(err) } @@ -218,20 +211,16 @@ func GenerateCollectorConfigWithPipelines( )) } - updatedProcessorList, _ := buildCollectorPipelineProcessorsList(p.Pipelines.Logs.Processors, signozPipelineProcNames) + updatedProcessorList, _ := buildLogsProcessors(p.Pipelines.Logs.Processors, procNames) p.Pipelines.Logs.Processors = updatedProcessorList // add the new processor to the data ( no checks required as the keys will exists) - collectorConf["service"].(map[string]interface{})["pipelines"].(map[string]interface{})["logs"] = p.Pipelines.Logs + c["service"].(map[string]interface{})["pipelines"].(map[string]interface{})["logs"] = p.Pipelines.Logs - updatedConf, err := yaml.Marshal(collectorConf) + updatedConf, err := yaml.Marshal(c) if err != nil { return nil, coreModel.BadRequest(err) } return updatedConf, nil } - -func hasSignozPipelineProcessorPrefix(procName string) bool { - return strings.HasPrefix(procName, constants.LogsPPLPfx) || strings.HasPrefix(procName, constants.OldLogsPPLPfx) -} diff --git a/pkg/query-service/app/logparsingpipeline/collector_config_test.go b/pkg/query-service/app/logparsingpipeline/collector_config_test.go index 2f2d898416..f5ba7a352b 100644 --- a/pkg/query-service/app/logparsingpipeline/collector_config_test.go +++ b/pkg/query-service/app/logparsingpipeline/collector_config_test.go @@ -94,7 +94,7 @@ var buildProcessorTestData = []struct { func TestBuildLogParsingProcessors(t *testing.T) { for _, test := range buildProcessorTestData { Convey(test.Name, t, func() { - err := updateProcessorConfigsInCollectorConf(test.agentConf, test.pipelineProcessor) + err := buildLogParsingProcessors(test.agentConf, test.pipelineProcessor) So(err, ShouldBeNil) So(test.agentConf, ShouldResemble, test.outputConf) }) @@ -200,7 +200,7 @@ var BuildLogsPipelineTestData = []struct { func TestBuildLogsPipeline(t *testing.T) { for _, test := range BuildLogsPipelineTestData { Convey(test.Name, t, func() { - v, err := buildCollectorPipelineProcessorsList(test.currentPipeline, test.logsPipeline) + v, err := buildLogsProcessors(test.currentPipeline, test.logsPipeline) So(err, ShouldBeNil) fmt.Println(test.Name, "\n", test.currentPipeline, "\n", v, "\n", test.expectedPipeline) So(v, ShouldResemble, test.expectedPipeline) diff --git a/pkg/query-service/app/logparsingpipeline/preview.go b/pkg/query-service/app/logparsingpipeline/preview.go index 548c1ee2f5..b37295eb96 100644 --- a/pkg/query-service/app/logparsingpipeline/preview.go +++ b/pkg/query-service/app/logparsingpipeline/preview.go @@ -7,7 +7,7 @@ import ( "time" _ "github.com/SigNoz/signoz-otel-collector/pkg/parser/grok" - "github.com/SigNoz/signoz-otel-collector/processor/signozlogspipelineprocessor" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/logstransformprocessor" "github.com/pkg/errors" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/plog" @@ -42,7 +42,7 @@ func SimulatePipelinesProcessing( simulatorInputPLogs := SignozLogsToPLogs(logs) processorFactories, err := processor.MakeFactoryMap( - signozlogspipelineprocessor.NewFactory(), + logstransformprocessor.NewFactory(), ) if err != nil { return nil, nil, model.InternalError(errors.Wrap( diff --git a/pkg/query-service/constants/constants.go b/pkg/query-service/constants/constants.go index 541d46d5ca..78ee31e1a1 100644 --- a/pkg/query-service/constants/constants.go +++ b/pkg/query-service/constants/constants.go @@ -341,9 +341,7 @@ var ReservedColumnTargetAliases = map[string]struct{}{ } // logsPPLPfx is a short constant for logsPipelinePrefix -// TODO(Raj): Remove old prefix after new processor based pipelines have been rolled out -const LogsPPLPfx = "signozlogspipeline/pipeline_" -const OldLogsPPLPfx = "logstransform/pipeline_" +const LogsPPLPfx = "logstransform/pipeline_" const IntegrationPipelineIdPrefix = "integration" From 266ed58908402553898cd7571c03d9810a02ba2a Mon Sep 17 00:00:00 2001 From: Shaheer Kochai Date: Tue, 1 Oct 2024 12:17:15 +0430 Subject: [PATCH 14/20] feat: add expand/collapse button to the top in trace details (#5980) * feat: add expand/collapse button to the top in trace details * fix: make the trace details collapsed sidebar match the design * fix: failing test by modifying the expand button class name --- frontend/src/container/AppLayout/index.tsx | 23 +++++++++---------- .../TraceDetail/SelectedSpanDetails/index.tsx | 23 +++++++++++-------- .../TraceDetail/TraceDetails.styles.scss | 6 +++++ frontend/src/container/TraceDetail/index.tsx | 20 +++++++++++----- frontend/src/container/TraceDetail/styles.ts | 2 ++ .../TraceDetail/__test__/TraceDetail.test.tsx | 4 +--- 6 files changed, 47 insertions(+), 31 deletions(-) diff --git a/frontend/src/container/AppLayout/index.tsx b/frontend/src/container/AppLayout/index.tsx index 4f5a3c43d7..9193decd6b 100644 --- a/frontend/src/container/AppLayout/index.tsx +++ b/frontend/src/container/AppLayout/index.tsx @@ -232,19 +232,16 @@ function AppLayout(props: AppLayoutProps): JSX.Element { const isDashboardListView = (): boolean => routeKey === 'ALL_DASHBOARD'; const isAlertHistory = (): boolean => routeKey === 'ALERT_HISTORY'; const isAlertOverview = (): boolean => routeKey === 'ALERT_OVERVIEW'; - const isDashboardView = (): boolean => { - /** - * need to match using regex here as the getRoute function will not work for - * routes with id - */ - const regex = /^\/dashboard\/[a-zA-Z0-9_-]+$/; - return regex.test(pathname); - }; + const isPathMatch = (regex: RegExp): boolean => regex.test(pathname); - const isDashboardWidgetView = (): boolean => { - const regex = /^\/dashboard\/[a-zA-Z0-9_-]+\/new$/; - return regex.test(pathname); - }; + const isDashboardView = (): boolean => + isPathMatch(/^\/dashboard\/[a-zA-Z0-9_-]+$/); + + const isDashboardWidgetView = (): boolean => + isPathMatch(/^\/dashboard\/[a-zA-Z0-9_-]+\/new$/); + + const isTraceDetailsView = (): boolean => + isPathMatch(/^\/trace\/[a-zA-Z0-9]+(\?.*)?$/); useEffect(() => { if (isDarkMode) { @@ -304,6 +301,8 @@ function AppLayout(props: AppLayoutProps): JSX.Element { isMessagingQueues() ? 0 : '0 1rem', + + ...(isTraceDetailsView() ? { marginRight: 0 } : {}), }} > {isToDisplayLayout && !renderFullScreen && } diff --git a/frontend/src/container/TraceDetail/SelectedSpanDetails/index.tsx b/frontend/src/container/TraceDetail/SelectedSpanDetails/index.tsx index 39e180ee12..d8eb1a6972 100644 --- a/frontend/src/container/TraceDetail/SelectedSpanDetails/index.tsx +++ b/frontend/src/container/TraceDetail/SelectedSpanDetails/index.tsx @@ -1,4 +1,4 @@ -import { Button, Modal, Tabs, Tooltip, Typography } from 'antd'; +import { Button, Modal, Row, Tabs, Tooltip, Typography } from 'antd'; import Editor from 'components/Editor'; import { StyledSpace } from 'components/Styled'; import { QueryParams } from 'constants/query'; @@ -6,7 +6,8 @@ import ROUTES from 'constants/routes'; import { useIsDarkMode } from 'hooks/useDarkMode'; import createQueryParams from 'lib/createQueryParams'; import history from 'lib/history'; -import { useState } from 'react'; +import { PanelRight } from 'lucide-react'; +import { Dispatch, SetStateAction, useState } from 'react'; import { useSelector } from 'react-redux'; import { useParams } from 'react-router-dom'; import { AppState } from 'store/reducers'; @@ -28,6 +29,7 @@ function SelectedSpanDetails(props: SelectedSpanDetailsProps): JSX.Element { firstSpanStartTime, traceStartTime = minTime, traceEndTime = maxTime, + setCollapsed, } = props; const { id: traceId } = useParams(); @@ -96,14 +98,14 @@ function SelectedSpanDetails(props: SelectedSpanDetailsProps): JSX.Element { styledclass={[styles.selectedSpanDetailsContainer, styles.overflow]} direction="vertical" > - - Details for selected Span - + + Details for selected Span +