2022-11-01 16:21:43 +00:00
|
|
|
# okit
|
|
|
|
|
|
|
|
Short for "observability kit", `okit` aims to provide an all-in-one solution to application observability.
|
|
|
|
|
2022-11-02 20:16:48 +00:00
|
|
|
## Why
|
2022-11-01 16:21:43 +00:00
|
|
|
|
|
|
|
Traditional approaches to observability treat logging, application metrics, and tracing as independent operations, with
|
|
|
|
independent data streams. In practice, these elements are more or less all the same, with some minor differences between
|
|
|
|
them. Developers often have to choose between logging a message, emitting a metric, or expanding a trace.
|
|
|
|
|
|
|
|
**Logging**
|
|
|
|
|
2022-11-02 20:16:48 +00:00
|
|
|
- Used by developers and operators to determine what issues an application may be facing.
|
|
|
|
- High cardinality data (errors, stack traces, user id / signature).
|
|
|
|
- Often sent to stdout/stderr and can optionally be captured by traditional logging solutions.
|
2022-11-01 16:21:43 +00:00
|
|
|
|
|
|
|
**Tracing**
|
|
|
|
|
2022-11-02 20:16:48 +00:00
|
|
|
- Used by developers and operators to troubleshoot performance issues across a set of distributed systems.
|
|
|
|
- Medium cardinality data (consistent structure, high variability in tag values)
|
|
|
|
- Typically available in real-time to assess product performance.
|
2022-11-01 16:21:43 +00:00
|
|
|
|
|
|
|
**Metrics**
|
|
|
|
|
2022-11-02 20:16:48 +00:00
|
|
|
- Used by developers and product managers to determine details about how their product is doing.
|
|
|
|
- Medium/High cardinality data (user id / signature, other metadata fields).
|
|
|
|
- Typically available in real-time to assess user experience / feature performance.
|
2022-11-01 16:21:43 +00:00
|
|
|
|
2022-11-06 17:59:39 +00:00
|
|
|
In addition to the complexity that each of these solutions bring with them, you often need to import a custom library
|
|
|
|
for each, and thus increase your dependency footprint.
|
|
|
|
|
2022-11-02 20:16:48 +00:00
|
|
|
## Usage
|
|
|
|
|
|
|
|
### Basic
|
2022-11-01 16:21:43 +00:00
|
|
|
|
2022-11-06 17:59:39 +00:00
|
|
|
Basic usage for `okit` is fairly straight forward. You can create dedicated client, use the default, or even replace the
|
|
|
|
default. The example below demonstrates how to use the default client.
|
|
|
|
|
2022-11-01 16:21:43 +00:00
|
|
|
```go
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
|
|
|
"go.pitz.tech/okit"
|
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
2022-11-02 20:16:48 +00:00
|
|
|
var tags []okit.Tag
|
2022-11-01 16:21:43 +00:00
|
|
|
|
|
|
|
// Metric emission
|
2022-11-02 20:16:48 +00:00
|
|
|
okit.Observe("temperature_c", 20.9, tags...)
|
2022-11-01 16:21:43 +00:00
|
|
|
|
|
|
|
// Multi-dimensional events
|
2022-11-02 20:16:48 +00:00
|
|
|
okit.Emit("user_signup", tags...)
|
2022-11-01 16:21:43 +00:00
|
|
|
|
|
|
|
// Tracing
|
2022-11-02 20:16:48 +00:00
|
|
|
ctx, done := okit.Trace(context.Background(), tags...)
|
2022-11-01 16:21:43 +00:00
|
|
|
defer done()
|
2022-11-02 20:16:48 +00:00
|
|
|
_ = ctx.Err() // not needed, removes unused error
|
2022-11-01 16:21:43 +00:00
|
|
|
|
|
|
|
// Logging
|
2022-11-02 20:16:48 +00:00
|
|
|
okit.Debug("a message used for debugging", tags...)
|
|
|
|
okit.Info("an informational message for the user", tags...)
|
|
|
|
okit.Warn("a warning indicating an issue with the system", tags...)
|
|
|
|
okit.Error("the system encountered an error", tags...)
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### HTTP
|
|
|
|
|
|
|
|
`okit` comes with built-in functionality to make it easy to trace HTTP operations.
|
2022-11-01 16:21:43 +00:00
|
|
|
|
2022-11-02 20:16:48 +00:00
|
|
|
```go
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
|
|
|
|
okithttp "go.pitz.tech/okit/http"
|
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
// Instrument HTTP Clients
|
|
|
|
okithttp.InstrumentClient(http.DefaultClient)
|
|
|
|
|
|
|
|
mux := http.NewServeMux()
|
2022-11-06 17:59:39 +00:00
|
|
|
|
|
|
|
{ // Add reporting endpoints
|
|
|
|
endpoint := okithttp.NewEndpoint()
|
|
|
|
mux.HandleFunc("/health", endpoint.Health)
|
|
|
|
mux.HandleFunc("/metrics", endpoint.Metrics)
|
|
|
|
mux.HandleFunc("/trace", endpoint.Trace)
|
|
|
|
}
|
2022-11-02 20:16:48 +00:00
|
|
|
|
|
|
|
// Instrument HTTP Handlers
|
|
|
|
handler := okithttp.InstrumentHandler(mux)
|
|
|
|
err := http.ListenAndServe("0.0.0.0:8080", handler)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2022-11-01 16:21:43 +00:00
|
|
|
}
|
|
|
|
```
|
2022-11-02 20:16:48 +00:00
|
|
|
|
2022-11-06 17:59:39 +00:00
|
|
|
## Implementation
|
|
|
|
|
|
|
|
### Wire Protocol
|
|
|
|
|
|
|
|
TBD
|
|
|
|
|
|
|
|
### Tracing
|
|
|
|
|
|
|
|
Because `okit` aims at providing an all-in-one solution, tracing not only produces spec compliant traces for ingestion
|
|
|
|
into remote systems but also produces bookend log events for developers and operators.
|
|
|
|
|
|
|
|
### Logging
|
|
|
|
|
|
|
|
Logging follows a fairly standard implementation. It allows messages to be logged at different levels including `debug`,
|
|
|
|
`info`, `warn`, and `error`. A fifth, `trace` level is also available that allows tracing bookend events to be enabled
|
|
|
|
disabled. Logging output can be written as text or as JSON.
|
|
|
|
|
|
|
|
### Metrics
|
|
|
|
|
|
|
|
Metrics are implemented using an observation based approach. Results are recorded and stored locally for administrators
|
|
|
|
to be able to query.
|
|
|
|
|
|
|
|
### Events
|
|
|
|
|
|
|
|
Multi-dimensional events are a lot like metrics. The most common use case is when metrics have a statically coded value
|
|
|
|
of 1. For example, page views, checkout, and many other user-driven actions.
|