Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions dev/prod/src/analytics/analyticsCollector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { AnalyticEvent, AnalyticEventType } from '@hcengineering/analytics-colle
import { Config } from '../platform'

export class AnalyticsCollectorProvider implements AnalyticProvider {
private readonly collectIntervalMs = 1000
private readonly collectIntervalMs = 5000

private readonly events: AnalyticEvent[] = []

Expand Down Expand Up @@ -85,10 +85,10 @@ export class AnalyticsCollectorProvider implements AnalyticProvider {
this.setTag('workspace', ws)
}

handleEvent(event: string): void {
handleEvent(event: string, params: Record<string, string>): void {
this.events.push({
event: AnalyticEventType.CustomEvent,
params: { event },
params: { ...params, event },
timestamp: Date.now()
})
}
Expand All @@ -108,4 +108,6 @@ export class AnalyticsCollectorProvider implements AnalyticProvider {
timestamp: Date.now()
})
}

logout(): void {}
}
7 changes: 5 additions & 2 deletions dev/prod/src/analytics/posthog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ export class PosthogAnalyticProvider implements AnalyticProvider {
name: `${ws}`
})
}
handleEvent(event: string): void {
posthog.capture(event)
logout(): void {
posthog.reset()
}
handleEvent(event: string, params: Record<string, any>): void {
posthog.capture(event, params)
}
handleError(error: Error): void {
posthog.capture(error.message)
Expand Down
3 changes: 3 additions & 0 deletions dev/prod/src/analytics/sentry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ export class SentryAnalyticProvider implements AnalyticProvider {
setUser(email: string): void {
Sentry.setUser({ email })
}
logout(): void {
Sentry.setUser(null)
}
setTag(key: string, value: string): void {
Sentry.setTag(key, value)
}
Expand Down
3 changes: 2 additions & 1 deletion models/recruit/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import view, { createAction, showColorsViewOption, actionTemplates as viewTempla
import workbench, { createNavigateAction, type Application } from '@hcengineering/model-workbench'
import notification from '@hcengineering/notification'
import { type IntlString } from '@hcengineering/platform'
import { recruitId, type Applicant } from '@hcengineering/recruit'
import { recruitId, type Applicant, RecruitEvents } from '@hcengineering/recruit'
import setting from '@hcengineering/setting'
import { type KeyBinding, type ViewOptionModel, type ViewOptionsModel } from '@hcengineering/view'

Expand Down Expand Up @@ -183,6 +183,7 @@ export function createModel (builder: Builder): void {
_class: recruit.mixin.Candidate,
icon: contact.icon.Person,
label: recruit.string.Talents,
createEvent: RecruitEvents.PlusTalentButtonClicked,
createLabel: recruit.string.TalentCreateLabel,
createComponent: recruit.component.CreateCandidate,
createComponentProps: { shouldSaveDraft: false }
Expand Down
13 changes: 9 additions & 4 deletions models/tracker/src/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import task from '@hcengineering/model-task'
import view, { actionTemplates, createAction } from '@hcengineering/model-view'
import workbench, { createNavigateAction } from '@hcengineering/model-workbench'
import { type IntlString } from '@hcengineering/platform'
import { trackerId } from '@hcengineering/tracker'
import { TrackerEvents, trackerId } from '@hcengineering/tracker'
import { type KeyBinding, type ViewAction } from '@hcengineering/view'
import tracker from './plugin'

Expand Down Expand Up @@ -124,6 +124,7 @@ export function createActions (builder: Builder, issuesId: string, componentsId:
mode: ['context', 'browser'],
group: 'edit'
},
analyticsEvent: TrackerEvents.ProjectArchived,
override: [view.action.Archive, view.action.Delete]
},
tracker.action.DeleteProject
Expand All @@ -145,6 +146,7 @@ export function createActions (builder: Builder, issuesId: string, componentsId:
mode: ['context', 'browser'],
group: 'edit'
},
analyticsEvent: TrackerEvents.ProjectDeleted,
override: [view.action.Archive, view.action.Delete]
},
tracker.action.DeleteProjectClean
Expand Down Expand Up @@ -187,7 +189,8 @@ export function createActions (builder: Builder, issuesId: string, componentsId:
group: 'remove'
},
visibilityTester: view.function.CanDeleteObject,
override: [view.action.Delete]
override: [view.action.Delete],
analyticsEvent: TrackerEvents.IssueDeleted
},
tracker.action.DeleteIssue
)
Expand Down Expand Up @@ -218,7 +221,8 @@ export function createActions (builder: Builder, issuesId: string, componentsId:
application: tracker.app.Tracker,
group: 'create'
},
override: [tracker.action.NewIssueGlobal]
override: [tracker.action.NewIssueGlobal],
analyticsEvent: TrackerEvents.NewIssueBindingCalled
},
tracker.action.NewIssue
)
Expand All @@ -239,7 +243,8 @@ export function createActions (builder: Builder, issuesId: string, componentsId:
context: {
mode: [],
group: 'create'
}
},
analyticsEvent: TrackerEvents.IssueCreateFromGlobalActionCalled
},
tracker.action.NewIssueGlobal
)
Expand Down
1 change: 1 addition & 0 deletions packages/analytics-service/src/sentry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,5 @@ export class SentryAnalyticProvider implements AnalyticProvider {
}

navigate (path: string): void {}
logout (): void {}
}
13 changes: 10 additions & 3 deletions packages/analytics/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ export interface AnalyticProvider {
setUser: (email: string) => void
setTag: (key: string, value: string) => void
setWorkspace: (ws: string) => void
handleEvent: (event: string) => void
handleEvent: (event: string, params: Record<string, string>) => void
handleError: (error: Error) => void
navigate: (path: string) => void
logout: () => void
}

export const Analytics = {
Expand Down Expand Up @@ -41,9 +42,9 @@ export const Analytics = {
})
},

handleEvent (event: string): void {
handleEvent (event: string, params: Record<string, any> = {}): void {
providers.forEach((provider) => {
provider.handleEvent(event)
provider.handleEvent(event, params)
})
},

Expand All @@ -57,6 +58,12 @@ export const Analytics = {
providers.forEach((provider) => {
provider.navigate(path)
})
},

logout (): void {
providers.forEach((provider) => {
provider.logout()
})
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
},
"dependencies": {
"@hcengineering/platform": "^0.6.11",
"@hcengineering/analytics": "^0.6.0",
"fast-equals": "^5.0.1"
},
"repository": "https://github.com/hcengineering/platform",
Expand Down
24 changes: 23 additions & 1 deletion packages/core/src/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type {
WithLookup
} from './storage'
import { DocumentClassQuery, Tx, TxApplyResult, TxCUD, TxFactory, TxProcessor } from './tx'
import { Analytics } from '@hcengineering/analytics'

/**
* @public
Expand Down Expand Up @@ -541,14 +542,22 @@ export async function updateAttribute (
_class: Ref<Class<Doc>>,
attribute: { key: string, attr: AnyAttribute },
value: any,
saveModified: boolean = false
saveModified: boolean = false,
analyticsProps: Record<string, any> = {}
): Promise<void> {
const doc = object
const attributeKey = attribute.key
if ((doc as any)[attributeKey] === value) return
const modifiedOn = saveModified ? doc.modifiedOn : Date.now()
const modifiedBy = attribute.key === 'modifiedBy' ? value : saveModified ? doc.modifiedBy : undefined
const attr = attribute.attr

const baseAnalyticsProps = {
objectClass: _class,
objectId: object._id,
attribute: attributeKey,
...analyticsProps
}
if (client.getHierarchy().isMixin(attr.attributeOf)) {
await client.updateMixin(
doc._id,
Expand All @@ -559,6 +568,7 @@ export async function updateAttribute (
modifiedOn,
modifiedBy
)
Analytics.handleEvent('ChangeAttribute', { ...baseAnalyticsProps, value })
} else {
if (client.getHierarchy().isDerived(attribute.attr.type._class, core.class.ArrOf)) {
const oldValue: any[] = (object as any)[attributeKey] ?? []
Expand All @@ -568,6 +578,10 @@ export async function updateAttribute (
const toPush = val.filter((it) => !oldValue.includes(it))
if (toPull.length > 0) {
await client.update(object, { $pull: { [attributeKey]: { $in: toPull } } }, false, modifiedOn, modifiedBy)
Analytics.handleEvent('RemoveCollectionItems', {
...baseAnalyticsProps,
removed: toPull
})
}
if (toPush.length > 0) {
await client.update(
Expand All @@ -577,9 +591,17 @@ export async function updateAttribute (
modifiedOn,
modifiedBy
)
Analytics.handleEvent('AddCollectionItems', {
...baseAnalyticsProps,
added: toPush
})
}
} else {
await client.update(object, { [attributeKey]: value }, false, modifiedOn, modifiedBy)
Analytics.handleEvent('SetCollectionItems', {
...baseAnalyticsProps,
value
})
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import { createEventDispatcher } from 'svelte'
import { getAttribute, KeyedAttribute, updateAttribute } from '../attributes'
import { getAttributeEditor, getClient } from '../utils'
import { Analytics } from '@hcengineering/analytics'

export let key: KeyedAttribute | string
export let object: Doc | Record<string, any>
Expand All @@ -29,6 +30,7 @@
export let showHeader: boolean = true
export let readonly = false
export let draft = false
export let identifier: string | undefined = undefined

export let kind: ButtonKind = 'link'
export let size: ButtonSize = 'large'
Expand All @@ -48,7 +50,9 @@
if (draft) {
;(doc as any)[attributeKey] = value
} else {
void updateAttribute(client, doc, doc._class, { key: attributeKey, attr: attribute }, value)
void updateAttribute(client, doc, doc._class, { key: attributeKey, attr: attribute }, value, false, {
objectId: identifier ?? doc._id
})
}
}

Expand Down
7 changes: 7 additions & 0 deletions packages/ui/src/components/Button.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import Icon from './Icon.svelte'
import Label from './Label.svelte'
import Spinner from './Spinner.svelte'
import { Analytics } from '@hcengineering/analytics'

export let label: IntlString | undefined = undefined
export let labelParams: Record<string, any> = {}
Expand Down Expand Up @@ -68,6 +69,7 @@
export let adaptiveShrink: WidthType | null = null
export let gap: 'medium' | 'large' = 'medium'
export let stopPropagation: boolean = true
export let event: string | undefined = undefined

$: iconSize = iconProps?.size !== undefined ? iconProps.size : size && size === 'inline' ? 'inline' : 'small'
$: iconRightSize = iconRightProps?.size !== undefined ? iconRightProps.size : 'x-small'
Expand Down Expand Up @@ -149,6 +151,11 @@
{title}
type={kind === 'primary' ? 'submit' : 'button'}
on:click={preventHandler}
on:click={() => {
if (event) {
Analytics.handleEvent(event)
}
}}
on:click
on:focus
on:blur
Expand Down
1 change: 1 addition & 0 deletions plugins/attachment-resources/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"typescript": "^5.3.3"
},
"dependencies": {
"@hcengineering/analytics": "^0.6.0",
"@hcengineering/activity": "^0.6.0",
"@hcengineering/attachment": "^0.6.14",
"@hcengineering/contact": "^0.6.24",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// limitations under the License.
-->
<script lang="ts">
import attachment, { Attachment, BlobMetadata } from '@hcengineering/attachment'
import attachment, { Attachment, BlobMetadata, AttachmentsEvents } from '@hcengineering/attachment'
import contact from '@hcengineering/contact'
import { Account, Doc, Ref, generateId, type Blob } from '@hcengineering/core'
import { IntlString, getResource, setPlatformStatus, unknownError } from '@hcengineering/platform'
Expand All @@ -37,11 +37,13 @@
import { AnySvelteComponent, getEventPositionElement, getPopupPositionElement, navigate } from '@hcengineering/ui'
import { uploadFiles } from '@hcengineering/uploader'
import view from '@hcengineering/view'
import { getCollaborationUser, getObjectLinkFragment } from '@hcengineering/view-resources'
import { getCollaborationUser, getObjectId, getObjectLinkFragment } from '@hcengineering/view-resources'
import { Analytics } from '@hcengineering/analytics'

import AttachmentsGrid from './AttachmentsGrid.svelte'

export let object: Doc
export let identifier: string | undefined = undefined
export let key: KeyedAttribute
export let placeholder: IntlString
export let focusIndex = -1
Expand Down Expand Up @@ -207,6 +209,13 @@
attachmentDoc,
attachmentDoc._id
)

const id = identifier ?? (await getObjectId(object, client.getHierarchy()))
Analytics.handleEvent(AttachmentsEvents.FilesAttached, {
objectId: id,
objectClass: object._class,
type: file.type
})
} catch (err: any) {
await setPlatformStatus(unknownError(err))
}
Expand Down
3 changes: 3 additions & 0 deletions plugins/attachment/src/analytics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export enum AttachmentsEvents {
FilesAttached = 'attachment.FilesAttached'
}
2 changes: 2 additions & 0 deletions plugins/attachment/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { IntlString, plugin, Resource } from '@hcengineering/platform'
import type { Preference } from '@hcengineering/preference'
import { AnyComponent } from '@hcengineering/ui'

export * from './analytics'

/**
* @public
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
import activity, { ActivityMessage } from '@hcengineering/activity'
import { Analytics } from '@hcengineering/analytics'
import { AttachmentRefInput } from '@hcengineering/attachment-resources'
import chunter, { ChatMessage, ThreadMessage } from '@hcengineering/chunter'
import chunter, { ChatMessage, ChunterEvents, ThreadMessage } from '@hcengineering/chunter'
import { Class, Doc, generateId, Ref, type CommitResult } from '@hcengineering/core'
import { createQuery, DraftController, draftsStore, getClient, isSpace } from '@hcengineering/presentation'
import { EmptyMarkup } from '@hcengineering/text'
import { createEventDispatcher } from 'svelte'
import { getObjectId } from '@hcengineering/view-resources'
import { getChannelSpace } from '../../utils'
Expand Down Expand Up @@ -108,7 +109,11 @@
const res = await createMessage(event, _id, `chunter.create.${_class} ${object._class}`)
console.log(`create.${_class} measure`, res.serverTime, res.time)
const objectId = await getObjectId(object, client.getHierarchy())
Analytics.handleEvent(ChunterEvents.MessageCreated, { ok: res.result, objectId, objectClass: object._class })
} catch (err: any) {
const objectId = await getObjectId(object, client.getHierarchy())
Analytics.handleEvent(ChunterEvents.MessageCreated, { ok: false, objectId, objectClass: object._class })
Analytics.handleError(err)
console.error(err)
}
Expand All @@ -117,7 +122,11 @@
async function handleEdit (event: CustomEvent): Promise<void> {
try {
await editMessage(event)
const objectId = await getObjectId(object, client.getHierarchy())
Analytics.handleEvent(ChunterEvents.MessageEdited, { ok: true, objectId, objectClass: object._class })
} catch (err: any) {
const objectId = await getObjectId(object, client.getHierarchy())
Analytics.handleEvent(ChunterEvents.MessageEdited, { ok: false, objectId, objectClass: object._class })
Analytics.handleError(err)
console.error(err)
}
Expand Down
Loading