*We're building a plugin for Obsidian called [Relay](https://system3.md/relay). Relay makes Obsidian real-time collaborative. We love Obsidian, and hope to make it a competitive tool in the workplace.*
*We use pocketbase as our auth backend, so I'm sharing some of the novel modifications we made to run it on fly.io.*
This middleware outputs server logs in Combined Log Format, enabling powerful analytics through GoAccess - an elegant tool that turns raw logs into real-time traffic visualizations and insights without requiring JavaScript injection or third-party services.
## The Middleware
```
func logMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
// Process the request
err := next(c)
// Get request and response details
req := c.Request()
res := c.Response()
// Get client IP
clientIP := c.RealIP()
// Get user identifier (- if not authenticated)
userIdentifier := "-"
// Get username (- if not authenticated)
username := "-"
// Format timestamp in apache format
timestamp := time.Now().Format("02/Jan/2006:15:04:05 -0700")
// Get request size
requestSize := req.Header.Get("Content-Length")
if requestSize == "" {
requestSize = "0"
}
// Format log entry in COMBINED format
// Format: %h %l %u [%t] "%r" %>s %b "%{Referer}i" "%{User-agent}i"
logEntry := fmt.Sprintf(`%s %s %s [%s] "%s %s %s" %d %s "%s" "%s"`,
clientIP,
userIdentifier,
username,
timestamp,
req.Method,
req.RequestURI,
req.Proto,
res.Status,
requestSize,
req.Referer(),
req.UserAgent(),
)
fmt.Printf("%s\n", logEntry)
return err
}
}
```
The middleware wraps your HTTP handlers to log each request, capturing key metrics like timestamp, method, path, status code, and client details. Just pipe these logs into GoAccess to transform this raw data into an interactive dashboard of traffic patterns, user behavior, and potential issues - all while maintaining complete control over your analytics data.
## Getting the GeoIP Database
1. Visit https://db-ip.com/db/download/ip-to-country-lite
2. Scroll down to "Free Download" and download the mmdb file (will be named something like `dbip-country-lite-2024-01.mmdb`)
3. Place it in the same directory as your goaccess.conf file
## GoAccess Configuration
```
# Log format - matches our middleware output
log-format COMBINED
# Time format - matches our UTC timestamp format
time-format %H:%M:%S
date-format %d/%b/%Y
# Output options
html-report-title Analytics
geoip-database dbip-country-lite-2024-11.mmdb
# UI Options
no-color false
no-progress false
no-parsing-spinner false
# Enable all panels
enable-panel VISITORS
enable-panel REQUESTS
enable-panel REQUESTS_STATIC
enable-panel NOT_FOUND
enable-panel HOSTS
enable-panel OS
enable-panel BROWSERS
enable-panel VISIT_TIMES
enable-panel VIRTUAL_HOSTS
enable-panel REFERRERS
enable-panel REFERRING_SITES
enable-panel KEYPHRASES
enable-panel GEO_LOCATION
enable-panel STATUS_CODES
```
## How to Run It
```
fly logs -c fly.toml --json | jq '.message' -r | goaccess -p goaccess.conf
```
This setup gives you:
- Real-time traffic visualization
- Geographic visitor distribution
- Most accessed endpoints
- Error rates and status codes
- Traffic patterns and peak times
- Browser and OS statistics
All without any client-side code or third-party services!