<commit_before>import * as getHosts from '../hosts/db'
import { watchContainer } from './containers'
import * as emitter from './emitter'
import docker from '../docker'

const hostState: { [id: number]: boolean } = {}

export default async function watchHosts() {
  const hosts = await getHosts.getAll()

  for (const host of hosts) {
    const isWatching = hostState[host.id]
    if (isWatching) {
      continue
    }

    const client = docker(host)
    const hostId = host.id
    const hostname = host.hostname
    client.getEvents({}, (err, stream: NodeJS.ReadableStream) => {
      if (err) {
        log.error(`[${hostname}] Failed to monitor host: ${err}`)
        return
      }

      log.info(`[${hostname}] Monitoring host`)
      hostState[hostId] = true
      stream.on('data', event => handleHostEvent(host, event))
    })
  }
}

function handleHostEvent(host: Concierge.Host, rawEvent: string) {
  const event: DockerEvent = JSON.parse(rawEvent)
  const id = (event.id || 'Host').slice(0, 10)
  const status = (event.status || 'unknown').toLowerCase()
  log.info(`[${host.hostname}:${id}] Emitted '${event.Type}:${event.Action}'`)

  emitter.host(host.hostname, event)

  const isStartEvent = status.toLowerCase() === 'start'
  const isContainer = id !== 'Host'
  if (isContainer && isStartEvent) {
    watchContainer(host, event.id)
  }
}

interface DockerEvent {
  Type: string
  Action: string<commit_msg>Gracefully handle non-JSON host events<commit_after>import * as getHosts from '../hosts/db'
import { watchContainer } from './containers'
import * as emitter from './emitter'
import docker from '../docker'

const hostState: { [id: number]: boolean } = {}

export default async function watchHosts() {
  const hosts = await getHosts.getAll()

  for (const host of hosts) {
    const isWatching = hostState[host.id]
    if (isWatching) {
      continue
    }

    const client = docker(host)
    const hostId = host.id
    const hostname = host.hostname
    client.getEvents({}, (err, stream: NodeJS.ReadableStream) => {
      if (err) {
        log.error(`[${hostname}] Failed to monitor host: ${err}`)
        return
      }

      log.info(`[${hostname}] Monitoring host`)
      hostState[hostId] = true
      stream.on('data', event => handleHostEvent(host, event))
    })
  }
}

function handleHostEvent(host: Concierge.Host, rawEvent: string) {
  const event = parseEvent(rawEvent)
  if (!event) {
    return
  }

  const id = (event.id || 'Host').slice(0, 10)
  const status = (event.status || 'unknown').toLowerCase()
  log.info(`[${host.hostname}:${id}] Emitted '${event.Type}:${event.Action}'`)

  emitter.host(host.hostname, event)

  const isStartEvent = status.toLowerCase() === 'start'
  const isContainer = id !== 'Host'
  if (isContainer && isStartEvent) {
    watchContainer(host, event.id)
  }
}

function parseEvent(rawEvent: string) {
  try {
    const event: DockerEvent = JSON.parse(rawEvent)
    return event
  } catch (ex) {
    log.warn(`Failed to parse Host Event`)
    log.debug(rawEvent)
    return undefined
  }
}

interface DockerEvent {
  Type: string
  Action: string
{'fraction_non_alphanumeric': 0.14674783723165652, 'fraction_numerical': 0.0019224607497596924, 'mean_word_length': 3.428368794326241, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6777917', 'n_tokens_mistral': 1004, 'n_tokens_neox': 984, 'n_words': 257}