serverless/lib/utils/telemetry/generatePayload.js

165 lines
4.8 KiB
JavaScript

'use strict';
const path = require('path');
const os = require('os');
const fs = require('fs').promises;
const userConfig = require('@serverless/utils/config');
const isStandalone = require('../isStandaloneExecutable');
const { triggeredDeprecations } = require('../logDeprecation');
const isNpmGlobal = require('../npmPackage/isGlobal');
const noServiceCommands = require('../../cli/commands-schema/no-service');
const ci = require('ci-info');
const versions = {
'serverless': require('../../../package').version,
'@serverless/enterprise-plugin': require('@serverless/enterprise-plugin/package').version,
};
const checkIsTabAutocompletionInstalled = async () => {
try {
return (await fs.readdir(path.resolve(os.homedir(), '.config/tabtab'))).some((filename) =>
filename.startsWith('serverless.')
);
} catch {
return false;
}
};
const shouldIncludeServiceSpecificConfig = (serverless) => {
if (!serverless.serviceDir) {
return false;
}
const noServiceCommand = noServiceCommands.get(serverless.processedInput.commands.join(' '));
if (noServiceCommand && !noServiceCommand.serviceDependencyMode) {
return false;
}
return true;
};
const getServiceConfig = (serverless) => {
const { service: serviceConfig } = serverless;
const { provider: providerConfig } = serviceConfig;
const provider = serverless.getProvider(providerConfig.name);
const isAwsProvider = providerConfig.name === 'aws';
const defaultRuntime = isAwsProvider ? provider.getRuntime() : providerConfig.runtime;
return {
provider: {
name: providerConfig.name,
runtime: defaultRuntime,
stage: isAwsProvider ? provider.getStage() : providerConfig.stage,
region: isAwsProvider ? provider.getRegion() : providerConfig.region,
},
plugins: serviceConfig.plugins ? serviceConfig.plugins.modules || serviceConfig.plugins : [],
functions: Object.values(serviceConfig.functions).map((functionConfig) => {
const functionEvents = functionConfig.events || [];
const functionRuntime = (() => {
if (functionConfig.image) return '$containerimage';
return functionConfig.runtime || defaultRuntime;
})();
return {
runtime: functionRuntime,
events: functionEvents.map((eventConfig) => ({
type: Object.keys(eventConfig)[0] || null,
})),
};
}),
};
};
module.exports = async (serverless) => {
let timezone;
try {
timezone = new Intl.DateTimeFormat().resolvedOptions().timeZone;
} catch {
// Pass silently
}
const ciName = (() => {
if (process.env.SERVERLESS_CI_CD) {
return 'Serverless CI/CD';
}
if (process.env.SEED_APP_NAME) {
return 'Seed';
}
if (ci.isCI) {
if (ci.name) {
return ci.name;
}
return 'unknown';
}
return null;
})();
const userId = (() => {
// In this situation deployment relies on existence on company-wide access key
// and `userId` from config does not matter
if (process.env.SERVERLESS_ACCESS_KEY) {
return null;
}
return userConfig.get('userId');
})();
const payload = {
ciName,
cliName: 'serverless',
command: serverless.processedInput.commands.join(' '),
dashboard: {
userId,
},
firstLocalInstallationTimestamp: userConfig.get('meta.created_at'),
frameworkLocalUserId: userConfig.get('frameworkId'),
installationType: await (async () => {
if (isStandalone) {
if (process.platform === 'win32') return 'global:standalone:windows';
return 'global:standalone:other';
}
if (!serverless.isLocallyInstalled) {
return (await isNpmGlobal()) ? 'global:npm' : 'global:other';
}
if (serverless._isInvokedByGlobalInstallation) return 'local:fallback';
return 'local:direct';
})(),
isAutoUpdateEnabled: Boolean(userConfig.get('autoUpdate.enabled')),
isTabAutocompletionInstalled: await checkIsTabAutocompletionInstalled(),
timestamp: Date.now(),
timezone,
triggeredDeprecations: Array.from(triggeredDeprecations),
versions,
};
if (shouldIncludeServiceSpecificConfig(serverless)) {
const npmDependencies = (() => {
const pkgJson = (() => {
try {
return require(path.resolve(serverless.serviceDir, 'package.json'));
} catch (error) {
return null;
}
})();
if (!pkgJson) return [];
return Array.from(
new Set([
...Object.keys(pkgJson.dependencies || {}),
...Object.keys(pkgJson.optionalDependencies || {}),
...Object.keys(pkgJson.devDependencies || {}),
])
);
})();
payload.npmDependencies = npmDependencies;
payload.config = getServiceConfig(serverless);
payload.dashboard.orgUid = serverless.service.orgUid;
}
return payload;
};