import type logSymbols from "log-symbols"; import type { GrowError } from "@garden-io/grow-sdk/errors"; import type { LogMessage, Log as SdkLog } from "@garden-io/grow-sdk/logs"; import type { Omit } from "@garden-io/grow-sdk/util/types"; import type { LogLevel, Logger } from "./logger"; export type LogSymbol = keyof typeof logSymbols | "empty"; export type TaskLogStatus = "active" | "success" | "error"; export interface LogMetadata { task?: TaskMetadata; workflowStep?: WorkflowStepMetadata; } export interface TaskMetadata { type: string; key: string; status: TaskLogStatus; uid: string; inputVersion: string | null; outputVersion?: string; durationMs?: number; } export interface WorkflowStepMetadata { index: number; } interface BaseContext { /** * Reference to what created the log message, e.g. tool that generated it (such as "docker") */ origin?: string; type: "coreLog" | "actionLog"; /** * A session ID, to identify the log entry as part of a specific command execution. */ sessionId?: string; /** * The key of a Garden instance, if applicable. */ gardenKey?: string; } export interface CoreLogContext extends BaseContext { type: "coreLog"; /** * The name of the log context. Will be printed as the "section" part of the log lines * belonging to this context. */ name?: string; } export interface ActionLogContext extends BaseContext { type: "actionLog"; /** * The name of the action that produced the log entry. Is printed in the "section" part of the log lines. */ actionName: string; /** * The action uid. */ actionUid: string; } export type LogContext = CoreLogContext | ActionLogContext; /** * Common Log config that the class implements and other interfaces pick / omit from. */ interface LogConfig { /** * A unique ID that's assigned to the config when it's created. */ key: string; timestamp: string; /** * Additional metadata to pass to the log context. The metadata gets added to * all log entries which can optionally extend it. */ metadata?: LogMetadata; /** * Fix the level of all log entries created by this Log such that they're * geq to this value. * * Useful to enforce the level in a given log context, e.g.: * const debugLog = log.createLog({ fixLevel: "debug" }) */ fixLevel?: LogLevel; context: C; /** * Append the duration from when the log context was created and until the * success or error methods are called to the success/error message. * E.g.: If calling `log.success(Done!)`, then the log message becomes "Done! (in 4 sec)" if showDuration=true. */ showDuration?: boolean; } interface LogConstructor extends Omit, "key" | "timestamp"> { root: Logger; parentConfigs: LogConfig[]; } interface CreateLogParams extends Pick, "metadata" | "fixLevel" | "showDuration">, Pick { } interface CreateCoreLogParams extends Pick, "metadata" | "fixLevel" | "showDuration">, Pick { name?: string; origin?: string; } export declare function transformMsg(msg: LogMessage, transformer: (input: string) => string): LogMessage; export interface LogEntry extends Pick, "key" | "timestamp" | "metadata" | "context"> { /** * The unique ID of the log context that created the log entry. */ parentLogKey: string; level: LogLevel; /** * The actual text of the log message. */ msg?: LogMessage; /** * A "raw" version of the log line. This field is preferred over 'msg' if set when rendering * log entries in the dashboard. * * Use this if the entry has a msg that doesn't render well in the UI. In that case you * can set terminal log line via the 'msg' field and a web friendly version via this field. */ rawMsg?: LogMessage; /** * A symbol that's printed with the log message to indicate it's type (e.g. "error" or "success"). */ symbol?: LogSymbol; data?: unknown; dataFormat?: "json" | "yaml"; error?: GrowError; skipEmit?: boolean; } interface LogParams extends Pick, Pick, Pick, "showDuration"> { } interface CreateLogEntryParams extends LogParams { level: LogLevel; } /** * A helper function for creating instances of ActionLogs. That is, the log class required * by most actions. * * It differs from the "normal" CoreLog class in that it's context type is "ActionLogContext" * which includes the action name. */ export declare function createActionLog({ log, actionName, origin, fixLevel, actionUid, }: { log: Log; actionName: string; actionUid: string; origin?: string; fixLevel?: LogLevel; }): ActionLog; /** * The abstract log class which the CoreLog, ActionLog, and others extends. * * Contains all the methods the log classes use for writing logs at different levels * a long with a handful of helper methods. */ export declare abstract class Log { readonly showDuration?: boolean; readonly metadata?: LogMetadata; readonly key: string; readonly parentConfigs: LogConfig[]; readonly timestamp: string; readonly root: Logger; readonly fixLevel?: LogLevel; readonly entries: LogEntry[]; readonly context: C; constructor(params: LogConstructor); /** * Helper method for creating the actual log entry shape that gets passed to the root * logger for writing. */ private createLogEntry; /** * Helper method for creating the basic log config that gets passed down to child logs * when creating new log instances. */ protected makeLogConfig(params: CreateLogParams): { metadata: LogMetadata | undefined; fixLevel: "error" | "warn" | "info" | "verbose" | "debug" | "silly" | undefined; showDuration: boolean; context: C & { origin: string | undefined; }; root: Logger; parentConfigs: (LogConfig | LogConfig)[]; }; /** * Create a new log instance of the same type as the parent log. */ abstract createLog(params?: CreateLogParams | CreateCoreLogParams): CoreLog | ActionLog; protected log(params: CreateLogEntryParams): this; /** * Append the duration to the log message if showDuration=true. * * That is, the time from when the log instance got created until now. */ private getMsgWithDuration; private resolveCreateParams; /** * Render a log entry at the silly level. This is the highest verbosity. */ silly(params: LogMessage | LogParams): this; /** * Render a log entry at the debug level. Intended for internal information * which can be useful for debugging. */ debug(params: LogMessage | LogParams): this; /** * Render a log entry at the verbose level. Intended for logs generated when * actions are executed. E.g. logs from Kubernetes. */ verbose(params: LogMessage | LogParams): this; /** * Render a log entry at the info level. Intended for framework level logs * such as information about the action being executed. */ info(params: LogMessage | (LogParams & { symbol?: Exclude; })): this; /** * Render a log entry at the warning level. */ warn(params: LogMessage | Omit): this; /** * Render a log entry at the error level. * Appends the duration to the message if showDuration=true. */ error(params: LogMessage | Omit): this; /** * Render a log entry at the info level with "success" styling. * Appends the duration to the message if showDuration=true. * * TODO @eysi: This should really happen in the renderer and the parent log context * timestamp, the log entry timestamp, and showDuration should just be fields on the entry. */ success(params: LogMessage | Omit): this; getConfig(): LogConfig; /** * Get the latest entry for this particular log context. */ getLatestEntry(): LogEntry | undefined; /** * Get the log entries for this particular log context. */ getLogEntries(): LogEntry[]; /** * Get all log entries, from this and other contexts, via the root logger. */ getAllLogEntries(): LogEntry[]; /** * Dumps log entries for this particular log context as a string, optionally filtering the entries with `filter`. * For example, to dump all the logs of level info or higher: * * log.toString((entry) => shouldEmitLog(entry.level, "info")) */ toString(filter?: (log: LogEntry) => boolean): string; /** * Return the log start time as a Date instance */ getStartTime(): Date; toSanitizedValue(): string; } /** * This is the default log class and mostly used for log entries created before invoking * actions and plugins. * * The corresponding log context has a name which is used in the section part when printing log * lines. * * The log context can be overwritten when creating child logs. */ export declare class CoreLog extends Log implements SdkLog { /** * Create a new CoreLog instance, optionally overwriting the context. */ createLog(params?: CreateCoreLogParams): CoreLog; } /** * The ActionLog class is used for log entries created by actions. * * The corresponding log context requires 'actionName' which is used in the section part when * printing log lines. * * The 'actionName' cannot be overwritten when creating child logs. */ export declare class ActionLog extends Log implements SdkLog { showDuration: boolean; /** * Create a new ActionLog instance. The new instance inherits the parent context. */ createLog(params?: CreateLogParams): ActionLog; createSilentLog(params?: CreateLogParams): ActionLog; } /** * A silent version of the `ActionLog` class. It doesn't print any log entries. Useful when * dynamically creating either a non-silent or silent log instance based on an action config's * `logOutput` field. * * This also lets helper functions accept a `log` parameter without having to be aware of * whether the logs actually get streamed (that's decided higher up in the flow). */ export declare class SilentActionLog extends ActionLog { log(_params: CreateLogEntryParams): this; } export {};