CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-tslog

Extensible TypeScript Logger for Node.js and Browser with customizable log levels, pretty or JSON output formatting, and universal compatibility.

Pending
Overview
Eval results
Files

transports.mddocs/

Transports

External logging system for integrating with log services, file systems, databases, and other logging destinations. Transports receive all log objects after processing and can forward them to external systems.

Capabilities

Transport Function Interface

Transport functions receive processed log objects and can handle them according to their specific requirements.

/**
 * Transport function interface for handling log objects
 * @template LogObj - Type for log object structure
 */
type TransportLogger<LogObj> = (transportLogger: LogObj & ILogObjMeta) => void;

/**
 * Log object with metadata passed to transports
 */
interface LogObj & ILogObjMeta {
  /** User-defined log data */
  [key: string]: unknown;
  
  /** Metadata property containing log information */
  [metaProperty: string]: IMeta;
}

interface IMeta {
  /** Timestamp when log was created */
  date: Date;
  /** Numeric log level (0-6) */
  logLevelId: number;
  /** String log level name */
  logLevelName: string;
  /** Stack frame information if available */
  path?: IStackFrame;
  /** Logger name */
  name?: string;
  /** Parent logger names for hierarchical loggers */
  parentNames?: string[];
  /** Runtime environment identifier */
  runtime: string;
}

Attaching Transports

Method to attach external transport functions to logger instances.

/**
 * Attach external transport for log forwarding
 * @param transportLogger - Function to handle log objects
 */
attachTransport(transportLogger: (transportLogger: LogObj & ILogObjMeta) => void): void;

Usage Examples:

import { Logger } from "tslog";

const logger = new Logger({ name: "MyApp" });

// Simple console transport
logger.attachTransport((logObj) => {
  console.log("External:", JSON.stringify(logObj));
});

// File transport example
import * as fs from "fs";

logger.attachTransport((logObj) => {
  const logLine = JSON.stringify(logObj) + "\n";
  fs.appendFileSync("application.log", logLine);
});

// Database transport example
logger.attachTransport(async (logObj) => {
  await database.logs.insert({
    timestamp: logObj._meta.date,
    level: logObj._meta.logLevelName,
    message: logObj[0], // First argument
    metadata: logObj,
  });
});

Multiple Transports

Loggers can have multiple transports attached, and each log message will be sent to all attached transports.

/**
 * Multiple transports are stored in settings
 */
interface ISettings<LogObj> {
  attachedTransports: ((transportLogger: LogObj & ILogObjMeta) => void)[];
}

Usage Examples:

import { Logger } from "tslog";

const logger = new Logger({ name: "MultiTransportApp" });

// Attach multiple transports
logger.attachTransport((logObj) => {
  // Send to external logging service
  externalLogService.send(logObj);
});

logger.attachTransport((logObj) => {
  // Write to file
  fs.appendFileSync("app.log", JSON.stringify(logObj) + "\n");
});

logger.attachTransport((logObj) => {
  // Send critical errors to monitoring system
  if (logObj._meta.logLevelId >= 5) { // ERROR and FATAL
    monitoringSystem.alert(logObj);
  }
});

// All transports will receive this log
logger.error("Database connection failed", { database: "users" });

Transport Configuration

Transports can be configured during logger initialization or added later.

/**
 * Configure transports during initialization
 */
interface ISettingsParam<LogObj> {
  attachedTransports?: ((transportLogger: LogObj & ILogObjMeta) => void)[];
}

Usage Examples:

import { Logger } from "tslog";

// Configure transports during initialization
const logger = new Logger({
  name: "PreConfiguredApp",
  attachedTransports: [
    (logObj) => {
      // File transport
      fs.appendFileSync("startup.log", JSON.stringify(logObj) + "\n");
    },
    (logObj) => {
      // External service transport
      if (logObj._meta.logLevelId >= 4) { // WARN and above
        alertingService.send(logObj);
      }
    },
  ],
});

// Add additional transports later
logger.attachTransport((logObj) => {
  // Development debugging transport
  if (process.env.NODE_ENV === "development") {
    debugConsole.log(logObj);
  }
});

Transport Best Practices

Guidelines for implementing robust transport functions.

/**
 * Example robust transport implementation
 */
function createRobustTransport(config: TransportConfig): TransportLogger<any> {
  return (logObj) => {
    try {
      // Handle the log object
      processLogObject(logObj, config);
    } catch (error) {
      // Don't let transport errors crash the application
      console.error("Transport error:", error);
    }
  };
}

interface TransportConfig {
  /** Maximum retries for failed sends */
  maxRetries?: number;
  /** Timeout for transport operations */
  timeout?: number;
  /** Buffer size for batching logs */
  bufferSize?: number;
  /** Filter function for selective logging */
  filter?: (logObj: any) => boolean;
}

Usage Examples:

import { Logger } from "tslog";

// HTTP transport with error handling
function createHttpTransport(endpoint: string) {
  return (logObj: any) => {
    try {
      fetch(endpoint, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(logObj),
      }).catch((error) => {
        // Handle network errors without crashing
        console.error("HTTP transport failed:", error);
      });
    } catch (error) {
      console.error("HTTP transport error:", error);
    }
  };
}

// Filtered transport (only errors and fatals)
function createErrorOnlyTransport(handler: (logObj: any) => void) {
  return (logObj: any) => {
    if (logObj._meta.logLevelId >= 5) { // ERROR and FATAL only
      handler(logObj);
    }
  };
}

// Batching transport for performance
function createBatchTransport(sender: (batch: any[]) => void, batchSize = 10) {
  let batch: any[] = [];
  
  return (logObj: any) => {
    batch.push(logObj);
    if (batch.length >= batchSize) {
      sender([...batch]);
      batch = [];
    }
  };
}

const logger = new Logger({ name: "AdvancedApp" });

// Use advanced transports
logger.attachTransport(createHttpTransport("https://logs.example.com/api"));
logger.attachTransport(createErrorOnlyTransport((logObj) => {
  alertingSystem.send(logObj);
}));
logger.attachTransport(createBatchTransport((batch) => {
  analytics.sendBatch(batch);
}, 5));

Transport Inheritance

Sub-loggers inherit transports from their parent loggers, and additional transports can be added.

/**
 * Sub-loggers inherit parent transports
 */
getSubLogger(settings?: ISettingsParam<LogObj>, logObj?: LogObj): Logger<LogObj>;

Usage Examples:

import { Logger } from "tslog";

// Parent logger with transports
const parentLogger = new Logger({ name: "ParentApp" });
parentLogger.attachTransport((logObj) => {
  console.log("Parent transport:", logObj._meta.name);
});

// Child logger inherits parent transports
const childLogger = parentLogger.getSubLogger({ name: "ChildModule" });

// Child logger can add its own transports
childLogger.attachTransport((logObj) => {
  console.log("Child transport:", logObj._meta.name);
});

// This log will go to both parent and child transports
childLogger.info("Child logger message");
// Output:
// Parent transport: ChildModule
// Child transport: ChildModule

Common Transport Patterns

File Transport

import * as fs from "fs";
import * as path from "path";

function createFileTransport(filePath: string) {
  return (logObj: any) => {
    const logLine = JSON.stringify(logObj) + "\n";
    fs.appendFileSync(filePath, logLine);
  };
}

Syslog Transport

function createSyslogTransport() {
  return (logObj: any) => {
    const syslogLevel = mapLogLevelToSyslog(logObj._meta.logLevelId);
    const message = `<${syslogLevel}>${JSON.stringify(logObj)}`;
    // Send to syslog daemon
    sendToSyslog(message);
  };
}

Database Transport

function createDatabaseTransport(database: any) {
  return async (logObj: any) => {
    await database.collection('logs').insertOne({
      timestamp: logObj._meta.date,
      level: logObj._meta.logLevelName,
      logger: logObj._meta.name,
      data: logObj,
    });
  };
}

Install with Tessl CLI

npx tessl i tessl/npm-tslog

docs

configuration.md

core-logging.md

index.md

transports.md

tile.json