Files
ISA-Frontend/.claude/skills/logging/references/api-reference.md
Lorenz Hilpert 43e4a6bf64 ♻️ refactor(claude): migrate skills to new skill-creator format
Recreate all 11 skills using the updated skill-creator tooling:
- api-sync, arch-docs, architecture-validator, css-animations
- git-workflow, library-creator, logging, state-patterns
- tailwind, template-standards, test-migration

Key changes:
- Updated YAML frontmatter structure
- Reorganized logging references into references/ subdirectory
- Applied progressive disclosure patterns where applicable
2025-12-11 12:27:15 +01:00

4.7 KiB

Logging API Reference

API Signatures

// Factory
function logger(ctx?: MaybeLoggerContextFn): LoggerApi

// Logger API
interface LoggerApi {
  trace(message: string, context?: MaybeLoggerContextFn): void;
  debug(message: string, context?: MaybeLoggerContextFn): void;
  info(message: string, context?: MaybeLoggerContextFn): void;
  warn(message: string, context?: MaybeLoggerContextFn): void;
  error(message: string, error?: Error, context?: MaybeLoggerContextFn): void;
}

// Types
type MaybeLoggerContextFn = LoggerContext | (() => LoggerContext);
interface LoggerContext { [key: string]: unknown; }

Common Patterns

Pattern Code
Basic logger #logger = logger()
Static context #logger = logger({ component: 'Name' })
Dynamic context #logger = logger(() => ({ id: this.id }))
Log info this.#logger.info('Message')
Log with context this.#logger.info('Message', () => ({ key: value }))
Log error this.#logger.error('Error', error)
Error with context this.#logger.error('Error', error, () => ({ id }))
Component context providers: [provideLoggerContext({ feature: 'x' })]

Configuration

// app.config.ts
import { provideLogging, withLogLevel, withSink, withContext,
         LogLevel, ConsoleLogSink } from '@isa/core/logging';

export const appConfig: ApplicationConfig = {
  providers: [
    provideLogging(
      withLogLevel(isDevMode() ? LogLevel.Debug : LogLevel.Warn),
      withSink(ConsoleLogSink),
      withContext({ app: 'ISA', version: '1.0.0' })
    )
  ]
};

Log Levels

Level Use Case Example
Trace Method entry/exit this.#logger.trace('Entering processData')
Debug Development info this.#logger.debug('Variable state', () => ({ x }))
Info Runtime events this.#logger.info('User logged in', { userId })
Warn Warnings this.#logger.warn('Deprecated API used')
Error Errors this.#logger.error('Operation failed', error)
Off Disable logging withLogLevel(LogLevel.Off)

Decision Trees

Context Type Decision

Value changes at runtime?
├─ Yes → () => ({ value: this.getValue() })
└─ No  → { value: 'static' }

Computing value is expensive?
├─ Yes → () => ({ data: this.compute() })
└─ No  → Either works

Log Level Decision

Method flow details? → Trace
Development debug?  → Debug
Runtime information? → Info
Potential problem?  → Warn
Error occurred?     → Error

Performance Tips

// ✅ DO: Lazy evaluation
this.#logger.debug('Data', () => ({
  result: this.expensive() // Only runs if debug enabled
}));

// ❌ DON'T: Eager evaluation
this.#logger.debug('Data', {
  result: this.expensive() // Always runs
});

// ✅ DO: Log aggregates
this.#logger.info('Batch done', () => ({ count: items.length }));

// ❌ DON'T: Log in loops
for (const item of items) {
  this.#logger.debug('Item', { item }); // Performance hit
}

Testing

import { createComponentFactory, Spectator } from '@ngneat/spectator/jest';
import { LoggingService } from '@isa/core/logging';

describe('MyComponent', () => {
  const createComponent = createComponentFactory({
    component: MyComponent,
    mocks: [LoggingService]
  });

  it('logs error', () => {
    const spectator = createComponent();
    const logger = spectator.inject(LoggingService);

    spectator.component.operation();

    expect(logger.error).toHaveBeenCalled();
  });
});

Custom Sink

import { Injectable } from '@angular/core';
import { Sink, LogLevel, LoggerContext } from '@isa/core/logging';

@Injectable()
export class CustomSink implements Sink {
  log(level: LogLevel, message: string, context?: LoggerContext, error?: Error): void {
    // Implementation
  }
}

// Register
provideLogging(withSink(CustomSink))

Sink Function (with DI)

import { inject } from '@angular/core';
import { SinkFn, LogLevel } from '@isa/core/logging';

export const remoteSink: SinkFn = () => {
  const http = inject(HttpClient);

  return (level, message, context, error) => {
    if (level === LogLevel.Error) {
      http.post('/api/logs', { level, message, context, error }).subscribe();
    }
  };
};

// Register
provideLogging(withSinkFn(remoteSink))

Common Imports

// Main imports
import { logger, provideLoggerContext } from '@isa/core/logging';

// Configuration imports
import {
  provideLogging,
  withLogLevel,
  withSink,
  withContext,
  LogLevel,
  ConsoleLogSink
} from '@isa/core/logging';

// Type imports
import {
  LoggerApi,
  Sink,
  SinkFn,
  LoggerContext
} from '@isa/core/logging';