@livy/contracts v1.1.2
@livy/contracts
This package (primarily) contains types representing the core concepts of the Livy logger. Those are especially useful when you're building Livy components using TypeScript. For this reason, code blocks in this documentation are written in TypeScript.
Table of Contents:
LogLevelLogRecordLoggerInterfaceHandlerInterfaceResettableInterfaceFormattableHandlerInterfaceProcessableHandlerInterfaceClosableHandlerInterfaceFormatterInterfaceProcessorInterface/ProcessorFunction
LogLevel
This module contains the available log levels and their corresponding severities:
LogLevelis a type representing any valid RFC 5424 log level whilelogLevelsis an array containing all those level strings, sorted from least (debug) to most serious (emergency):import { LogLevel, logLevels } from '@livy/contracts' function printLevel(level: LogLevel) { if (!logLevels.includes(level)) { throw Error('Invalidlog log level') } console.log(level) }The
SeverityLeveltype represents log level severity as an integer from0through7. TheSeverityMapobject maps log levels to their corresponding severity (debug → 7, ..., emergency → 0):import { LogLevel, SeverityMap } from '@livy/contracts' /** * Sort a list of log levels by severity ("debug" first, "emergency" last) */ function sortBySeverity(levels: LogLevel[]) { return [...levels].sort( (levelA, levelB) => SeverityMap[levelB] - SeverityMap[levelA] ) }
LogRecord
Exposes the LogRecord interface which describes the structure of a Livy log record. This is useful for writing, for example, a custom formatter in TypeScript:
import { FormatterInterface } from '@livy/contracts'
import { LogRecord } from '@livy/contracts'
class QueryStringFormatter implements FormatterInterface {
/*
* Format properties of a record as level=debug&severity=7&message=...
*/
public format(record: LogRecord) {
return new URLSearchParams(Object.entries(record)).toString()
}
/*
* Format properties of multiple records as level[]=debug&severity[]=7&message[]=...
*/
public formatBatch(records: LogRecord[]) {
return new URLSearchParams(
records.reduce(
(carry, record) => [
...carry,
...Object.entries(record).map(([key, value]) => [`${key}[]`, value])
],
[]
)
)
.toString()
.replace(/%5B%5D/g, '[]')
}
}LoggerInterface
Describes the abstract structure of a Livy logger instance (LoggerInterface) as well as two variations, AsyncLoggerInterface and SyncLoggerInterface, which extend LoggerInterface and additionally define concrete return types (instead of unknown) for the log methods.
import {
LoggerInterface,
AsyncLoggerInterface,
SyncLoggerInterface
} from '@livy/contracts'HandlerInterface
Describes the minimum viable structure of a Livy handler as HandlerInterface. Additionally, a SyncHandlerInterface is provided which represents a handler that has synchronous logging methods in addition to the asynchronous ones.
import { HandlerInterface, SyncHandlerInterface } from '@livy/contracts'ResettableInterface
Describes the structure of a resettable handler or processor — a component able to reset its internal state (e.g. the ArrayHandler which can clear its own buffer).
import { ResettableInterface } from '@livy/contracts'Handlers implementing this interface expose a reset method to trigger the reset:
const resettableHandler = new SomeResettableHandler()
resettableHandler.reset()Calling this method on a handler should not only reset its own state but also the state of all components attached to it (e.g. processors or wrapped handlers).
FormattableHandlerInterface
Describes the structure of a handler which has a configurable formatter.
import { FormattableHandlerInterface } from '@livy/contracts'ProcessableHandlerInterface
Describes the structure of a handler with support for processors.
import { ProcessableHandlerInterface } from '@livy/contracts'Handlers implementing this interface expose a Set of processors as their processors property:
const processableHandler = new SomeProcessableHandler()
processableHandler.processors
.add(new SomeProcessor())
.add(new OtherProcessor())ClosableHandlerInterface
Describes the structure of a handler which wants to do cleanup tasks when the process exits.
If you want to implement such a handler, please be aware that there is often no spare time left when the close() method is invoked (because it is triggered when the process exits/the web page is left), i.e. asynchronous cleanup actions usually won't work.
import { ClosableHandlerInterface } from '@livy/contracts'FormatterInterface
Describes the structure of a formatter.
import { FormatterInterface } from '@livy/contracts'ProcessorInterface/ProcessorFunction
Describes the structure of a processor.
import { ProcessorInterfaceOrFunction } from '@livy/contracts'A processor can either be stateless or stateful:
Stateless Processors
A stateless processor is just a bare function taking a log record and returning a log record.
import { ProcessorFunction } from '@livy/contracts'Stateful Processors
A stateful processor is a class with a process method. That method then does the job of accepting and returning a log record.
import { ProcessorInterface } from '@livy/contracts'Writing a processor in a stateful is usually done...
- ...if it needs to take options (which are usually taken to the processor's constructor).
- ...if it needs to retain state between several processed records.