React LogViewer

repository·main·Indexed 41 days ago

https://github.com/melloware/react-logviewer

A high-performance React component for efficiently loading and viewing large remote text files (up to 100MB+). Version 6.5.5 supports ANSI color parsing, infinite scrolling, and multiple data sources including URLs, local text strings, WebSockets, and EventSource (SSE). It includes the LazyLog component for lazy loading and the ScrollFollow HOC for automatic bottom-scrolling functionality.

Tokens
10.8K
Snippets
41
Records
49
Agent score
49%

What's inside React LogViewer

  1. Customize styling for LazyLog

    main

    There are three primary ways to style the components:

    1. Using style and containerStyle props

    • Use the style prop on <LazyLog /> to affect the core container styles.
    • Use the containerStyle prop to affect the look or behavior of the scrollable region.

    2. Overriding defaultProps.style

    To avoid passing style objects repeatedly, you can override the defaultProps.style of internal components directly. For example, to change the color of all lines:

    import Line from "@melloware/react-logviewer/build/Line";
    
    Line.defaultProps.style = {
        color: "green",
    };

    Note: Overriding ANSI colors and styles is currently undocumented and may require inspecting source code.

    3. Using CSS stylesheets

    You can target the virtual list and its children using CSS classes. The main virtual list uses the react-lazylog class name. From there, you can target:

    • Individual line divs
    • Line number a tags
    • Line content span tags
  2. Use the LazyLog component

    main

    The LazyLog component is the core of the library. It loads and views remote text lazily and efficiently.

    Basic Usage

    Render LazyLog with a url prop pointing to your log file. By default, it expands to fill its container, so ensure the parent element has defined dimensions. You can also set fixed height and width props.

    Performance Modes

    • Standard Mode: For complete files or endpoints that can be downloaded all at once, use <LazyLog url="..." />. This offers better overall performance but has a longer upfront load time.
    • Streaming Mode: For streaming or chunked responses, use <LazyLog stream url="..." /> (setting the stream prop to true). This allows for quicker upfront rendering as content is decoded as it arrives.
    import React from "react";
    import { render } from "react-dom";
    import { LazyLog } from "@melloware/react-logviewer";
    
    // Standard usage
    render(<LazyLog url="http://example.log" />, document.getElementById("root"));
    
    // Streaming usage
    render(<LazyLog stream url="http://example.log" />, document.getElementById("root"));
  3. Use the ScrollFollow higher-order component

    main

    ScrollFollow is a higher-order component (HOC) designed to simplify toggling the "follow" functionality of a LazyLog component based on user scrolling behavior.

    It uses a render prop pattern. The render prop accepts a function that provides several control functions to manage the scroll state. These functions are passed into the child component (typically a LazyLog) to enable or disable automatic scrolling to the bottom of the logs.

    Render Prop Arguments

    The render function receives an object containing:

    • onScroll: A function to be passed to the log component to track scroll events.
    • follow: A boolean indicating if the component is currently in "follow" mode.
    • startFollowing: A function to trigger the follow mode.
    • stopFollowing: A function to stop the follow mode.
    import { LazyLog, ScrollFollow } from "@melloware/react-logviewer";
    
    const url = "https://example.com/logs";
    
    <div style={{ height: 500, width: 902 }}>
      <ScrollFollow
        startFollowing
        render={({ onScroll, follow, startFollowing, stopFollowing }) => (
          <LazyLog 
            extraLines={1} 
            enableSearch 
            url={url} 
            stream 
            onScroll={onScroll} 
            follow={follow} 
          />
        )}
      />
    </div>
  4. Use the ScrollFollow HOC to follow logs

    main

    The ScrollFollow higher-order component (HOC) simplifies toggling a LazyLog's "follow" functionality (automatically scrolling to the bottom) based on user scrolling behavior.

    Requirements:

    • ScrollFollow must be wrapped in an element that has a fixed height (e.g., a <div> with a specific height).
    • It uses a render prop pattern, providing follow (boolean) and onScroll (function) to the child component.

    To implement auto-following, pass the follow and onScroll props from the render function directly to your LazyLog component.

    import React from "react";
    import { render } from "react-dom";
    import { LazyLog, ScrollFollow } from "@melloware/react-logviewer";
    
    render(
        <div style={{ height: 500, width: 902 }}>
        <ScrollFollow
            startFollowing={true}
            render={({ follow, onScroll }) => (
                <LazyLog url="http://example.log" stream follow={follow} onScroll={onScroll} />
            )}
        />
        </div >,
        document.getElementById("root"),
    );
  5. Update LazyLog data externally using appendLines

    main

    If you set the external prop to true, the LazyLog component becomes a controlled-like component where you are responsible for feeding it data. You can use a ref to access the appendLines method to push new log entries into the view.

    1. Set external={true} on the <LazyLog /> component.
    2. Create a ref using useRef<LazyLog>(null).
    3. Call ref.current.appendLines(['new line 1', 'new line 2']) to update the log.
    import React, { useRef } from 'react';
    import LazyLog from '@melloware/react-logviewer';
    
    const MyLogManager = () => {
      const logRef = useRef<any>(null);
    
      const addLogs = () => {
        logRef.current?.appendLines(['New log entry at ' + new Date().toISOString()]);
      };
    
      return (
        <div>
          <button onClick={addLogs}>Add Log</button>
          <LazyLog external ref={logRef} />
        </div>
      );
    };
  6. Use the Line component for individual log lines

    main

    The Line component is used to render a single log line within the log viewer. It accepts props for controlling the visual height of the row, the line number to display, and the data object containing the log content (typically an object with a text property).

    <Line
      rowHeight={19}
      number={10}
      data={[{ text: 'Hello!' }]}
    />
  7. View logs using a WebSocket

    main

    To stream logs via WebSockets, use the <LazyLog /> component with the url prop, set the websocket boolean prop to true, and provide websocketOptions to handle connection lifecycle and message formatting.

    const url = 'wss://echo.websocket.org';
    let socket = null;
    
    <div>
      <button
        style={{ marginBottom: 8, background: '#eee' }}
        onClick={() => socket && socket.send(JSON.stringify({ message: '[taskcluster 2018-11-14 21:08:32.452Z] Worker Group: us-east-1' }))}>
        ping
      </button>
      <div style={{ height: 200, width: 902 }}>
      <LazyLog
        enableSearch
        url={url}
        websocket
        websocketOptions={{
          onOpen: (e, sock) => {
              socket = sock; sock.send(JSON.stringify({message: "Socket has be opened!"}))
            },
          formatMessage: e => JSON.parse(e).message,
        }}
      />
      </div
    </div>
  8. View logs from a text string

    main

    Use the <LazyLog /> component with the text prop to display logs provided as a local string instead of fetching them from a URL.

    const text = `
    Sed ut perspiciatis unde omnis iste natus error voluptatem...
    `;
    
    <div style={{ height: 300, width: 902 }}>
      <LazyLog extraLines={1} enableSearch text={text} caseInsensitive />
    </div>
  9. Format line parts with formatPart

    main

    You can transform the text of each part in a log line by providing a formatPart function to the LineContent component. The formatPart function receives the text of a part and should return the transformed text.

    <LineContent
      number={10}
      data={[{ text: 'Hello' }, { text: ' world!' }]}
      formatPart={text => text.replace('world', 'galaxy')}
    />