Skip to content

Logs & Parsers

Runeya streams your process logs in real-time and allows transforming them via configurable JavaScript parsers.

Log Interface

In a service's log panel:

  • Real-time streaming via WebSocket
  • Filters: log level, free text, stream (stdout/stderr)
  • Clear the log buffer (doesn't affect active parsers)
  • Export displayed logs

Log Levels

Runeya automatically detects log levels via regex patterns:

LevelColorDetected Patterns
errorRedERROR, ERR, FATAL, CRIT
warnOrangeWARN, WARNING
infoWhiteINFO, LOG
debugGreyDEBUG, TRACE, VERBOSE

JavaScript Parsers

Parsers allow transforming each log line before display. They run in a pipeline: the output of one is the input of the next.

LogLine Interface

typescript
interface LogLine {
  raw: string       // Raw text (immutable)
  stream: string    // 'stdout' | 'stderr' (immutable)
  level: string     // Detected level (mutable)
  message: string   // Displayed message (mutable)
  hidden: boolean   // Hide the line (mutable)
  metadata: object  // Enriched data (mutable)
  json?: object     // If the line is valid JSON
}

Creating a Parser (v2)

javascript
// v2 signature: receives a LogLine, returns a LogLine
(line) => {
  // Automatic JSON parsing
  if (line.json) {
    return {
      ...line,
      level: line.json.level || line.level,
      message: line.json.message || line.raw,
      metadata: line.json,
    }
  }
  return line  // pass-through if not applicable
}

Practical Examples

Structured JSON parser (winston, pino...):

javascript
(line) => {
  if (!line.json) return line
  return {
    ...line,
    level: line.json.level ?? line.level,
    message: line.json.msg ?? line.json.message ?? line.raw,
    metadata: { service: line.json.service, trace: line.json.trace },
  }
}

Hide healthcheck lines:

javascript
(line) => {
  if (line.raw.includes('GET /health')) {
    return { ...line, hidden: true }
  }
  return line
}

Extract a custom timestamp:

javascript
(line) => {
  const match = line.raw.match(/^\[(\d{4}-\d{2}-\d{2}T[^\]]+)\] (.+)/)
  if (match) {
    return {
      ...line,
      message: match[2],
      metadata: { ...line.metadata, timestamp: match[1] },
    }
  }
  return line
}

Execution Pipeline

Raw line from process


   detectLevel()     ← automatic regex (step 0)


   Parser 1          ← in list order


   Parser 2


   ...


   Sanitisation      ← message truncated to 16KB, max 100 metadata keys


   UI Display

Security Constraints

Parsers run in a Node.js sandbox (vm.Script) with:

  • 100ms timeout per line
  • No access to require, import, eval
  • No access to filesystem or network
  • On error: the line passes to the next parser unchanged

Managing Parsers

Global parsers are defined in Settings → Log Parsers.

To attach them to a service:

  1. Open the service config → Logs tab
  2. Drag and drop parsers in the desired execution order
  3. Save

Order matters — a parser can modify a line before the next one receives it.

Released under the MIT License.