Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: buyer org users metrics #128

Merged
merged 7 commits into from
Sep 25, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
65 changes: 41 additions & 24 deletions node/resolvers/Mutations/Users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import {
sendImpersonateB2BUserMetric,
sendImpersonateUserMetric,
} from '../../utils/metrics/impersonate'
import {
sendAddUserMetric,
sendRemoveUserMetric,
sendUpdateUserMetric,
} from '../../utils/metrics/user'

export const getUserRoleSlug: (
id: string,
Expand Down Expand Up @@ -406,18 +411,22 @@ const Users = {
}
}

const fields = {
email,
id,
userId,
}

return storefrontPermissionsClient
.deleteUser({
email,
id,
userId,
})
.deleteUser(fields)
.then((result: any) => {
events.sendEvent('', 'b2b-organizations-graphql.removeUser', {
id,
email,
})

sendRemoveUserMetric(logger, ctx.vtex.account, fields)

return result.data.deleteUser
})
.catch((error: any) => {
Expand Down Expand Up @@ -460,17 +469,21 @@ const Users = {
throw error
}

const fields = {
costId,
email,
id,
name,
orgId,
roleId,
userId,
}

return storefrontPermissionsClient
.addUser({
costId,
email,
id,
name,
orgId,
roleId,
userId,
})
.addUser(fields)
.then((result: any) => {
sendAddUserMetric(logger, ctx.vtex.account, fields)

return result.data.addUser
})
.catch((error: any) => {
Expand Down Expand Up @@ -538,18 +551,22 @@ const Users = {
})
}

const fields = {
clId,
costId,
email,
id,
name,
orgId,
roleId,
userId,
}

return storefrontPermissionsClient
.updateUser({
clId,
costId,
email,
id,
name,
orgId,
roleId,
userId,
})
.updateUser(fields)
.then((result: any) => {
sendUpdateUserMetric(logger, ctx.vtex.account, fields)

return result.data.updateUser
})
.catch((error: any) => {
Expand Down
33 changes: 6 additions & 27 deletions node/utils/metrics/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,13 @@ import axios from 'axios'

const ANALYTICS_URL = 'https://rc.vtex.com/api/analytics/schemaless-events'

type ImpersonateUserMetric = {
kind: 'impersonate-user-graphql-event'
description: 'Impersonate User Action - Graphql'
export interface Metric {
readonly account: string
readonly kind: string
readonly description: string
readonly name: 'b2b-suite-buyerorg-data'
}

type ImpersonateB2BUserMetric = {
kind: 'impersonate-b2b-user-graphql-event'
description: 'Impersonate B2B User Action - Graphql'
}
Rudge marked this conversation as resolved.
Show resolved Hide resolved

interface UpdateOrganizationMetric {
kind: 'update-organization-graphql-event'
description: 'Update Organization Action - Graphql'
}

export type Metric = {
name: 'b2b-suite-buyerorg-data'
account: string
} & (
| ImpersonateUserMetric
| ImpersonateB2BUserMetric
| UpdateOrganizationMetric
)

export const sendMetric = async (metric: Metric) => {
try {
await axios.post(ANALYTICS_URL, metric)
} catch (error) {
console.warn('Unable to log metrics', error)
}
await axios.post(ANALYTICS_URL, metric)
}
21 changes: 14 additions & 7 deletions node/utils/metrics/organization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ export interface UpdateOrganizationParams {
updatedProperties: Partial<Organization>
}

class UpdateOrganizationMetric implements Metric {
public readonly description = 'Update Organization Action - Graphql'
public readonly kind = 'update-organization-graphql-event'
public readonly account: string
public readonly fields: UpdateOrganizationFieldsMetric
public readonly name = 'b2b-suite-buyerorg-data'

constructor(account: string, fields: UpdateOrganizationFieldsMetric) {
this.account = account
this.fields = fields
}
}

const buildUpdateOrganizationMetric = (
account: string,
updatedProperties: string[]
Expand All @@ -25,13 +38,7 @@ const buildUpdateOrganizationMetric = (
update_details: { properties: updatedProperties },
}

return {
account,
description: 'Update Organization Action - Graphql',
fields: updateOrganizationFields,
kind: 'update-organization-graphql-event',
name: 'b2b-suite-buyerorg-data',
} as UpdateOrganization
return new UpdateOrganizationMetric(account, updateOrganizationFields)
}

const getFieldsNamesByFieldsUpdated = (
Expand Down
100 changes: 100 additions & 0 deletions node/utils/metrics/user.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { randEmail, randWord } from '@ngneat/falso'
import type { Logger } from '@vtex/api/lib/service/logger/logger'

import { sendMetric } from './metrics'
import {
sendAddUserMetric,
sendRemoveUserMetric,
sendUpdateUserMetric,
} from './user'

jest.mock('./metrics')
afterEach(() => {
jest.resetAllMocks()
})

describe('given an action for a user', () => {
describe('when add user', () => {
const logger = jest.fn() as unknown as Logger

const account = randWord()

const userArgs: Partial<UserArgs> = {
email: randEmail(),
id: randWord(),
userId: randWord(),
}

beforeEach(async () => {
await sendAddUserMetric(logger, account, userArgs)
})

it('should metrify the action', () => {
const metricParam = {
account,
description: 'Add User Action - Graphql',
fields: userArgs,
kind: 'add-user-graphql-event',
name: 'b2b-suite-buyerorg-data',
}

expect(sendMetric).toHaveBeenCalledWith(metricParam)
})
})

describe('when remove user', () => {
const logger = jest.fn() as unknown as Logger

const account = randWord()

const userArgs: Partial<UserArgs> = {
email: randEmail(),
id: randWord(),
userId: randWord(),
}

beforeEach(async () => {
await sendRemoveUserMetric(logger, account, userArgs)
})

it('should metrify the action', () => {
const metricParam = {
account,
description: 'Remove User Action - Graphql',
fields: userArgs,
kind: 'remove-user-graphql-event',
name: 'b2b-suite-buyerorg-data',
}

expect(sendMetric).toHaveBeenCalledWith(metricParam)
})
})

describe('when update user', () => {
const logger = jest.fn() as unknown as Logger

const account = randWord()

const userArgs: Partial<UserArgs> = {
email: randEmail(),
id: randWord(),
userId: randWord(),
}

beforeEach(async () => {
await sendUpdateUserMetric(logger, account, userArgs)
})

it('should metrify the action', () => {
const metricParam = {
account,
description: 'Update User Action - Graphql',
fields: userArgs,
kind: 'update-user-graphql-event',
name: 'b2b-suite-buyerorg-data',
}

expect(sendMetric).toHaveBeenCalledWith(metricParam)
})
})
})
87 changes: 87 additions & 0 deletions node/utils/metrics/user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import type { Logger } from '@vtex/api/lib/service/logger/logger'

import type { Metric } from './metrics'
import { sendMetric } from './metrics'

interface UserMetricType {
description: string
kind: string
}

const userMetricType = {
add: {
description: 'Add User Action - Graphql',
kind: 'add-user-graphql-event',
} as UserMetricType,
remove: {
description: 'Remove User Action - Graphql',
kind: 'remove-user-graphql-event',
} as UserMetricType,
update: {
description: 'Update User Action - Graphql',
kind: 'update-user-graphql-event',
} as UserMetricType,
}

class UserMetric implements Metric {
public readonly description: string
public readonly kind: string
public readonly account: string
public readonly fields: Partial<UserArgs>
public readonly name = 'b2b-suite-buyerorg-data'

constructor(
account: string,
{ kind, description }: UserMetricType,
fields: Partial<UserArgs>
) {
this.account = account
this.fields = fields
this.kind = kind
this.description = description
}
}

const sendUserMetric = async (logger: Logger, userMetric: UserMetric) => {
try {
await sendMetric(userMetric)
} catch (error) {
logger.error({
error,
message: `Error to send metrics from user action ${userMetric.kind}`,
})
}
}

export const sendRemoveUserMetric = async (
logger: Logger,
account: string,
userArgs: Partial<UserArgs>
) => {
await sendUserMetric(
logger,
new UserMetric(account, userMetricType.remove, userArgs)
)
}

export const sendAddUserMetric = async (
logger: Logger,
account: string,
userArgs: Partial<UserArgs>
) => {
await sendUserMetric(
logger,
new UserMetric(account, userMetricType.add, userArgs)
)
}

export const sendUpdateUserMetric = async (
logger: Logger,
account: string,
userArgs: Partial<UserArgs>
) => {
await sendUserMetric(
logger,
new UserMetric(account, userMetricType.update, userArgs)
)
}
Loading