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

Experimental logging #906

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
2 changes: 2 additions & 0 deletions cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
"miniflare": "^2.11.0",
"node-fetch": "^3.3.0",
"open": "^8.4.1",
"pino": "^8.10.0",
"pino-pretty": "^9.2.0",
"prompts": "^2.4.2",
"relaxed-json": "^1.0.3",
"rollup-plugin-esbuild": "^5.0.0",
Expand Down
82 changes: 77 additions & 5 deletions cli/src/base.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Command, Config, Flags, Interfaces } from '@oclif/core';
import { Command, Flags, Interfaces } from '@oclif/core';
import {
getAPIKey,
getCurrentBranchName,
Expand All @@ -14,8 +14,10 @@ import { cosmiconfigSync } from 'cosmiconfig';
import dotenv from 'dotenv';
import dotenvExpand from 'dotenv-expand';
import { readFile, writeFile } from 'fs/promises';
import compact from 'lodash.compact';
import fetch from 'node-fetch';
import path from 'path';
import pino from 'pino';
import prompts from 'prompts';
import table from 'text-table';
import which from 'which';
Expand All @@ -30,6 +32,8 @@ import {
} from './credentials.js';
import { reportBugURL } from './utils.js';

const logLevels = ['debug', 'info', 'warn', 'error'] as const;

export const projectConfigSchema = z.object({
databaseURL: z.string(),
codegen: z.object({
Expand Down Expand Up @@ -82,6 +86,8 @@ export abstract class BaseCommand<T extends typeof Command> extends Command {

#xataClient?: XataApiClient;

#logger!: pino.Logger;

// The first place is the one used by default when running `xata init`
// In the future we can support YAML
searchPlaces = [`.${moduleName}rc`, `.${moduleName}rc.json`, 'package.json'];
Expand Down Expand Up @@ -128,6 +134,16 @@ export abstract class BaseCommand<T extends typeof Command> extends Command {
helpGroup: commonFlagsHelpGroup,
helpValue: '<profile-name>',
description: 'Profile name to use'
}),
'log-level': Flags.custom<(typeof logLevels)[number]>({
summary: 'Specify level for logging.',
options: Object.values(logLevels),
helpGroup: commonFlagsHelpGroup,
description: `Specify level for logging. Possible values: ${Object.values(logLevels).join(', ')}.`
})(),
'log-file': Flags.string({
helpGroup: commonFlagsHelpGroup,
description: 'Specify file to persist all logs.'
})
};

Expand All @@ -151,6 +167,19 @@ export abstract class BaseCommand<T extends typeof Command> extends Command {
}

async init() {
const { flags } = await this.parseCommand();
const { ['log-file']: logFile, ['log-level']: logLevel = 'info' } = flags;

this.#logger = pino({
level: logLevel,
transport: {
targets: compact([
{ level: logLevel, target: 'pino-pretty', options: { colorize: true } },
logFile ? { level: 'trace', target: 'pino/file', options: { destination: logFile } } : undefined
])
}
});

if (process.env.XATA_API_KEY) this.apiKeyLocation = 'shell';
for (const envFile of ENV_FILES) {
this.loadEnvFile(envFile);
Expand Down Expand Up @@ -262,14 +291,57 @@ export abstract class BaseCommand<T extends typeof Command> extends Command {
});
}

info(message: string) {
this.log(`${chalk.blueBright('i')} ${message}`);
log(message?: string) {
this.#logger.info(message);
return super.log(message);
}

success(message: string) {
this.log(`${chalk.greenBright('✔')} ${message}`);
info(message?: string) {
this.#logger.info(message);
return super.log(`${chalk.blueBright('i')} ${message}`);
}

success(message?: string) {
this.#logger.info(message);
return super.log(`${chalk.greenBright('✔')} ${message}`);
}

warn(input: string | Error) {
this.#logger.warn(input instanceof Error ? input.message : input);
return super.warn(input);
}

error(
input: string | Error,
options?: {
/**
* messsage to display related to the error
*/
message?: string;
/**
* a unique error code for this error class
*/
code?: string;
/**
* a url to find out more information related to this error
* or fixing the error
*/
ref?: string;
/**
* a suggestion that may be useful or provide additional context
*/
suggestions?: string[];
}
) {
this.#logger.error(input instanceof Error ? input.message : input);
return super.error(input, options);
}

debug = (...args: any[]) => {
this.#logger.debug(args);
return super.debug(args);
};

async verifyAPIKey(profile: Profile) {
this.info('Checking access to the API...');
const xata = await this.getXataClient(profile);
Expand Down
59 changes: 56 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.