• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { BuildConfig } from './types';
17import {
18  ErrorCode,
19  SubsystemCode
20} from './error_code';
21
22export class Logger {
23  private static instance: Logger | undefined;
24  private loggerMap: { [key in SubsystemCode]?: ILogger };
25  private hasErrorOccurred: boolean = false;
26
27  private constructor(projectConfig: BuildConfig) {
28    if (typeof projectConfig.getHvigorConsoleLogger !== 'function') {
29      projectConfig.getHvigorConsoleLogger = getConsoleLogger;
30    }
31    let getHvigorConsoleLogger = projectConfig.getHvigorConsoleLogger as Function;
32    this.loggerMap = {};
33    this.loggerMap[SubsystemCode.BUILDSYSTEM] = getHvigorConsoleLogger(SubsystemCode.BUILDSYSTEM);
34    this.loggerMap[SubsystemCode.ES2PANDA] = getHvigorConsoleLogger(SubsystemCode.ES2PANDA);
35  }
36
37  public static getInstance(projectConfig?: BuildConfig): Logger {
38    if (!Logger.instance) {
39      if (!projectConfig) {
40        throw new Error('projectConfig is required for the first instantiation.');
41      }
42      Logger.instance = new Logger(projectConfig);
43    }
44    return Logger.instance;
45  }
46
47  public static destroyInstance(): void {
48    Logger.instance = undefined;
49  }
50
51  public printInfo(message: string, subsystemCode: SubsystemCode = SubsystemCode.BUILDSYSTEM): void {
52    const logger: ILogger = this.getLoggerFromSubsystemCode(subsystemCode);
53    logger.printInfo(message);
54  }
55
56  public printWarn(message: string, subsystemCode: SubsystemCode = SubsystemCode.BUILDSYSTEM): void {
57    const logger: ILogger = this.getLoggerFromSubsystemCode(subsystemCode);
58    logger.printWarn(message);
59  }
60
61  public printDebug(message: string, subsystemCode: SubsystemCode = SubsystemCode.BUILDSYSTEM): void {
62    const logger: ILogger = this.getLoggerFromSubsystemCode(subsystemCode);
63    logger.printDebug(message);
64  }
65
66  public printError(error: LogData): void {
67    this.hasErrorOccurred = true;
68    const logger: ILogger = this.getLoggerFromErrorCode(error.code);
69    logger.printError(error);
70  }
71
72  public printErrorAndExit(error: LogData): void {
73    this.hasErrorOccurred = true;
74    const logger: ILogger = this.getLoggerFromErrorCode(error.code);
75    logger.printErrorAndExit(error);
76  }
77
78  private isValidErrorCode(errorCode: ErrorCode): boolean {
79    return /^\d{8}$/.test(errorCode);
80  }
81
82  private getLoggerFromErrorCode(errorCode: ErrorCode): ILogger {
83    if (!this.isValidErrorCode(errorCode)) {
84      throw new Error('Invalid errorCode.');
85    }
86    const subsystemCode = errorCode.slice(0, 3) as SubsystemCode;
87    const logger = this.getLoggerFromSubsystemCode(subsystemCode);
88    return logger;
89  }
90
91  private getLoggerFromSubsystemCode(subsystemCode: SubsystemCode): ILogger {
92    if (!this.loggerMap[subsystemCode]) {
93      throw new Error('Invalid subsystemCode.');
94    }
95    return this.loggerMap[subsystemCode];
96  }
97
98  public hasErrors(): boolean {
99    return this.hasErrorOccurred;
100  }
101
102  public resetErrorFlag(): void {
103    this.hasErrorOccurred = false;
104  }
105}
106
107interface ILogger {
108  printInfo(message: string): void;
109  printWarn(message: string): void;
110  printDebug(message: string): void;
111  printError(error: LogData): void;
112  printErrorAndExit(error: LogData): void;
113}
114
115export class LogDataFactory {
116
117  static newInstance(
118    code: ErrorCode,
119    description: string,
120    cause: string = '',
121    position: string = '',
122    solutions: string[] = [],
123    moreInfo?: Object
124  ): LogData {
125    const data: LogData = new LogData(code, description, cause, position, solutions, moreInfo);
126    return data;
127  }
128}
129
130export class LogData {
131
132  code: ErrorCode;
133  description: string;
134  cause: string;
135  position: string;
136  solutions: string[];
137  moreInfo?: Object;
138
139  constructor(
140    code: ErrorCode,
141    description: string,
142    cause: string = '',
143    position: string = '',
144    solutions: string[],
145    moreInfo?: Object
146  ) {
147    this.code = code;
148    this.description = description;
149    this.cause = cause;
150    this.position = position;
151    this.solutions = solutions;
152    if (moreInfo) {
153      this.moreInfo = moreInfo;
154    }
155  }
156
157  toString(): string {
158    let errorString = `ERROR Code: ${this.code} ${this.description}\n`;
159
160    if (this.cause || this.position) {
161      errorString += `Error Message: ${this.cause}`;
162      if (this.position) {
163        errorString += ` ${this.position}`;
164      }
165      errorString += '\n\n';
166    }
167
168    if (this.solutions.length > 0 && this.solutions[0] !== '') {
169      errorString += `* Try the following: \n${this.solutions.map(str => `  > ${str}`).join('\n')}\n`;
170    }
171
172    if (this.moreInfo) {
173      errorString += `\nMore Info:\n`;
174      for (const [key, value] of Object.entries(this.moreInfo)) {
175        errorString += `  - ${key.toUpperCase()}: ${value}\n`;
176      }
177    }
178
179    return errorString;
180  }
181}
182
183class ConsoleLogger {
184  private static instances: { [key: string]: ConsoleLogger } = {};
185
186  private constructor() {}
187
188  public printInfo(message: string): void {
189    console.info(message);
190  }
191
192  public printWarn(message: string): void {
193    console.warn(message);
194  }
195
196  public printDebug(message: string): void {
197    console.debug(message);
198  }
199
200  public printError(error: LogData): void {
201    console.error(error.toString());
202  }
203
204  public printErrorAndExit(error: LogData): void {
205    console.error(error.toString());
206    process.exit(1);
207  }
208
209  public static createLogger(subsystemCode: string): ConsoleLogger {
210    if (!ConsoleLogger.instances[subsystemCode]) {
211      ConsoleLogger.instances[subsystemCode] = new ConsoleLogger();
212    }
213    return ConsoleLogger.instances[subsystemCode];
214  }
215}
216
217function getConsoleLogger(subsystemCode: string): ConsoleLogger {
218  return ConsoleLogger.createLogger(subsystemCode);
219}
220