• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

dev-ignis / cross-log / 16982792483

15 Aug 2025 04:15AM UTC coverage: 85.706% (-9.9%) from 95.62%
16982792483

push

github

dev-ignis
test: - ci;

489 of 647 branches covered (75.58%)

Branch coverage included in aggregate %.

944 of 1025 relevant lines covered (92.1%)

357.96 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.81
/src/loggers/base.ts
1
/**
2
 * Base logger implementation with shared functionality
3
 */
4

5
import { 
36✔
6
  LoggerConfig, 
7
  LogLevel, 
8
  LogEntry,
9
  PartialLoggerConfig 
10
} from '../core/types';
11
import { ConfigManager } from '../core/config';
36✔
12
import { 
36✔
13
  isLoggingEnabled, 
14
  formatMessage
15
} from '../core/utils';
16
import { PluginManager } from '../plugins/manager';
36✔
17
import { Plugin, LoggerWithPlugins } from '../plugins/types';
18

19
export abstract class BaseLogger implements LoggerWithPlugins {
36✔
20
  protected configManager: ConfigManager;
21
  protected pluginManager: PluginManager;
22
  protected recentLogs: Map<string, number> = new Map();
705✔
23
  protected readonly duplicateThreshold = 1000; // ms
705✔
24

25
  constructor(initialConfig?: PartialLoggerConfig) {
26
    this.configManager = new ConfigManager(initialConfig);
705✔
27
    this.pluginManager = new PluginManager(this);
705✔
28
  }
29

30
  /**
31
   * Log debug message
32
   */
33
  debug(message: string, category?: string, ...args: unknown[]): void {
34
    this.logWithLevel(LogLevel.DEBUG, message, category, ...args);
3,399✔
35
  }
36

37
  /**
38
   * Log informational message
39
   */
40
  info(message: string, category?: string, ...args: unknown[]): void {
41
    this.logWithLevel(LogLevel.INFO, message, category, ...args);
9,708✔
42
  }
43

44
  /**
45
   * Log warning message
46
   */
47
  warn(message: string, category?: string, ...args: unknown[]): void {
48
    this.logWithLevel(LogLevel.WARN, message, category, ...args);
3,123✔
49
  }
50

51
  /**
52
   * Log error message or Error object
53
   */
54
  error(message: string | Error, category?: string, ...args: unknown[]): void {
55
    this.logWithLevel(LogLevel.ERROR, message, category, ...args);
159✔
56
  }
57

58
  /**
59
   * Set the minimum log level
60
   */
61
  setLevel(level: LogLevel): void {
62
    const config = this.configManager.getConfig();
30✔
63
    this.configManager.updateConfig({ ...config, minLevel: level });
30✔
64
  }
65

66
  /**
67
   * Configure the logger
68
   */
69
  configure(newConfig: PartialLoggerConfig): void {
70
    this.configManager.updateConfig(newConfig);
42✔
71
  }
72

73
  /**
74
   * Enable logging for a specific category
75
   */
76
  enableCategory(category: string, minLevel: LogLevel = LogLevel.DEBUG): void {
×
77
    const config = this.configManager.getConfig();
39✔
78
    config.categories[category] = { enabled: true, minLevel };
39✔
79
    this.configManager.updateConfig(config);
39✔
80
  }
81

82
  /**
83
   * Disable logging for a specific category
84
   */
85
  disableCategory(category: string): void {
86
    const config = this.configManager.getConfig();
15✔
87
    if (config.categories[category]) {
15!
88
      config.categories[category].enabled = false;
×
89
    } else {
90
      config.categories[category] = { enabled: false, minLevel: LogLevel.DEBUG };
15✔
91
    }
92
    this.configManager.updateConfig(config);
15✔
93
  }
94

95
  /**
96
   * Enable all logging
97
   */
98
  enableAll(): void {
99
    const config = this.configManager.getConfig();
12✔
100
    config.enabled = true;
12✔
101
    config.minLevel = LogLevel.DEBUG;
12✔
102
    
103
    // Enable all existing categories
104
    Object.keys(config.categories).forEach(category => {
12✔
105
      config.categories[category]!.enabled = true;
×
106
    });
107
    
108
    this.configManager.updateConfig(config);
12✔
109
  }
110

111
  /**
112
   * Disable all logging
113
   */
114
  disableAll(): void {
115
    const config = this.configManager.getConfig();
15✔
116
    config.enabled = false;
15✔
117
    this.configManager.updateConfig(config);
15✔
118
  }
119

120
  /**
121
   * Get the current logger configuration
122
   */
123
  getConfig(): LoggerConfig {
124
    return this.configManager.getConfig();
138✔
125
  }
126

127
  /**
128
   * Check if logging is currently enabled
129
   */
130
  isEnabled(): boolean {
131
    return this.configManager.getConfig().enabled;
27✔
132
  }
133

134
  /**
135
   * Log level constants
136
   */
137
  get Level(): typeof LogLevel {
138
    return LogLevel;
57✔
139
  }
140

141
  /**
142
   * Use a plugin with the logger
143
   */
144
  use(plugin: Plugin): void {
145
    this.pluginManager.use(plugin);
177✔
146
  }
147

148
  /**
149
   * Get a plugin instance by name
150
   */
151
  getPlugin(name: string) {
152
    return this.pluginManager.getPlugin(name);
3✔
153
  }
154

155
  /**
156
   * Core logging method with level checking
157
   */
158
  protected logWithLevel(
159
    level: LogLevel,
160
    message: string | Error,
161
    category?: string,
162
    ...args: unknown[]
163
  ): void {
164
    const config = this.configManager.getConfig();
16,389✔
165

166
    // Check if logging is globally enabled
167
    if (!config.enabled) return;
16,389✔
168

169
    // Check category-specific settings first
170
    if (category && config.categories[category]) {
1,353✔
171
      const categoryConfig = config.categories[category]!;
36✔
172
      if (!categoryConfig.enabled) return;
36✔
173
      if (!isLoggingEnabled(categoryConfig.minLevel, level, true)) return;
27✔
174
    } else {
175
      // Check global log level only if no category-specific settings
176
      if (!isLoggingEnabled(config.minLevel, level, true)) return;
1,317✔
177
    }
178

179
    // Check for duplicate logs
180
    if (this.isDuplicateLog(message, category)) return;
1,266✔
181

182
    // Create log entry
183
    const logEntry: LogEntry = {
1,236✔
184
      level,
185
      message: typeof message === 'string' ? message : message.message,
1,236✔
186
      category,
187
      timestamp: new Date(),
188
      args
189
    };
190

191
    // Format message
192
    const formattedMessage = formatMessage(
1,236✔
193
      logEntry.message,
194
      category,
195
      config.showTimestamp
196
    );
197

198
    // Output the log
199
    this.outputLog(level, formattedMessage, logEntry, ...args);
1,236✔
200

201
    // Handle error stack traces
202
    if (level === LogLevel.ERROR && config.includeStackTrace) {
1,233✔
203
      // Check if message is an Error
204
      if (message instanceof Error) {
138✔
205
        this.outputStackTrace(message);
30✔
206
      } else {
207
        // Check if any of the arguments is an Error
208
        for (const arg of args) {
108✔
209
          if (arg instanceof Error) {
54✔
210
            this.outputStackTrace(arg);
9✔
211
            break; // Only output the first error's stack trace
9✔
212
          }
213
        }
214
      }
215
    }
216
  }
217

218
  /**
219
   * Check if this is a duplicate log message
220
   */
221
  protected isDuplicateLog(message: string | Error, category?: string): boolean {
222
    const key = `${typeof message === 'string' ? message : message.message}:${category || ''}`;
1,266✔
223
    const now = Date.now();
1,266✔
224
    const lastTime = this.recentLogs.get(key);
1,266✔
225

226
    if (lastTime && (now - lastTime) < this.duplicateThreshold) {
1,266✔
227
      return true;
30✔
228
    }
229

230
    this.recentLogs.set(key, now);
1,236✔
231
    
232
    // Clean up old entries
233
    if (this.recentLogs.size > 100) {
1,236✔
234
      const cutoff = now - this.duplicateThreshold * 2;
150✔
235
      for (const [k, time] of this.recentLogs.entries()) {
150✔
236
        if (time < cutoff) {
18,825!
237
          this.recentLogs.delete(k);
×
238
        }
239
      }
240
    }
241

242
    return false;
1,236✔
243
  }
244

245
  /**
246
   * Abstract method for outputting logs (implemented by subclasses)
247
   */
248
  protected abstract outputLog(
249
    level: LogLevel,
250
    formattedMessage: string,
251
    logEntry: LogEntry,
252
    ...args: unknown[]
253
  ): void;
254

255
  /**
256
   * Abstract method for outputting stack traces (implemented by subclasses)
257
   */
258
  protected abstract outputStackTrace(error: Error): void;
259
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc