From 081d081370ec3cc91973b6047b409c46d0396ff0 Mon Sep 17 00:00:00 2001 From: Peter Savchenko Date: Fri, 20 Dec 2024 18:24:50 +0300 Subject: [PATCH 1/3] sentry dsn guide --- src/assets/catalog/sentry.svg | 15 ++++ src/components/catalog/GuidePageHeader.vue | 16 +++- src/components/catalog/Item.vue | 16 +++- .../catalog/catchers/AddCatcher.vue | 36 ++++++++ .../catalog/catchers/dynamicLoadGuidePages.js | 1 + .../catalog/catchers/guides/sentry.vue | 88 +++++++++++++++++++ .../project/settings/Integrations.vue | 19 ++++ src/i18n/messages/en.json | 13 ++- src/i18n/messages/ru.json | 13 ++- src/utils.ts | 40 ++++++++- 10 files changed, 246 insertions(+), 11 deletions(-) create mode 100644 src/assets/catalog/sentry.svg create mode 100644 src/components/catalog/catchers/guides/sentry.vue diff --git a/src/assets/catalog/sentry.svg b/src/assets/catalog/sentry.svg new file mode 100644 index 000000000..addd0703c --- /dev/null +++ b/src/assets/catalog/sentry.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/components/catalog/GuidePageHeader.vue b/src/components/catalog/GuidePageHeader.vue index dcdfd9b84..fbdb4fadf 100644 --- a/src/components/catalog/GuidePageHeader.vue +++ b/src/components/catalog/GuidePageHeader.vue @@ -22,18 +22,22 @@
{{ description }}
- + {{ $t('components.catalog.viewSource') }} {{ $t('components.catalog.viewReadme') }} @@ -61,9 +65,13 @@ export default { type: String, required: true, }, + badge: { + type: String, + default: 'catcher', + }, githubLink: { type: String, - required: true, + default: '', }, description: { type: String, @@ -71,7 +79,7 @@ export default { }, readmeLink: { type: String, - required: true, + default: '', }, }, data() { diff --git a/src/components/catalog/Item.vue b/src/components/catalog/Item.vue index eab6d5903..a6edd95e6 100644 --- a/src/components/catalog/Item.vue +++ b/src/components/catalog/Item.vue @@ -1,5 +1,8 @@ @@ -243,6 +262,7 @@ export default { display: flex; flex-direction: column; justify-content: center; + margin-bottom: 100px; } &__catalog-header { @@ -283,5 +303,21 @@ export default { max-width: 245px; } } + + &__catalog-more { + background-color: var(--color-bg-main); + margin: 7.5px 7.5px 50px; + text-align: center; + padding: 18px 20px; + border-radius: 4px; + width: 100%; + cursor: pointer; + transition: all 0.2s ease; + + &:hover { + box-shadow: 0 6px 12px -5px rgba(0,0,0,0.15); + transform: translateY(-2px); + } + } } diff --git a/src/components/catalog/catchers/dynamicLoadGuidePages.js b/src/components/catalog/catchers/dynamicLoadGuidePages.js index f18ab0e5f..dac169f5b 100644 --- a/src/components/catalog/catchers/dynamicLoadGuidePages.js +++ b/src/components/catalog/catchers/dynamicLoadGuidePages.js @@ -11,6 +11,7 @@ export default { async beforeRouteEnter(to, _from, next) { const hasSeparatePage = [ 'javascript', + 'sentry', ]; let view = 'common'; diff --git a/src/components/catalog/catchers/guides/sentry.vue b/src/components/catalog/catchers/guides/sentry.vue new file mode 100644 index 000000000..339a545a7 --- /dev/null +++ b/src/components/catalog/catchers/guides/sentry.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/src/components/project/settings/Integrations.vue b/src/components/project/settings/Integrations.vue index f8109f023..a06d7a41e 100644 --- a/src/components/project/settings/Integrations.vue +++ b/src/components/project/settings/Integrations.vue @@ -24,6 +24,19 @@ +
+
+
+
+ {{ $t('projects.settings.integrations.sentryDSN') }} +
+
+ {{ $t('projects.settings.integrations.sentryDSNText') }} +
+
@@ -34,6 +47,7 @@ import TokenBlock from '../TokenBlock.vue'; import { ActionType } from '../../utils/ConfirmationWindow/types'; import { GENERATE_NEW_INTEGRATION_TOKEN } from '@/store/modules/projects/actionTypes'; import notifier from 'codex-notifier'; +import { getSentryDSN } from '../../../utils'; export default Vue.extend({ name: 'ProjectIntegrationsSettings', @@ -73,6 +87,11 @@ export default Vue.extend({ }); }, }, + computed: { + sentryDSN(): string { + return getSentryDSN(this.project.token); + }, + }, }); diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index 84d787e87..7f9bf1527 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -55,7 +55,10 @@ "step2": "Integrate a catcher", "whatToDo": "To start track events, you need to connect one of our Catchers", "whatIsCatcher": "Catcher is a small script that will catch errors in your application and send it to Hawk.", + "discoverMore": "Discover more integrations", "selectCatcherHeading": "Select a Catcher", + "migrationFromSentry": "Migration from Sentry", + "migrationFromSentryDescription": "Hawk can accept errors from Sentry SDK. You will need to change only one line.", "catchers": { "nodejs": "Track errors from the server application built on JS or TS", "php": "Can be connected as a standalone script or as a monolog provider", @@ -74,7 +77,11 @@ "getToken": "Get an Integration Token", "hereIsToken": "Here is your Integration token. You can also found it in the project settings later.", "followGuide": "Follow the Installation guide", - "readmeDisclaimer": "And the most actual guide at the README.md file in Catcher’s repo. As well as its source code." + "readmeDisclaimer": "And the most actual guide at the README.md file in Catcher’s repo. As well as its source code.", + "getDSN": "Get a DSN", + "hereIsDSN": "Here is your DSN. You can also found it in the project settings later.", + "useDSN": "Use DSN in Sentry SDK", + "useDSNText": "All Sentry SDK in one way or another support the `dsn` parameter. Pass the received DSN to the Sentry SDK options." } }, "forms": { @@ -129,7 +136,9 @@ "revokeConfirmation": { "title": "Revoke integration token?", "description": "After this action, Hawk will stop accepting events with the old integration token. You will need to replace it with a new one in your project." - } + }, + "sentryDSN": "Sentry DSN", + "sentryDSNText": "If you use Sentry SDK, you can use this DSN to send errors to Hawk." }, "notifications": { "title": "Notifications", diff --git a/src/i18n/messages/ru.json b/src/i18n/messages/ru.json index 252d834b5..bff116629 100644 --- a/src/i18n/messages/ru.json +++ b/src/i18n/messages/ru.json @@ -55,7 +55,10 @@ "step2": "Интегрировать Кэтчер", "whatToDo": "Чтобы начать принимать ивенты, вам нужно интегрировать один из Кэтчеров", "whatIsCatcher": "Кэтчер это небольшой скрипт, который будет отлавливать ошибки в вашем приложении и отправлять их в Хоука.", + "discoverMore": "Посмотреть все интеграции", "selectCatcherHeading": "Выберите Кэтчер", + "migrationFromSentry": "Миграция из Sentry", + "migrationFromSentryDescription": "Хоук может принимать ошибки из Sentry SDK. Просто поменяйте DSN.", "catchers": { "nodejs": "Прокачайте серверное приложение на JS или TS", "php": "Держит нагрузки, ловит ошибки, поддерживает Monolog", @@ -74,7 +77,11 @@ "getToken": "Получить Интеграционный Токен", "hereIsToken": "Это ваш Интеграционный Токен. Вы сможете найти его в настройках проекта.", "followGuide": "Следуйте Инструкции по установке", - "readmeDisclaimer": "А наиболее актуальная инструкция — в README.md Кэтчера. А также его исходный код." + "readmeDisclaimer": "А наиболее актуальная инструкция — в README.md Кэтчера. А также его исходный код.", + "getDSN": "Получить DSN", + "hereIsDSN": "Это ваш DSN, который вы можете использовать в Sentry SDK.", + "useDSN": "Поменяйте DSN в Sentry SDK", + "useDSNText": "Все Sentry SDK в том или ином виде поддерживают параметр `dsn`. Передайте полученный DSN в опции Sentry SDK." } }, "forms": { @@ -129,7 +136,9 @@ "revokeConfirmation": { "title": "Отозвать интеграционный токен?", "description": "После этого действия Хоук перестанет принимать ивенты со старым интеграционным токеном. Вам будет необходимо заменить его на новый в вашем проекте." - } + }, + "sentryDSN": "Sentry DSN", + "sentryDSNText": "Если вы используете Sentry SDK, вы можете использовать этот DSN для того, чтобы отправлять ошибки в Хоук." }, "notifications": { "title": "Уведомления", diff --git a/src/utils.ts b/src/utils.ts index 1885e90d4..9ee1178f7 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -182,7 +182,7 @@ export function repetitionAssembler(originalEvent: HawkEventPayload, repetition: return originalParam; } - + if (typeof repetitionParam === 'object' && typeof originalParam === 'object') { /** * If original event has null but repetition has some value, we need to return repetition value @@ -472,3 +472,41 @@ export function filterBeautifiedAddons(repetitions: HawkEventRepetition[]): void export function trim(value: string, maxLen: number): string { return value.length > maxLen ? value.substring(0, maxLen - 1) + '…' : value.substring(0, maxLen); } + + +/** + * Decode Hawk integration token + * + * @param token - stringified integration token + */ +function decodeIntegrationToken(token: string): DecodedIntegrationToken { + return JSON.parse(Buffer.from(token, 'base64').toString('utf-8')); +} + +/** + * Sentry DSN should follow this: + * const DSN_REGEX = /^(?:(\w+):)\/\/(?:(\w+)(?::(\w+)?)?@)([\w.-]+)(?::(\d+))?\/(.+)/; + * https://github.com/getsentry/sentry-javascript/blob/d773cb7324480ed3cffc14504f0e41951e344d19/packages/core/src/utils-hoist/dsn.ts#L7 + * + * So we can't use our integration token as is. + * Instead, we will concatinate integrationId and secret and remove hyphens from their uuids. + * + * @param token - stringified integration token + */ +function getHexIntegrationToken(token: string): string { + const { integrationId, secret } = decodeIntegrationToken(token); + + const removeHyphens = (str: string): string => str.replace(/-/g, ''); + + return `${removeHyphens(integrationId)}${removeHyphens(secret)}`; +} + + +/** + * Returns Sentry DSN from integration token + * + * @param token - stringified integration token + */ +export function getSentryDSN(token: string): string { + return `https://${getHexIntegrationToken(token)}@k1.hawk.so/0`; +} From d8648405e4e8cb5f1e320571d041c74a16249593 Mon Sep 17 00:00:00 2001 From: Peter Savchenko Date: Fri, 20 Dec 2024 18:28:06 +0300 Subject: [PATCH 2/3] Update utils.ts --- src/utils.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils.ts b/src/utils.ts index 9ee1178f7..fcc0cc5c1 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,6 +1,7 @@ import mergeWith from 'lodash.mergewith'; import cloneDeep from 'lodash.clonedeep'; import { HawkEventDailyInfo, HawkEventPayload, HawkEventRepetition } from './types/events'; +import { DecodedIntegrationToken } from '@hawk.so/types'; /** * Returns entity color from predefined list From a0f06950dafb8ae64a02428e837b58e526d429e2 Mon Sep 17 00:00:00 2001 From: Peter Savchenko Date: Fri, 20 Dec 2024 18:31:56 +0300 Subject: [PATCH 3/3] fix eslint --- src/components/catalog/catchers/guides/sentry.vue | 6 ------ src/components/project/settings/Integrations.vue | 10 +++++----- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/components/catalog/catchers/guides/sentry.vue b/src/components/catalog/catchers/guides/sentry.vue index 339a545a7..f99ff6b94 100644 --- a/src/components/catalog/catchers/guides/sentry.vue +++ b/src/components/catalog/catchers/guides/sentry.vue @@ -38,12 +38,9 @@