# LogViewerModel

Source: /tuil/docs/reference/packages/log-viewer/api/log-viewer-model
Locale: en

class exported by @mwillbanks/tuil-log-viewer.



{/* Generated by tooling/docs/generate-reference.ts. */}

## class [#class]

Public class exported by `@mwillbanks/tuil-log-viewer`.

```ts
export class LogViewerModel {
  readonly #pipeline: LogPipeline;
  readonly #ownsQueryEditor: boolean;
  readonly scroll: ScrollAreaState;
  readonly queryEditor: EditorSession;
  #records: readonly LogRecord[] = [];
  #selected = 0;
  #query = "";
  #theme: LogTheme;
  readonly #observers = new Set<() => void>();
  readonly #unsubscribeBuffer: () => void;
  #revision = 0;

  constructor(pipeline: LogPipeline, options: LogViewerModelOptions = {}) {
    this.#pipeline = pipeline;
    this.#records = pipeline.buffer.records();
    this.scroll = new ScrollAreaState({
      id: options.id ?? "log-viewer",
      viewport: {
        width: options.width ?? 100,
        height: options.height ?? 20,
      },
      extent: {
        width: options.width ?? 100,
        height: this.#records.length,
      },
      sticky: { bottom: true },
      followFocus: true,
    });
    if (!options.queryEditor) {
      throw new Error(
        "LogViewerModel requires a queryEditor from the application editor provider registry",
      );
    }
    if (!options.queryEditorOwnership) {
      throw new Error(
        "LogViewerModel requires explicit borrowed or owned queryEditor ownership",
      );
    }
    this.queryEditor = options.queryEditor;
    this.#ownsQueryEditor = options.queryEditorOwnership === "owned";
    this.#selected = Math.max(0, this.#records.length - 1);
    this.scroll.move("bottom");
    this.#theme = createLogTheme(options.theme ?? "comfortable");
    this.#unsubscribeBuffer = pipeline.buffer.subscribe(() => {
      if (!pipeline.buffer.statistics().paused) this.refresh();
      else this.#notify();
    });
  }

  refresh(): void {
    this.#records = this.#query
      ? this.#pipeline.filter(this.#query)
      : this.#pipeline.buffer.records();
    this.scroll.setExtent({
      width: this.scroll.snapshot().extent.width,
      height: this.#records.length,
    });
    this.#selected = Math.max(
      0,
      Math.min(this.#records.length - 1, this.#selected),
    );
    this.#notify();
  }

  setQuery(source: string): readonly string[] {
    const compiled = compileLogQuery(source);
    this.#query = source;
    this.#pipeline.query(source);
    this.queryEditor.dispatch({
      changes: [
        {
          range: {
            anchor: { line: 0, column: 0 },
            head: {
              line: 0,
              column: this.queryEditor.serialize().length,
            },
          },
          insert: source,
        },
      ],
    });
    this.refresh();
    return Object.freeze(compiled.diagnostics.map((item) => item.message));
  }

  select(index: number): void {
    this.#selected = Math.max(0, Math.min(this.#records.length - 1, index));
    this.scroll.scrollIntoView({
      x: 0,
      y: this.#selected,
      width: 1,
      height: 1,
    });
    this.#notify();
  }

  move(delta: number): void {
    this.select(this.#selected + delta);
  }

  pause(): void {
    this.#pipeline.buffer.pause();
  }

  resume(): void {
    this.#pipeline.buffer.resume();
  }

  setTheme(variant: LogThemeVariant): void {
    this.#theme = createLogTheme(variant);
    this.#notify();
  }

  subscribe(observer: () => void): () => void {
    this.#observers.add(observer);
    return () => this.#observers.delete(observer);
  }

  revision(): number {
    return this.#revision;
  }

  snapshot(): {
    readonly rows: readonly LogRowView[];
    readonly selected?: LogRecord;
    readonly live: boolean;
    readonly theme: LogTheme;
    readonly dropped: number;
    readonly sampled: number;
    readonly rateLimited: number;
    readonly total: number;
  } {
    const viewport = this.scroll.snapshot();
    const statistics = this.#pipeline.buffer.statistics();
    const start = viewport.position.y;
    const end = start + viewport.viewport.height;
    return Object.freeze({
      rows: Object.freeze(
        this.#records
          .slice(start, end)
          .map((record, offset) =>
            LogRow(record, start + offset, start + offset === this.#selected),
          ),
      ),
      selected: this.#records[this.#selected],
      live: !statistics.paused,
      theme: this.#theme,
      dropped: statistics.dropped,
      sampled: statistics.sampled,
      rateLimited: statistics.rateLimited,
      total: this.#records.length,
    });
  }

  export(format: "jsonl" | "text" = "jsonl"): string {
    return this.#pipeline.export(this.#records, format);
  }

  async copy(
    clipboard: EditorClipboardAdapter,
    format: "jsonl" | "text" = "text",
  ): Promise<string> {
    const value = this.export(format);
    await clipboard.write(value);
    return value;
  }

  dispose(): void {
    this.#unsubscribeBuffer();
    this.#observers.clear();
    if (this.#ownsQueryEditor) this.queryEditor.dispose();
  }

  #notify(): void {
    this.#revision += 1;
    for (const observer of this.#observers) observer();
  }
}
```

## Members [#members]

| Member               | Type                                                                                                                                                                                                                                                   | Required | Description                                                                                                                                                                                                                                                                                     | Related types                                                                                                                                                                                         |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `#pipeline`          | `LogPipeline`                                                                                                                                                                                                                                          | Yes      | The `#pipeline` member uses the `LogPipeline` contract.                                                                                                                                                                                                                                         | [`LogPipeline`](/tuil/docs/reference/packages/logging/api/log-pipeline)                                                                                                                                    |
| `#ownsQueryEditor`   | `boolean`                                                                                                                                                                                                                                              | Yes      | The `#ownsQueryEditor` member uses the `boolean` contract.                                                                                                                                                                                                                                      | —                                                                                                                                                                                                     |
| `scroll`             | `ScrollAreaState`                                                                                                                                                                                                                                      | Yes      | The `scroll` member uses the `ScrollAreaState` contract.                                                                                                                                                                                                                                        | [`ScrollAreaState`](/tuil/docs/reference/packages/scroll/api/scroll-area-state)                                                                                                                            |
| `queryEditor`        | `EditorSession`                                                                                                                                                                                                                                        | Yes      | The `queryEditor` member uses the `EditorSession` contract.                                                                                                                                                                                                                                     | [`EditorSession`](/tuil/docs/reference/packages/editor/api/editor-session)                                                                                                                                 |
| `#records`           | `readonly LogRecord[]`                                                                                                                                                                                                                                 | Yes      | The `#records` member uses the `readonly LogRecord[]` contract.                                                                                                                                                                                                                                 | [`LogRecord`](/tuil/docs/reference/packages/logging/api/log-record)                                                                                                                                        |
| `#selected`          | `number`                                                                                                                                                                                                                                               | Yes      | The `#selected` member uses the `number` contract.                                                                                                                                                                                                                                              | —                                                                                                                                                                                                     |
| `#query`             | `string`                                                                                                                                                                                                                                               | Yes      | The `#query` member uses the `string` contract.                                                                                                                                                                                                                                                 | —                                                                                                                                                                                                     |
| `#theme`             | `LogTheme`                                                                                                                                                                                                                                             | Yes      | The `#theme` member uses the `LogTheme` contract.                                                                                                                                                                                                                                               | [`LogTheme`](/tuil/docs/reference/packages/log-viewer/api/log-theme)                                                                                                                                       |
| `#observers`         | `Set<() => void>`                                                                                                                                                                                                                                      | Yes      | The `#observers` member uses the `Set<() => void>` contract.                                                                                                                                                                                                                                    | —                                                                                                                                                                                                     |
| `#unsubscribeBuffer` | `() => void`                                                                                                                                                                                                                                           | Yes      | The `#unsubscribeBuffer` member uses the `() => void` contract.                                                                                                                                                                                                                                 | —                                                                                                                                                                                                     |
| `#revision`          | `number`                                                                                                                                                                                                                                               | Yes      | The `#revision` member uses the `number` contract.                                                                                                                                                                                                                                              | —                                                                                                                                                                                                     |
| `__constructor`      | `any`                                                                                                                                                                                                                                                  | Yes      | The `__constructor` member uses the `any` contract.                                                                                                                                                                                                                                             | —                                                                                                                                                                                                     |
| `refresh`            | `() => void`                                                                                                                                                                                                                                           | Yes      | The `refresh` member uses the `() => void` contract.                                                                                                                                                                                                                                            | —                                                                                                                                                                                                     |
| `setQuery`           | `(source: string) => readonly string[]`                                                                                                                                                                                                                | Yes      | The `setQuery` member uses the `(source: string) => readonly string[]` contract.                                                                                                                                                                                                                | —                                                                                                                                                                                                     |
| `select`             | `(index: number) => void`                                                                                                                                                                                                                              | Yes      | The `select` member uses the `(index: number) => void` contract.                                                                                                                                                                                                                                | —                                                                                                                                                                                                     |
| `move`               | `(delta: number) => void`                                                                                                                                                                                                                              | Yes      | The `move` member uses the `(delta: number) => void` contract.                                                                                                                                                                                                                                  | —                                                                                                                                                                                                     |
| `pause`              | `() => void`                                                                                                                                                                                                                                           | Yes      | The `pause` member uses the `() => void` contract.                                                                                                                                                                                                                                              | —                                                                                                                                                                                                     |
| `resume`             | `() => void`                                                                                                                                                                                                                                           | Yes      | The `resume` member uses the `() => void` contract.                                                                                                                                                                                                                                             | —                                                                                                                                                                                                     |
| `setTheme`           | `(variant: LogThemeVariant) => void`                                                                                                                                                                                                                   | Yes      | The `setTheme` member uses the `(variant: LogThemeVariant) => void` contract.                                                                                                                                                                                                                   | [`LogThemeVariant`](/tuil/docs/reference/packages/log-viewer/api/log-theme-variant)                                                                                                                        |
| `subscribe`          | `(observer: () => void) => () => void`                                                                                                                                                                                                                 | Yes      | The `subscribe` member uses the `(observer: () => void) => () => void` contract.                                                                                                                                                                                                                | —                                                                                                                                                                                                     |
| `revision`           | `() => number`                                                                                                                                                                                                                                         | Yes      | The `revision` member uses the `() => number` contract.                                                                                                                                                                                                                                         | —                                                                                                                                                                                                     |
| `snapshot`           | `() => &#123; readonly rows: readonly LogRowView[]; readonly selected?: LogRecord; readonly live: boolean; readonly theme: LogTheme; readonly dropped: number; readonly sampled: number; readonly rateLimited: number; readonly total: number; &#125;` | Yes      | The `snapshot` member uses the `() => &#123; readonly rows: readonly LogRowView[]; readonly selected?: LogRecord; readonly live: boolean; readonly theme: LogTheme; readonly dropped: number; readonly sampled: number; readonly rateLimited: number; readonly total: number; &#125;` contract. | [`LogRecord`](/tuil/docs/reference/packages/logging/api/log-record), [`LogRowView`](/tuil/docs/reference/packages/log-viewer/api/log-row-view), [`LogTheme`](/tuil/docs/reference/packages/log-viewer/api/log-theme) |
| `export`             | `(format?: "jsonl" \| "text") => string`                                                                                                                                                                                                               | Yes      | The `export` member uses the `(format?: "jsonl" \| "text") => string` contract.                                                                                                                                                                                                                 | —                                                                                                                                                                                                     |
| `copy`               | `(clipboard: EditorClipboardAdapter, format?: "jsonl" \| "text") => Promise<string>`                                                                                                                                                                   | Yes      | The `copy` member uses the `(clipboard: EditorClipboardAdapter, format?: "jsonl" \| "text") => Promise<string>` contract.                                                                                                                                                                       | —                                                                                                                                                                                                     |
| `dispose`            | `() => void`                                                                                                                                                                                                                                           | Yes      | The `dispose` member uses the `() => void` contract.                                                                                                                                                                                                                                            | —                                                                                                                                                                                                     |
| `#notify`            | `() => void`                                                                                                                                                                                                                                           | Yes      | The `#notify` member uses the `() => void` contract.                                                                                                                                                                                                                                            | —                                                                                                                                                                                                     |

## Parameters [#parameters]

This declaration has no public members.

## Returns [#returns]

This declaration does not return a value.

## Throws [#throws]

No thrown errors are documented for this declaration.

## Related types [#related-types]

* [`LogRow`](/tuil/docs/reference/packages/log-viewer/api/log-row)
* [`LogRowView`](/tuil/docs/reference/packages/log-viewer/api/log-row-view)
* [`LogTheme`](/tuil/docs/reference/packages/log-viewer/api/log-theme)
* [`LogThemeVariant`](/tuil/docs/reference/packages/log-viewer/api/log-theme-variant)
* [`LogViewerModelOptions`](/tuil/docs/reference/packages/log-viewer/api/log-viewer-model-options)

## Source [#source]

[View the secondary source reference](https://github.com/mwillbanks/tuil/blob/main/packages/log-viewer/src/index.tsx)

## Package [#package]

[@mwillbanks/tuil-log-viewer](/tuil/docs/reference/packages/log-viewer)
