git.iko.soy/parseable-macos
on 3988312 help sign in
parseable-macos/README.md
151 lines 6.7 kB history raw
1# Parseable Viewer
3A native macOS log viewer for [Parseable](https://www.parseable.com/), built with Swift and SwiftUI.
5Browse log streams, run SQL queries, tail logs in real time, and inspect server configuration — all from a lightweight desktop app with zero external dependencies.
7## Features
9- **SQL Query Editor** — Write and execute SQL queries against any log stream with configurable time ranges (presets or custom), result filtering, column sorting, and query history
10- **Live Tail** — Stream logs in near-real-time via HTTP polling with automatic deduplication, pause/resume, and a configurable entry buffer
11- **Stream Management** — List, create, and delete log streams; view schema, ingestion stats, storage usage, retention policies, and partitioning config
12- **Multiple Connections** — Save and switch between Parseable server connections with Keychain-backed password storage
13- **Export** — Export query results as CSV or JSON via the system save dialog
14- **Saved Queries** — Bookmark frequently-used SQL queries per stream for quick access from the sidebar
15- **Alerts & Users** — View configured alert rules and user accounts on the connected server
16- **Server Info** — Health status, version, deployment mode, storage backend, and update availability at a glance
18## Install
20```bash
21brew install ilyakooo0/tap/parseable-viewer
22```
24## Requirements
26- macOS 14.0+ (Sonoma)
27- Xcode 16+
28- [XcodeGen](https://github.com/yonaskolb/XcodeGen)
30## Build from source
32```bash
33# Install XcodeGen (one-time)
34brew install xcodegen
36# Generate the Xcode project and build
37xcodegen generate
38xcodebuild -project ParseableViewer.xcodeproj \
39 -scheme ParseableViewer \
40 -configuration Release \
41 build
42```
44The built app is located at `build/Build/Products/Release/Parseable Viewer.app`.
46To run tests:
48```bash
49xcodebuild test \
50 -project ParseableViewer.xcodeproj \
51 -scheme ParseableViewer \
52 -configuration Debug \
53 -destination 'platform=macOS'
54```
56## CI
58GitHub Actions builds and tests on every push and PR via [`.github/workflows/build.yml`](.github/workflows/build.yml). The pipeline:
601. Builds for both `arm64` and `x86_64`
612. Runs tests on `arm64`
623. Creates a universal binary via `lipo`
634. On tagged releases (`v*`), creates a draft GitHub Release with all three zips
65## Architecture
67| Layer | Description |
68|-------|-------------|
69| **App** | `@main` entry point, `AppState` (central `@Observable` singleton injected via `.environment()`) |
70| **Models** | `Codable` data types — `JSONValue` (recursive enum for arbitrary JSON), `LogStream`, `ServerAbout`, `AlertConfig`, etc. |
71| **Services** | `ParseableClient` (stateless HTTP client, Basic Auth, `URLSession` async/await), `ConnectionStore` (UserDefaults + Keychain persistence) |
72| **ViewModels** | `QueryViewModel` (SQL execution, filtering, export, history), `LiveTailViewModel` (timer-based polling, deduplication) |
73| **Views** | SwiftUI views — `NavigationSplitView` sidebar + tabbed detail pane |
75### Key design decisions
77- **No external dependencies** — the app uses only Apple frameworks (`Foundation`, `SwiftUI`, `Network`, `Security`)
78- **Defensive decoding** — models use `try?` for optional API fields to tolerate version differences across Parseable releases
79- **Passwords in Keychain** — `ServerConnection` excludes `password` from its `Codable` conformance; the password is stored/loaded via `KeychainService` separately from the UserDefaults data
80- **Live tail via HTTP polling** — Parseable's native live tail uses gRPC Arrow Flight streaming; this app approximates it with a sliding time window and content-based deduplication (FNV-1a fingerprinting)
82### Parseable API endpoints used
84All under `/api/v1/`. Auth: `Authorization: Basic <base64(user:pass)>`.
86| Method | Path | Purpose |
87|--------|------|---------|
88| HEAD | `/liveness` | Health check |
89| GET | `/about` | Server version, mode, storage info |
90| GET | `/logstream` | List all streams |
91| PUT/DELETE | `/logstream/{name}` | Create/delete stream |
92| GET | `/logstream/{name}/schema` | Field names and types |
93| GET | `/logstream/{name}/stats` | Ingestion/storage statistics |
94| GET | `/logstream/{name}/info` | Creation time, partitioning config |
95| POST | `/query` | SQL query with time range |
96| GET | `/alerts` | Alert rules |
97| GET | `/logstream/{name}/retention` | Retention policy |
98| GET | `/user` | List users |
100## Project structure
102```
103ParseableViewer/
104 App/
105 ParseableViewerApp.swift # @main, window/menu setup
106 AppState.swift # Central observable: connections, streams, navigation
107 Models/
108 JSONValue.swift # Recursive JSON enum (null|bool|int|double|string|array|object)
109 LogStream.swift # Stream, schema, stats, info models
110 ServerInfo.swift # ServerAbout, RetentionConfig, UserInfo
111 AlertModels.swift # AlertConfig, AlertRule, AlertTarget
112 ServerConnection.swift # Connection model with Keychain integration
113 Services/
114 ParseableClient.swift # HTTP client + ParseableError
115 ConnectionStore.swift # UserDefaults persistence, SavedQuery store
116 KeychainService.swift # Keychain read/write/delete
117 ViewModels/
118 QueryViewModel.swift # Query execution, filtering, export, history
119 LiveTailViewModel.swift # Polling, deduplication, entry buffer
120 Views/
121 ContentView.swift # Root layout: sidebar + detail
122 SidebarView.swift # Stream list, saved queries, connection switching
123 QueryView.swift # SQL editor, time picker, results table
124 LiveTailView.swift # Real-time log streaming UI
125 StreamDetailView.swift # Schema, stats, retention for selected stream
126 LogTableView.swift # Sortable log record table with detail pane
127 LogDetailView.swift # Formatted + raw JSON record inspector
128 AlertsView.swift # Alert rule listing
129 UsersView.swift # User listing
130 ServerInfoView.swift # Server health, version, storage info
131 ConnectionSheet.swift # Add/edit/test connection dialog
132 TimeRangePicker.swift # Preset + custom date range selector
133 SettingsView.swift # Preferences: query defaults, live tail config
134 Resources/
135 Assets.xcassets # App icon, accent color
136```
138## Keyboard shortcuts
140| Shortcut | Action |
141|----------|--------|
142| `Cmd+Shift+N` | New connection |
143| `Cmd+R` | Refresh streams |
144| `Cmd+Enter` | Run query |
145| `Cmd+P` | Pause/resume live tail |
146| `Cmd+Delete` | Clear live tail entries |
147| `Cmd+Ctrl+S` | Toggle sidebar |
149## License
151See [LICENSE](LICENSE) for details.