All files / modules/70-pipeline/components/LogsContent useLogsStream.ts

100% Statements 31/31
100% Branches 10/10
100% Functions 6/6
100% Lines 31/31

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93              33x 33x 33x   33x                                       33x 26x 26x 26x   26x   26x 10x 10x 10x     26x   4x 4x   4x   4x   4x         4x   4x 2x 1x       2x 1x 1x       4x   1x 1x             26x           5x        
/*
 * Copyright 2021 Harness Inc. All rights reserved.
 * Use of this source code is governed by the PolyForm Shield 1.0.0 license
 * that can be found in the licenses directory at the root of this repository, also available at
 * https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt.
 */
 
import React from 'react'
import { EventSourcePolyfill } from 'event-source-polyfill'
import { throttle } from 'lodash-es'
 
const STREAM_ENDPOINT = `${window.apiUrl || ''}/log-service/stream`
 
export interface StartStreamProps {
  queryParams: {
    key: string
    accountId: string
  }
  headers: Record<string, string>
  key: string
  throttleTime?: number
}
 
export interface UseLogsStreamReturn {
  log: string
  key: string
  startStream(props: StartStreamProps): void
  closeStream(): void
  getEventSource(): null | EventSource
}
 
export function useLogsStream(): UseLogsStreamReturn {
  const eventSource = React.useRef<null | EventSource>(null)
  const [log, setLog] = React.useState('')
  const [key, setKey] = React.useState('')
  // eslint-disable-next-line react-hooks/exhaustive-deps
  const throttledSetLog = React.useCallback(throttle(setLog, 2000), [setLog])
 
  const closeStream = React.useCallback(() => {
    eventSource.current?.close()
    throttledSetLog.cancel()
    eventSource.current = null
  }, [throttledSetLog])
 
  const startStream = React.useCallback(
    (props: StartStreamProps): void => {
      closeStream()
      setLog('')
 
      let cache = ''
 
      setKey(props.key)
 
      const currentEventSource: EventSource = new EventSourcePolyfill(
        `${STREAM_ENDPOINT}?accountID=${props.queryParams.accountId}&key=${props.queryParams.key}`,
        { headers: props.headers }
      )
 
      eventSource.current = currentEventSource
 
      currentEventSource.onmessage = (e: MessageEvent) => {
        if (e.type === 'error') {
          currentEventSource.close()
        }
 
        /* istanbul ignore else */
        if (e.data) {
          cache += `\n${e.data}`
          throttledSetLog(cache.trim())
        }
      }
 
      currentEventSource.onerror = (e: Event) => {
        /* istanbul ignore else */
        if (e.type === 'error') {
          currentEventSource.close()
        }
      }
    },
    [throttledSetLog, closeStream]
  )
 
  return {
    log,
    startStream,
    closeStream,
    key,
    getEventSource(): null | EventSource {
      return eventSource.current
    }
  }
}