Getting Started with Outrig

Outrig is a lightweight observability tool for Go programs, providing logs, goroutine monitoring, watches, and more, all with minimal setup.

How It Works

Outrig consists of two components:

  1. SDK: A lightweight Go package that integrates into your application. It provides hooks for capturing logs, goroutine state, runtime metrics, and more.

  2. Server: A local process running separately on your machine. It collects data from the SDK and presents it via a web UI.

Why Separate Components?

  • Minimal SDK footprint: Keeps your application lightweight—no embedded UI or unnecessary dependencies.
  • Independent data storage: View and compare logs and metrics even after your app exits or across multiple runs.
  • Improved security: Your app doesn't expose any ports or require a built-in web server.
  • Optimized performance: When disconnected, the SDK enters standby mode, suspends collection, and performs only a brief periodic check for reconnection (for virtually zero overhead).

Installing Outrig

Outrig supports MacOS and Linux (x86_64 and ARM64). On macOS, it's distributed as a system tray application that manages the Outrig server. On Linux, it's distributed as a single binary with no external dependencies.

MacOS

Install the Outrig System Tray Application via Homebrew Cask:

brew install --cask outrigdev/outrig/outrig

This installs a system tray application. After installation, you'll need to launch the Outrig application from your Applications folder or Spotlight to start the server.

Linux

Install directly without root privileges:

curl -sf https://outrig.run/install.sh | sh

This will install the Outrig server to ~/.local/bin.

Manual Downloads

Alternatively, you can download .dmg, .deb, .rpm, or .tar.gz packages directly from our GitHub releases page.

Running the Outrig Server

MacOS

The Outrig server is managed through the system tray application. After installation, launch the Outrig app from your Applications folder or Spotlight. The server will start automatically and you'll see the Outrig icon in your system tray.

Linux

To start the Outrig server, run the following command in your terminal:

outrig server

To stop the server, use Ctrl+C in the terminal where the server is running. Note that future versions will include systemd support to run the server as a background service.

Adding the SDK

The simplest way to add Outrig to your Go application is with a single import statement. Add this import to your main Go file:

import _ "github.com/outrigdev/outrig/autoinit"

That's it! The autoinit package automatically initializes Outrig with sensible defaults, enabling log capture, goroutine monitoring, and runtime stats collection (e.g. memory usage, CPU usage, and basic application info).

Manual Initialization (Advanced)

For more control over configuration, you can manually initialize Outrig:

package main

import "github.com/outrigdev/outrig"

func main() {
    // Initialize Outrig with your application name
	cfg := outrig.DefaultConfig()
	// Customize the configuration as needed
    outrig.Init("your-app-name", cfg)

    // Optionally signal graceful shutdown
    defer outrig.AppDone()
    
    // Your application code here...
}

For advanced configuration options, see the Go Docs and Config Struct definition.

Adding watches

Watches enable real-time monitoring of values in your Go application. Outrig provides several methods for adding watches through the Watch type. Values are collected automatically every second (except for push-based watches).

Creating a Watch

All watches start by creating a new watch instance. The Watch API supports method chaining, allowing you to configure tags, formatters, and polling methods in a fluent style:

// Basic watch
outrig.NewWatch("watch-name").PollFunc(getValue)

// Chained configuration
outrig.NewWatch("metric").
    WithTags("performance", "critical").
    AsJSON().
    PollFunc(getData)

Push Values

Push values directly from your code using a pusher:

pusher := outrig.NewWatch("counter").ForPush()
pusher.Push(42)
// Later...
pusher.Push(43)

Poll Values

Automatically poll values via a provided function:

outrig.NewWatch("counter").PollFunc(func() int {
    return myCounter
})

Thread-Safe Watching

Watch values with mutex protection:

var mu sync.Mutex
var counter int
outrig.NewWatch("sync-counter").PollSync(&mu, &counter)

Atomic Values

Directly watch atomic values:

var counter atomic.Int64
outrig.NewWatch("atomic-counter").PollAtomic(&counter)

Formatting and Tags

By default, Outrig formats values as JSON if the type supports JSON marshaling, otherwise it falls back to Go's %#v format. You can use formatters to override this behavior.

Watches can be configured with different formatters and tags. The canonical order is: NewWatch(name).WithTags(...).AsFormatter().PollMethod():

// Default formatting (JSON if available, %#v fallback)
outrig.NewWatch("data").PollFunc(getData)

// Force JSON formatting
outrig.NewWatch("data").
    WithTags("api", "response").
    AsJSON().
    PollFunc(getData)

// Force Go's fmt package (%#v)
outrig.NewWatch("status").
    AsGoFmt().
    PollFunc(getStatus)

// Force String() method
outrig.NewWatch("object").
    AsStringer().
    PollFunc(getObject)

// Use as a counter (incremental values)
outrig.NewWatch("requests").
    WithTags("performance").
    AsCounter().
    PollFunc(getRequestCount)

GoRoutine Monitoring

Outrig automatically dumps your goroutine stack traces every second for easy search/viewing. You can optionally name your goroutines for easier inspecting.

By using the Go method, outrig will also automatically catch panics (and log them) preventing your application from crashing, and it will capture more exact timing information about goroutine start/stop times.

outrig.Go("worker-pool-1").WithTags("worker").Run(func() {
    // Goroutine code...
})

Searching

Outrig provides powerful, typeahead search capabilities that update results instantly as you type, enabling quick filtering of logs, watches, and goroutines.

Advanced Search Operators

  • Exact Match: Use double quotes for exact phrase matching or to search for special characters.

    "timeout error"
    
  • Case-Sensitive Match: Use single quotes for case-sensitive matching.

    'TimeoutError'
    
  • Fuzzy Search: Prefix a token with ~ for approximate matches.

    ~errror ~toc
    
  • Regular Expressions: Use / for regexp searches (use c/regexp/ for case-sensitive)

    /timeout.*error/ c/CaSe SENsitive/
    
  • Exclude Results: Prefix any term (raw, quoted, fuzzy, regexp) with - to exclude entries.

    -debug -"status: 200" -/[A-Z][0-9]+/
    
  • Tags: Search for tags (e.g., #bug, #feature) using #. Because Outrig is a type-ahead search it finds all tags that start with the provided tag. So #foo will match #foobar, #foo, and #foobarbaz. To force an exact match use #tag/ (with a trailing slash).

    #foobar
    
  • Field-specific Searches: Target specific fields using $.

    • Logs: msg, source, linenum
    • Goroutines: goid, name, stack, state
    • Watches: name, type, val
    $source:main.go $goid:1234 $type:string
    
  • Grouping: Use parentheses () to group search terms.

    (error | panic) -debug
    
  • Combined Searches: Combine searches using | (OR) and spaces (AND).

    timeout | $source:db.go -debug
    

The search is designed with type-ahead semantics in mind. So, incomplete quotes, parentheses, and other operators will work.