diff --git a/desktop/src/ui/types.ts b/desktop/src/ui/types.ts index 0888fdb1a0b..52388b81e09 100644 --- a/desktop/src/ui/types.ts +++ b/desktop/src/ui/types.ts @@ -8,9 +8,6 @@ export interface Config { ACCOUNTS_URL: string AI_URL?: string ANALYTICS_COLLECTOR_URL?: string - POSTHOG_API_KEY?: string - POSTHOG_HOST?: string - SENTRY_DSN?: string BRANDING_URL?: string CALENDAR_URL: string COLLABORATOR?: string diff --git a/dev/docker-compose.yaml b/dev/docker-compose.yaml index 42ba98f2dc1..330dc472f24 100644 --- a/dev/docker-compose.yaml +++ b/dev/docker-compose.yaml @@ -426,22 +426,23 @@ services: # - STATS_URL=http://huly.local:4900 # # - LOVE_ENDPOINT=http://huly.local:8096 # # - OPENAI_API_KEY=token - # analytics: - # image: hardcoreeng/analytics-collector - # extra_hosts: - # - 'huly.local:host-gateway' - # restart: unless-stopped - # ports: - # - 4017:4017 - # environment: - # - SECRET=secret - # - PORT=4017 - # - SERVICE_ID=analytics-collector-service - # - ACCOUNTS_URL=http://huly.local:3000 - # - STATS_URL=http://huly.local:4900 - # - POSTHOG_HOST=${POSTHOG_HOST} - # - POSTHOG_API_KEY=${POSTHOG_API_KEY} - # - MAX_PAYLOAD_SIZE=10mb + analytics: + image: hardcoreeng/analytics-collector + extra_hosts: + - 'huly.local:host-gateway' + restart: unless-stopped + ports: + - 4017:4017 + environment: + - SECRET=secret + - PORT=4017 + - SERVICE_ID=analytics-collector-service + - ACCOUNTS_URL=http://huly.local:3000 + - STATS_URL=http://huly.local:4900 + - OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318/v1/traces + # - POSTHOG_HOST=${POSTHOG_HOST} + # - POSTHOG_API_KEY=${POSTHOG_API_KEY} + # - MAX_PAYLOAD_SIZE=10mb export: image: hardcoreeng/export extra_hosts: diff --git a/dev/prod/package.json b/dev/prod/package.json index 094e4fd85dc..68b09abe548 100644 --- a/dev/prod/package.json +++ b/dev/prod/package.json @@ -282,8 +282,6 @@ "@hcengineering/ai-assistant": "^0.6.0", "@hcengineering/ai-assistant-assets": "^0.6.0", "@hcengineering/ai-assistant-resources": "^0.6.0", - "@sentry/svelte": "^9.22.0", - "posthog-js": "^1.246.0", "readable-stream": "^4.7.0", "svelte": "^4.2.20" } diff --git a/dev/prod/public/config.json b/dev/prod/public/config.json index 2c17577b866..ac85cae2d8d 100644 --- a/dev/prod/public/config.json +++ b/dev/prod/public/config.json @@ -29,5 +29,6 @@ "BACKUP_URL": "http://huly.local:4039/api/backup", "PULSE_URL": "ws://huly.local:8099/ws", "HULYLAKE_URL": "http://huly.local:8096", - "EXCLUDED_APPLICATIONS_FOR_ANONYMOUS": "[\"chunter\", \"notification\"]" + "EXCLUDED_APPLICATIONS_FOR_ANONYMOUS": "[\"chunter\", \"notification\"]", + "ANALYTICS_COLLECTOR_URL": "http://huly.local:4017" } diff --git a/dev/prod/src/platform.ts b/dev/prod/src/platform.ts index c8a9a099b89..75540ba2364 100644 --- a/dev/prod/src/platform.ts +++ b/dev/prod/src/platform.ts @@ -168,13 +168,10 @@ export interface Config { GITHUB_APP?: string GITHUB_CLIENTID?: string GITHUB_URL: string - SENTRY_DSN?: string LOVE_ENDPOINT?: string LIVEKIT_WS?: string SIGN_URL?: string PRINT_URL?: string - POSTHOG_API_KEY?: string - POSTHOG_HOST?: string ANALYTICS_COLLECTOR_URL?: string BRANDING_URL?: string TELEGRAM_BOT_URL?: string diff --git a/packages/analytics-providers/package.json b/packages/analytics-providers/package.json index b8e3ff3fb98..030455a073e 100644 --- a/packages/analytics-providers/package.json +++ b/packages/analytics-providers/package.json @@ -45,8 +45,6 @@ "@hcengineering/analytics-collector": "^0.6.0", "@hcengineering/presentation": "^0.6.3", "@hcengineering/core": "^0.6.32", - "posthog-js": "^1.246.0", - "@sentry/svelte": "^9.22.0", "ua-parser-js": "^2.0.4", "@hcengineering/ui": "^0.6.15" }, diff --git a/packages/analytics-providers/src/analyticsCollector.ts b/packages/analytics-providers/src/analyticsCollector.ts index 13f5061816e..1fb59e29848 100644 --- a/packages/analytics-providers/src/analyticsCollector.ts +++ b/packages/analytics-providers/src/analyticsCollector.ts @@ -14,11 +14,11 @@ // import { type AnalyticProvider } from '@hcengineering/analytics' -import presentation from '@hcengineering/presentation' -import { getMetadata } from '@hcengineering/platform' import { AnalyticEventType } from '@hcengineering/analytics-collector' -import { collectEventMetadata, triggerUrlChange } from './utils' +import { getMetadata } from '@hcengineering/platform' +import presentation from '@hcengineering/presentation' import { type QueuedEvent } from './types' +import { collectEventMetadata, triggerUrlChange } from './utils' export class AnalyticsCollectorProvider implements AnalyticProvider { private readonly collectIntervalMs = 5000 @@ -39,6 +39,7 @@ export class AnalyticsCollectorProvider implements AnalyticProvider { if (this.url !== undefined && this.url !== '' && this.url !== null) { this.initializeAnonymousId() this.startCollectionTimer() + this.registerExceptionHandlers() return true } return false @@ -48,6 +49,18 @@ export class AnalyticsCollectorProvider implements AnalyticProvider { this.anonymousId = this.generateAnonymousId() } + private registerExceptionHandlers (): void { + // Capture unhandled errors + window.addEventListener('error', (event) => { + this.handleError(event.error ?? new Error(event.message)) + }) + + // Capture unhandled promise rejections + window.addEventListener('unhandledrejection', (event) => { + this.handleError(event.reason instanceof Error ? event.reason : new Error(String(event.reason))) + }) + } + private generateAnonymousId (): string { return 'anon_' + Date.now() + '_' + Math.random().toString(36).substring(2, 15) } @@ -151,7 +164,13 @@ export class AnalyticsCollectorProvider implements AnalyticProvider { $is_identified: this.isAuthenticated } - const eventMetadata: Record = collectEventMetadata(baseProperties) + let eventMetadata: Record = {} + + try { + eventMetadata = collectEventMetadata(baseProperties) + } catch (err: any) { + // Ignore metadata collection errors + } if (eventType === AnalyticEventType.CustomEvent && (eventName !== '' || eventName != null)) { eventMetadata.event = eventName } @@ -271,16 +290,20 @@ export class AnalyticsCollectorProvider implements AnalyticProvider { handleError (error: Error): void { const currentId = this.isAuthenticated && (this.email != null || this.email !== '') ? this.email : this.anonymousId - this.addEvent( - AnalyticEventType.Error, - { + + const event: QueuedEvent = { + event: AnalyticEventType.Error, + properties: { error_message: error.message ?? 'Unknown error', error_type: error.name ?? 'Error', error_stack: error.stack ?? '' }, - '$exception', - currentId - ) + timestamp: Date.now(), + distinct_id: currentId ?? '' + } + this.events.push(event) + // We need to trigger sending immediately for errors + void this.sendEvents() } navigate (path: string): void { diff --git a/packages/analytics-providers/src/configure.ts b/packages/analytics-providers/src/configure.ts index b248e8887cd..0603c268dc3 100644 --- a/packages/analytics-providers/src/configure.ts +++ b/packages/analytics-providers/src/configure.ts @@ -15,22 +15,14 @@ import { type AnalyticProvider, Analytics } from '@hcengineering/analytics' import { AnalyticsCollectorProvider } from './analyticsCollector' -import { PosthogAnalyticProvider } from './posthog' -import { SentryAnalyticProvider } from './sentry' import { type AnalyticsConfig } from './types' export * from './analyticsCollector' -export * from './posthog' -export * from './sentry' export * from './utils' export * from './types' export function configureAnalyticsProviders (config: AnalyticsConfig): void { - const providers: AnalyticProvider[] = [ - new AnalyticsCollectorProvider(), - new SentryAnalyticProvider(), - new PosthogAnalyticProvider() - ] + const providers: AnalyticProvider[] = [new AnalyticsCollectorProvider()] for (const provider of providers) { Analytics.init(provider, config) diff --git a/packages/analytics-providers/src/index.ts b/packages/analytics-providers/src/index.ts index 31bc7c2f0dd..913a4af25f2 100644 --- a/packages/analytics-providers/src/index.ts +++ b/packages/analytics-providers/src/index.ts @@ -14,8 +14,6 @@ // export * from './analyticsCollector' -export * from './posthog' -export * from './sentry' export * from './utils' export * from './types' export * from './configure' diff --git a/packages/analytics-providers/src/posthog.ts b/packages/analytics-providers/src/posthog.ts deleted file mode 100644 index a15614f216e..00000000000 --- a/packages/analytics-providers/src/posthog.ts +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright © 2025 Hardcore Engineering Inc. -// -// Licensed under the Eclipse Public License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. You may -// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import { type AnalyticProvider } from '@hcengineering/analytics' -import posthog from 'posthog-js' - -export class PosthogAnalyticProvider implements AnalyticProvider { - init (config: Record): boolean { - if (config.POSTHOG_API_KEY !== undefined && config.POSTHOG_API_KEY !== '' && config.POSTHOG_HOST !== null) { - posthog.init(config.POSTHOG_API_KEY, { - api_host: config.POSTHOG_HOST, - autocapture: false, - capture_pageview: false, - capture_pageleave: false - }) - return true - } - return false - } - - setUser (email: string): void { - if (!posthog._isIdentified()) { - posthog.identify(email, { email }) - } - } - - setAlias (distinctId: string, alias: string): void { - posthog.alias(alias, distinctId) - } - - setTag (key: string, value: string | number): void { - posthog.setPersonProperties({ [key]: value }) - } - - setWorkspace (ws: string, guest: boolean): void { - const prop: string = guest ? 'visited-workspace' : 'workspace' - this.setTag(prop, ws) - if (!guest) posthog.group(prop, ws, { name: `${ws}` }) - } - - logout (): void { - posthog.reset(true) - } - - handleEvent (event: string, params: Record): void { - posthog.capture(event, params) - } - - handleError (error: Error): void { - posthog.capture(error.message) - } - - navigate (path: string): void { - posthog.capture('$pageview') - } -} diff --git a/packages/analytics-providers/src/sentry.ts b/packages/analytics-providers/src/sentry.ts deleted file mode 100644 index 22b7ba33216..00000000000 --- a/packages/analytics-providers/src/sentry.ts +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright © 2025 Hardcore Engineering Inc. -// -// Licensed under the Eclipse Public License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. You may -// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import { type AnalyticProvider } from '@hcengineering/analytics' -import * as Sentry from '@sentry/svelte' - -export class SentryAnalyticProvider implements AnalyticProvider { - navigate (path: string): void {} - init (config: Record): boolean { - if (config.SENTRY_DSN !== undefined && config.SENTRY_DSN !== '') { - Sentry.init({ - dsn: config.SENTRY_DSN, - integrations: [ - Sentry.browserTracingIntegration(), - Sentry.replayIntegration({ - maskAllText: false, - blockAllMedia: false - }) - ], - - // Set tracesSampleRate to 1.0 to capture 100% - // of transactions for performance monitoring. - // We recommend adjusting this value in production - tracesSampleRate: 1.0, - - tracePropagationTargets: [/^https:\/\/huly\.app/, /^https:\/\/app\.huly\.io/, /^https:\/\/account\.huly\.io/], - - replaysSessionSampleRate: 0.0, - replaysOnErrorSampleRate: 1.0 - }) - return true - } - return false - } - - setUser (email: string): void { - Sentry.setUser({ email }) - } - - setAlias (distinctId: string, alias: string): void {} - - logout (): void { - Sentry.setUser(null) - } - - setTag (key: string, value: string | number): void { - Sentry.setTag(key, value) - } - - setWorkspace (ws: string, guest: boolean): void { - const prop: string = guest ? 'visited-workspace' : 'workspace' - this.setTag(prop, ws) - } - - handleEvent (event: string): void { - // currently we don't need it, but maybe in future - // Sentry.captureMessage(event, 'log') - } - - handleError (error: Error): void { - Sentry.captureException(error) - } -} diff --git a/packages/analytics-providers/src/types.ts b/packages/analytics-providers/src/types.ts index e995b530681..7ca93ae0e31 100644 --- a/packages/analytics-providers/src/types.ts +++ b/packages/analytics-providers/src/types.ts @@ -17,7 +17,6 @@ import { type AnalyticEvent } from '@hcengineering/analytics-collector' export interface AnalyticsConfig { ANALYTICS_COLLECTOR_URL?: string - SENTRY_DSN?: string POSTHOG_API?: string POSTHOG_HOST?: string [key: string]: any diff --git a/packages/presentation/src/components/DocPopup.svelte b/packages/presentation/src/components/DocPopup.svelte index fe5519bc9c6..ec9a99d9824 100644 --- a/packages/presentation/src/components/DocPopup.svelte +++ b/packages/presentation/src/components/DocPopup.svelte @@ -37,6 +37,7 @@ import presentation from '..' import { ObjectCreate } from '../types' import { getClient } from '../utils' + import { Analytics } from '@hcengineering/analytics' export let _class: Ref> export let objects: Doc[] = [] @@ -184,7 +185,7 @@ presenter = result }) .catch((err) => { - console.error('Failed to find presenter for class ' + _class, err) + Analytics.handleError(err) }) } } diff --git a/packages/presentation/src/components/DrawingBoard.svelte b/packages/presentation/src/components/DrawingBoard.svelte index 2f426d2fc3c..fe64e017048 100644 --- a/packages/presentation/src/components/DrawingBoard.svelte +++ b/packages/presentation/src/components/DrawingBoard.svelte @@ -136,7 +136,6 @@ } catch (error: any) { commandProcessor.set([]) Analytics.handleError(error) - console.error('Failed to parse drawing content', error) } } else { commandProcessor.set([]) @@ -151,7 +150,6 @@ } createDrawing(data).catch((error) => { Analytics.handleError(error) - console.error('Failed to save drawing', error) }) } } diff --git a/packages/presentation/src/components/DrawingBoardToolbar.svelte b/packages/presentation/src/components/DrawingBoardToolbar.svelte index b4532cee655..93ce265c0a5 100644 --- a/packages/presentation/src/components/DrawingBoardToolbar.svelte +++ b/packages/presentation/src/components/DrawingBoardToolbar.svelte @@ -36,6 +36,7 @@ import DrawingBoardToolbarColorIcon from './DrawingBoardToolbarColorIcon.svelte' import DrawingBoardColorSelectorIcon from './DrawingBoardColorSelectorIcon.svelte' import { ColorsList, DrawingBoardColoringSetup } from '../drawingColors' + import { Analytics } from '@hcengineering/analytics' interface DrawingBoardToolbarEvents { undo: undefined @@ -130,9 +131,7 @@ break } default: { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const _exhaustive: never = id - console.error('Unknown command id', id) + Analytics.handleError(new Error(`Unknown command id '${id as any}'`)) } } }) diff --git a/packages/presentation/src/components/FilePreviewPopup.svelte b/packages/presentation/src/components/FilePreviewPopup.svelte index 478d3e7f2c5..4f8f96c05c9 100644 --- a/packages/presentation/src/components/FilePreviewPopup.svelte +++ b/packages/presentation/src/components/FilePreviewPopup.svelte @@ -73,7 +73,6 @@ .catch((error) => { drawingLoading = false Analytics.handleError(error) - console.error('Failed to load drawings for file', file, error) }) } } diff --git a/packages/presentation/src/components/markup/Mark.svelte b/packages/presentation/src/components/markup/Mark.svelte index 617be8e4dd2..ebb36448f95 100644 --- a/packages/presentation/src/components/markup/Mark.svelte +++ b/packages/presentation/src/components/markup/Mark.svelte @@ -18,6 +18,7 @@ import uiPlugin, { navigate, parseLocation } from '@hcengineering/ui' import presentation from '../../plugin' + import { Analytics } from '@hcengineering/analytics' export let mark: MarkupMark @@ -40,8 +41,8 @@ } } } - } catch (err) { - console.error('Failed to handle link', mark, err) + } catch (err: any) { + Analytics.handleError(err) } } diff --git a/plugins/activity-resources/package.json b/plugins/activity-resources/package.json index 2091b6f0702..a2364c385ee 100644 --- a/plugins/activity-resources/package.json +++ b/plugins/activity-resources/package.json @@ -37,6 +37,7 @@ "typescript": "^5.8.3" }, "dependencies": { + "@hcengineering/analytics": "^0.6.0", "@hcengineering/activity": "^0.6.0", "@hcengineering/card": "^0.6.0", "@hcengineering/contact": "^0.6.24", diff --git a/plugins/activity-resources/src/components/Activity.svelte b/plugins/activity-resources/src/components/Activity.svelte index 9ba9f3d299a..ae113b41e98 100644 --- a/plugins/activity-resources/src/components/Activity.svelte +++ b/plugins/activity-resources/src/components/Activity.svelte @@ -22,15 +22,16 @@ } from '@hcengineering/activity' import { Class, Doc, getCurrentAccount, Ref, SortingOrder } from '@hcengineering/core' import { createQuery, getClient } from '@hcengineering/presentation' - import { Grid, Section, Spinner, location, Lazy } from '@hcengineering/ui' + import { Grid, Lazy, location, Section, Spinner } from '@hcengineering/ui' import { onDestroy, onMount } from 'svelte' - import ActivityExtensionComponent from './ActivityExtension.svelte' - import ActivityFilter from './ActivityFilter.svelte' + import { editingMessageStore, messageInFocus } from '../activity' import { combineActivityMessages, sortActivityMessages } from '../activityMessagesUtils' - import { canGroupMessages, getMessageFromLoc, getSpace, getActivityNewestFirst } from '../utils' + import { canGroupMessages, getActivityNewestFirst, getMessageFromLoc, getSpace } from '../utils' import ActivityMessagePresenter from './activity-message/ActivityMessagePresenter.svelte' - import { editingMessageStore, messageInFocus } from '../activity' + import ActivityExtensionComponent from './ActivityExtension.svelte' + import ActivityFilter from './ActivityFilter.svelte' + import { Analytics } from '@hcengineering/analytics' export let object: WithReferences export let showCommenInput: boolean = true @@ -185,8 +186,8 @@ } clazz = hierarchy.getClass(clazz).extends } - } catch (e) { - console.error(e) + } catch (e: any) { + Analytics.handleError(e) return [] } return [] diff --git a/plugins/ai-assistant-resources/src/components/Configure.svelte b/plugins/ai-assistant-resources/src/components/Configure.svelte index db3075465c7..2c2ab3eb78f 100644 --- a/plugins/ai-assistant-resources/src/components/Configure.svelte +++ b/plugins/ai-assistant-resources/src/components/Configure.svelte @@ -25,6 +25,7 @@ import aiAssistant from '../plugin' import { buildSocialIdString, getCurrentAccount, SocialIdType, type PersonId } from '@hcengineering/core' import HulyAssistant from './icons/HulyAssistant.svelte' + import { Analytics } from '@hcengineering/analytics' export let integration: Integration | undefined = undefined @@ -51,9 +52,10 @@ isLoading = false dispatch('close') - } catch (err) { + } catch (err: any) { isLoading = false console.error('Failed to find/create huly assistant social id/integration:', err) + Analytics.handleError(err) } }) diff --git a/plugins/attachment-resources/src/components/LinkPreviewPresenter.svelte b/plugins/attachment-resources/src/components/LinkPreviewPresenter.svelte index 7f11cab575a..a3347653f5c 100644 --- a/plugins/attachment-resources/src/components/LinkPreviewPresenter.svelte +++ b/plugins/attachment-resources/src/components/LinkPreviewPresenter.svelte @@ -27,6 +27,7 @@ import { getImageDimensions } from '../utils' import LinkPreviewIcon from './LinkPreviewIcon.svelte' import LinkPreviewImage from './LinkPreviewImage.svelte' + import { Analytics } from '@hcengineering/analytics' export let attachment: WithLookup export let isOwn = false @@ -56,7 +57,7 @@ }) .catch((err) => { viewModel = undefined - console.error(err) + Analytics.handleError(err) }) }) diff --git a/plugins/bitrix-resources/src/components/FieldMappingPresenter.svelte b/plugins/bitrix-resources/src/components/FieldMappingPresenter.svelte index 3240822f756..0a0e48ae1bf 100644 --- a/plugins/bitrix-resources/src/components/FieldMappingPresenter.svelte +++ b/plugins/bitrix-resources/src/components/FieldMappingPresenter.svelte @@ -18,7 +18,7 @@ try { attr = getClient().getHierarchy().getAttribute(value.ofClass, value.attributeName) } catch (err: any) { - console.error(err) + Analytics.handleError(err) } diff --git a/plugins/calendar-resources/package.json b/plugins/calendar-resources/package.json index c46cc0c290c..01d142c3798 100644 --- a/plugins/calendar-resources/package.json +++ b/plugins/calendar-resources/package.json @@ -38,6 +38,7 @@ "svelte-eslint-parser": "^0.33.1" }, "dependencies": { + "@hcengineering/analytics": "^0.6.0", "@hcengineering/account-client": "^0.6.0", "@hcengineering/login": "^0.6.12", "@hcengineering/core": "^0.6.32", diff --git a/plugins/calendar-resources/src/components/CalDavAccess.svelte b/plugins/calendar-resources/src/components/CalDavAccess.svelte index 55b1b40856d..25db31a9fa1 100644 --- a/plugins/calendar-resources/src/components/CalDavAccess.svelte +++ b/plugins/calendar-resources/src/components/CalDavAccess.svelte @@ -13,6 +13,7 @@ import { getMetadata } from '@hcengineering/platform' import { getCurrentAccount, pickPrimarySocialId, SocialId, SocialIdType } from '@hcengineering/core' import { getAccountClient } from '../utils' + import { Analytics } from '@hcengineering/analytics' const workspaceUuid = getCurrentWorkspaceUuid() @@ -89,7 +90,7 @@ selectedSocialId = socialId accessEnabled = integrationWs != null && integrationGlobal != null } catch (err: any) { - console.error('Failed to load CalDAV intergrations', err) + Analytics.handleError(err) error = `${err.message ?? 'Unable to load CalDAV intergrations'}` } finally { loading = false @@ -151,7 +152,7 @@ dispatch('close', true) } catch (err: any) { error = `${err.message ?? 'Unable to save CalDAV intergration'}` - console.error('Failed to save CalDAV integration', err) + Analytics.handleError(err) } finally { loading = false } diff --git a/plugins/calendar-resources/src/components/ScheduleEditor.svelte b/plugins/calendar-resources/src/components/ScheduleEditor.svelte index d06644bb26e..44e43ac6125 100644 --- a/plugins/calendar-resources/src/components/ScheduleEditor.svelte +++ b/plugins/calendar-resources/src/components/ScheduleEditor.svelte @@ -55,6 +55,7 @@ import calendar from '../plugin' import CalendarSelector from './CalendarSelector.svelte' import TimeZoneSelector from './TimeZoneSelector.svelte' + import { Analytics } from '@hcengineering/analytics' export let schedule: Schedule | undefined @@ -99,8 +100,8 @@ .then((text) => { durationVariants.push({ msec, text }) }) - .catch((err) => { - console.error(err) + .catch((err: any) => { + Analytics.handleError(err) }) }) } @@ -112,8 +113,8 @@ .then((text) => { intervalVariants.push({ msec, text }) }) - .catch((err) => { - console.error(err) + .catch((err: any) => { + Analytics.handleError(err) }) }) } @@ -170,8 +171,8 @@ .then((res) => { formattedMeetingDuration = res }) - .catch((err) => { - console.error(err) + .catch((err: any) => { + Analytics.handleError(err) }) } @@ -180,8 +181,8 @@ .then((res) => { formattedMeetingInterval = res }) - .catch((err) => { - console.error(err) + .catch((err: any) => { + Analytics.handleError(err) }) } diff --git a/plugins/card-resources/src/components/NewCardForm.svelte b/plugins/card-resources/src/components/NewCardForm.svelte index 51efcd5940e..9cc1b893f11 100644 --- a/plugins/card-resources/src/components/NewCardForm.svelte +++ b/plugins/card-resources/src/components/NewCardForm.svelte @@ -33,6 +33,7 @@ import chat from '@hcengineering/chat' import EditorActions from './EditorActions.svelte' + import { Analytics } from '@hcengineering/analytics' const dispatch = createEventDispatcher() const communicationClient = getCommunicationClient() @@ -90,7 +91,7 @@ const createdCard = await createCard(type, space, data, cardDescription, _id) if (isThread) { if (createdCard == null) { - console.error('Failed to create thread card') + Analytics.handleError(new Error('Failed to create thread card')) return } const blobs: (BlobParams & { mimeType: string })[] = descriptionBox.getAttachments().map((attachment) => ({ diff --git a/plugins/card-resources/src/components/settings/ManageMasterTagsContent.svelte b/plugins/card-resources/src/components/settings/ManageMasterTagsContent.svelte index 188fb656fe1..6385afa55e4 100644 --- a/plugins/card-resources/src/components/settings/ManageMasterTagsContent.svelte +++ b/plugins/card-resources/src/components/settings/ManageMasterTagsContent.svelte @@ -13,26 +13,27 @@ // limitations under the License. -->