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

chore: telemetry localization #6075

Merged
merged 1 commit into from
Apr 29, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/email-nodemailer/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const nodemailerAdapter = async (
const { defaultFromAddress, defaultFromName, transport } = await buildEmail(args)

const adapter: NodemailerAdapter = () => ({
name: 'nodemailer',
defaultFromAddress,
defaultFromName,
sendEmail: async (message) => {
Expand Down
4 changes: 1 addition & 3 deletions packages/payload/src/collections/config/sanitize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { isPlainObject } from '../../utilities/isPlainObject.js'
import baseVersionFields from '../../versions/baseFields.js'
import { authDefaults, defaults } from './defaults.js'

const sanitizeCollection = (
export const sanitizeCollection = (
config: Config,
collection: CollectionConfig,
): SanitizedCollectionConfig => {
Expand Down Expand Up @@ -159,5 +159,3 @@ const sanitizeCollection = (

return sanitized as SanitizedCollectionConfig
}

export default sanitizeCollection
1 change: 1 addition & 0 deletions packages/payload/src/collections/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ const collectionSchema = joi.object().keys({
}),
upload: joi.alternatives().try(
joi.object({
adapter: joi.string(),
adminThumbnail: joi.alternatives().try(joi.string(), componentSchema),
crop: joi.bool(),
disableLocalStorage: joi.bool(),
Expand Down
8 changes: 7 additions & 1 deletion packages/payload/src/config/sanitize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type {
} from './types.js'

import { defaultUserCollection } from '../auth/defaultUser.js'
import sanitizeCollection from '../collections/config/sanitize.js'
import { sanitizeCollection } from '../collections/config/sanitize.js'
import { migrationsCollection } from '../database/migrations/migrationsCollection.js'
import { InvalidConfiguration } from '../errors/index.js'
import sanitizeGlobals from '../globals/config/sanitize.js'
Expand Down Expand Up @@ -110,5 +110,11 @@ export const sanitizeConfig = (incomingConfig: Config): SanitizedConfig => {
config.csrf.push(config.serverURL)
}

// Get deduped list of upload adapters
if (!config.upload) config.upload = { adapters: [] }
config.upload.adapters = Array.from(
new Set(config.collections.map((c) => c.upload?.adapter).filter(Boolean)),
)

return config as SanitizedConfig
}
8 changes: 7 additions & 1 deletion packages/payload/src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ export type Config = {

export type SanitizedConfig = Omit<
DeepRequired<Config>,
'collections' | 'endpoint' | 'globals' | 'i18n' | 'localization'
'collections' | 'endpoint' | 'globals' | 'i18n' | 'localization' | 'upload'
> & {
collections: SanitizedCollectionConfig[]
endpoints: Endpoint[]
Expand All @@ -652,6 +652,12 @@ export type SanitizedConfig = Omit<
configDir: string
rawConfig: string
}
upload: ExpressFileUploadOptions & {
/**
* Deduped list of adapters used in the project
*/
adapters: string[]
}
}

export type EditConfig =
Expand Down
1 change: 1 addition & 0 deletions packages/payload/src/email/consoleEmailAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { emailDefaults } from './defaults.js'
import { getStringifiedToAddress } from './getStringifiedToAddress.js'

export const consoleEmailAdapter: EmailAdapter<void> = ({ payload }) => ({
name: 'console',
defaultFromAddress: emailDefaults.defaultFromAddress,
defaultFromName: emailDefaults.defaultFromName,
sendEmail: async (message) => {
Expand Down
1 change: 1 addition & 0 deletions packages/payload/src/email/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ export type InitializedEmailAdapter<TSendEmailResponse = unknown> = ReturnType<
export type EmailAdapter<TSendEmailResponse = unknown> = ({ payload }: { payload: Payload }) => {
defaultFromAddress: string
defaultFromName: string
name: string
sendEmail: (message: SendEmailOptions) => Promise<TSendEmailResponse>
}
4 changes: 4 additions & 0 deletions packages/payload/src/uploads/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ export type ImageSize = Omit<ResizeOptions, 'withoutEnlargement'> & {
export type GetAdminThumbnail = (args: { doc: Record<string, unknown> }) => false | null | string

export type UploadConfig = {
/**
* The adapter to use for uploads.
*/
adapter?: string
/**
* Represents an admin thumbnail, which can be either a React component or a string.
* - If a string, it should be one of the image size names.
Expand Down
61 changes: 46 additions & 15 deletions packages/payload/src/utilities/telemetry/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,18 @@ const Conf = (ConfImport.default || ConfImport) as unknown as typeof ConfImport.

export type BaseEvent = {
ciName: null | string
dbAdapter: string
emailAdapter: null | string
envID: string
isCI: boolean
locales: string[]
localizationDefaultLocale: null | string
localizationEnabled: boolean
nodeEnv: string
nodeVersion: string
payloadPackages: Record<string, string>
payloadVersion: string
projectID: string
uploadAdapters: string[]
}

type PackageJSON = {
Expand All @@ -42,7 +47,7 @@ let baseEvent: BaseEvent | null = null

export const sendEvent = async ({ event, payload }: Args): Promise<void> => {
try {
const packageJSON = await getPackageJSON()
const { packageJSON, packageJSONPath } = await getPackageJSON()

// Only generate the base event once
if (!baseEvent) {
Expand All @@ -52,15 +57,18 @@ export const sendEvent = async ({ event, payload }: Args): Promise<void> => {
isCI: ciInfo.isCI,
nodeEnv: process.env.NODE_ENV || 'development',
nodeVersion: process.version,
payloadPackages: getPayloadPackages(packageJSON),
payloadVersion: getPayloadVersion(packageJSON),
projectID: getProjectID(payload, packageJSON),
...getLocalizationInfo(payload),
dbAdapter: payload.db.name,
emailAdapter: payload.email?.name || null,
uploadAdapters: payload.config.upload.adapters,
}
}

if (process.env.PAYLOAD_TELEMETRY_DEBUG) {
payload.logger.info({
event: { ...baseEvent, ...event },
event: { ...baseEvent, ...event, packageJSONPath },
msg: 'Telemetry Event',
})
return
Expand Down Expand Up @@ -120,18 +128,23 @@ const getGitID = (payload: Payload) => {
}
}

const getPayloadPackages = (packageJSON: PackageJSON): Record<string, string> => {
return Object.keys(packageJSON.dependencies || {}).reduce((acc, key) => {
return key.startsWith('@payloadcms/') ? { ...acc, [key]: packageJSON.dependencies[key] } : acc
}, {})
}
const getPackageJSON = async (): Promise<{
packageJSON?: PackageJSON
packageJSONPath: string
}> => {
let packageJSONPath = path.resolve(process.cwd(), 'package.json')

if (!fs.existsSync(packageJSONPath)) {
// Old logic
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
packageJSONPath = await findUp('package.json', { cwd: dirname })
const jsonContent: PackageJSON = JSON.parse(fs.readFileSync(packageJSONPath, 'utf-8'))
return { packageJSON: jsonContent, packageJSONPath }
}

const getPackageJSON = async (): Promise<PackageJSON> => {
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
const packageJsonPath = await findUp('package.json', { cwd: dirname })
const jsonContent: PackageJSON = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))
return jsonContent
const packageJSON: PackageJSON = JSON.parse(fs.readFileSync(packageJSONPath, 'utf-8'))
return { packageJSON, packageJSONPath }
}

const getPackageJSONID = (payload: Payload, packageJSON: PackageJSON): string => {
Expand All @@ -141,3 +154,21 @@ const getPackageJSONID = (payload: Payload, packageJSON: PackageJSON): string =>
export const getPayloadVersion = (packageJSON: PackageJSON): string => {
return packageJSON?.dependencies?.payload ?? ''
}

export const getLocalizationInfo = (
payload: Payload,
): Pick<BaseEvent, 'locales' | 'localizationDefaultLocale' | 'localizationEnabled'> => {
if (!payload.config.localization) {
return {
locales: [],
localizationDefaultLocale: null,
localizationEnabled: false,
}
}

return {
locales: payload.config.localization.localeCodes,
localizationDefaultLocale: payload.config.localization.defaultLocale,
localizationEnabled: true,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const azureBlobStorageAdapter = ({

return ({ collection, prefix }): GeneratedAdapter => {
return {
name: 'azure',
generateURL: getGenerateURL({ baseURL, containerName }),
handleDelete: getHandleDelete({ collection, getStorageClient }),
handleUpload: getHandleUpload({
Expand Down
1 change: 1 addition & 0 deletions packages/plugin-cloud-storage/src/adapters/gcs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export const gcsAdapter =
}

return {
name: 'gcs',
generateURL: getGenerateURL({ bucket, getStorageClient }),
handleDelete: getHandleDelete({ bucket, getStorageClient }),
handleUpload: getHandleUpload({
Expand Down
1 change: 1 addition & 0 deletions packages/plugin-cloud-storage/src/adapters/s3/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export const s3Adapter =
}

return {
name: 's3',
generateURL: getGenerateURL({ bucket, config }),
handleDelete: getHandleDelete({ bucket, getStorageClient }),
handleUpload: getHandleUpload({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export const vercelBlobAdapter =
const baseUrl = `https://${storeId}.${access}.blob.vercel-storage.com`

return {
name: 'vercel-blob',
generateURL: getGenerateUrl({ baseUrl, prefix }),
handleDelete: getHandleDelete({ baseUrl, prefix, token }),
handleUpload: getHandleUpload({
Expand Down
8 changes: 4 additions & 4 deletions packages/plugin-cloud-storage/src/hooks/afterDelete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ export const getAfterDeleteHook = ({

await Promise.all(promises)
} catch (err: unknown) {
req.payload.logger.error(
`There was an error while deleting files corresponding to the ${collection.labels?.singular} with ID ${doc.id}:`,
)
req.payload.logger.error(err)
req.payload.logger.error({
err,
msg: `There was an error while deleting files corresponding to the ${collection.labels?.singular} with ID ${doc.id}.`,
})
}
return doc
}
Expand Down
1 change: 1 addition & 0 deletions packages/plugin-cloud-storage/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export const cloudStorage =
},
upload: {
...(typeof existingCollection.upload === 'object' ? existingCollection.upload : {}),
adapter: adapter.name,
disableLocalStorage:
typeof options.disableLocalStorage === 'boolean'
? options.disableLocalStorage
Expand Down
1 change: 1 addition & 0 deletions packages/plugin-cloud-storage/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface GeneratedAdapter {
generateURL: GenerateURL
handleDelete: HandleDelete
handleUpload: HandleUpload
name: string
onInit?: () => void
staticHandler: StaticHandler
}
Expand Down
1 change: 1 addition & 0 deletions packages/storage-azure/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ function azureStorageInternal({

return ({ collection, prefix }): GeneratedAdapter => {
return {
name: 'azure',
generateURL: getGenerateURL({ baseURL, containerName }),
handleDelete: getHandleDelete({ collection, getStorageClient }),
handleUpload: getHandleUpload({
Expand Down
1 change: 1 addition & 0 deletions packages/storage-gcs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ function gcsStorageInternal({ acl, bucket, options }: GcsStorageOptions): Adapte
}

return {
name: 'gcs',
generateURL: getGenerateURL({ bucket, getStorageClient }),
handleDelete: getHandleDelete({ bucket, getStorageClient }),
handleUpload: getHandleUpload({
Expand Down
1 change: 1 addition & 0 deletions packages/storage-s3/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ function s3StorageInternal({ acl, bucket, config = {} }: S3StorageOptions): Adap
}

return {
name: 's3',
generateURL: getGenerateURL({ bucket, config }),
handleDelete: getHandleDelete({ bucket, getStorageClient }),
handleUpload: getHandleUpload({
Expand Down
1 change: 1 addition & 0 deletions packages/storage-vercel-blob/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ function vercelBlobStorageInternal(
return ({ collection, prefix }): GeneratedAdapter => {
const { access, addRandomSuffix, baseUrl, cacheControlMaxAge, token } = options
return {
name: 'vercel-blob',
generateURL: getGenerateUrl({ baseUrl, prefix }),
handleDelete: getHandleDelete({ baseUrl, prefix, token: options.token }),
handleUpload: getHandleUpload({
Expand Down