internal

package
v0.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 30, 2026 License: MIT Imports: 20 Imported by: 0

README

internal

A composition space for the oida package. Go closes internal/ to importers outside this module, so nothing here is API and nothing here needs a compatibility promise. The root package uses it to stay what a reader of the public API needs it to be: the tracer, the middleware, the mount and the instrumentation, rather than those plus the utilities and the component implementations they are built from.

What belongs here

A symbol moves when it stands on its own: a utility, or a component whose whole implementation is private.

  • Free functions and unexported types are the usual case. They are already unreachable from outside the module, so moving them changes no API.
  • A structure another package's type holds moves too, when the structure is generic rather than the thing that package exists to be. A ring buffer is a ring buffer wherever it lives.
  • A helper taking model.Options moves too. oida.Options is an alias of it, so the call site reads the same.
  • A component whose whole implementation is private moves with its tests: reading options out of the environment, the rate sampler, the response writer that records a status.

What does not

  • Anything taking or returning *Tracer, which would import the root package and close the cycle. That is what keeps serveTraced and the methods on Tracer where they are.
  • The implementation surface of a package. The front end's route handlers are what frontend is; moving them would move the package.

Layout

internal is one package unless a subpackage earns its own name, the way internal/ring does: a structure with a vocabulary of its own reads better as ring.New than as internal.NewRing, and a subpackage is what keeps the imports one way. The file is named after what it holds, remote_addr.go for RemoteAddr, so splint grouping passes and a reader finds a symbol by its filename.

Symbols here are exported for the rest of the module to call, and that export means nothing outside it. A standalone structure moves here even when a package's own type refers to it, which is how storage.memoryStorage came to hold a *ring.Ring: the ring is a buffer, not the retention driver.

Imports

internal imports model and storage, and internal/ring imports model alone. Nothing here imports oida, and nothing storage imports may import internal itself, which is why the ring has a package of its own.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ClockNow

func ClockNow(o model.Options) time.Time

ClockNow returns the current time from the configured clock.

func IgnoredPath

func IgnoredPath(o model.Options, path string) bool

IgnoredPath reports whether a request path is excluded from tracing. The debug front end is always excluded so it does not trace itself.

func InvalidOption

func InvalidOption(field string, reason string) error

InvalidOption formats a field level configuration error, wrapping model.ErrInvalidOptions so a caller can match on it.

func MemoryLimit

func MemoryLimit() uint64

MemoryLimit returns the smallest memory limit the process is subject to, or zero when none can be determined.

func NewRateSampler

func NewRateSampler(rate float64) model.Sampler

NewRateSampler returns a sampler tracing the given percentage of requests. A rate of 100 or more traces everything, a rate of 0 or less traces nothing.

func OptionsFromEnv

func OptionsFromEnv(opts *model.Options) error

OptionsFromEnv applies the OIDA_* environment to opts. A variable applies only where the code left the field at its NewOptions default, so authentication and tuning configured in code win over the environment, and a variable set to nothing leaves the default alone.

The variables and their defaults are the table in docs/guide-configuration.md, which is where a deployment reads them; keeping the list in one place is what keeps it true. Lists are comma separated. OIDA_SAMPLE_RATE out of [0,100] clamps to the nearest bound. OIDA_AUTH holds one username:password pair, hashed here so the options carry a bcrypt hash the way a configured deployment would.

func RemoteAddr

func RemoteAddr(r *http.Request) string

remoteAddr resolves the client IP of a request. It walks the forwarding chain from the Forwarded (RFC 7239) or X-Forwarded-For headers right to left and returns the first address outside the trusted LAN ranges: the hops a proxy appended are trustworthy, anything to their left is client input. When every hop is trusted, all-LAN traffic, the leftmost valid address is the client. Without a usable header the request's own RemoteAddr decides.

func RequestID

func RequestID(r *http.Request, opts model.Options) string

RequestID returns the identifier to record the request under.

func RoutePattern

func RoutePattern(r *http.Request, opts model.Options) string

RoutePattern returns the routed pattern of the request. A configured RouteFunc decides on its own, including when it returns nothing: a service mounting a catch-all knows that pattern is not worth grouping by, and the fallback would put it back. Without one, the pattern the router recorded on the request is used.

func SamplerFor

func SamplerFor(o model.Options) model.Sampler

SamplerFor returns the configured sampler, or a rate sampler for SampleRate.

func SymbolName

func SymbolName(in any) string

SymbolName returns a span name read from a function, a value or a string. The import path is trimmed to its last element, so the result is the package, type and function names joined with a dot: billing.UserStore.GetUsers.

func TraceOptionsFor

func TraceOptionsFor(o model.Options) model.TraceOptions

TraceOptionsFor returns the part of the configuration a recorded trace carries.

Types

type Broker

type Broker struct {
	// contains filtered or unexported fields
}

Broker fans out change notifications to live view subscribers. Sends are non blocking: a subscriber that is behind coalesces updates instead of slowing down the request that produced them.

func NewBroker

func NewBroker() *Broker

NewBroker returns an empty broker.

func (*Broker) Len

func (b *Broker) Len() int

Len returns the number of active subscribers.

func (*Broker) Notify

func (b *Broker) Notify()

Notify wakes every subscriber. Subscribers with a pending notification are skipped, so a burst of traces produces one redraw, not one per trace.

func (*Broker) Subscribe

func (b *Broker) Subscribe() (<-chan struct{}, func())

Subscribe returns a channel notified on every change, and a function that releases it. The release function is idempotent.

type RateSampler

type RateSampler struct {
	// contains filtered or unexported fields
}

RateSampler samples a fixed percentage of requests using a counter rather than randomness, so the decision sequence is deterministic and testable.

func (*RateSampler) Sample

func (s *RateSampler) Sample(*http.Request) bool

Sample implements model.Sampler.

type ResponseWriter

type ResponseWriter struct {
	http.ResponseWriter
	// contains filtered or unexported fields
}

ResponseWriter records the status and the number of bytes written while preserving the optional interfaces of the wrapped writer.

func NewResponseWriter

func NewResponseWriter(w http.ResponseWriter, trace *model.Trace) *ResponseWriter

NewResponseWriter wraps w to record what the handler answered with. The trace moves to StateWriting once, when the first byte or the status goes out. The wrapper comes from a pool; the middleware returns it with Release once the handler is done with it.

func (*ResponseWriter) Bytes

func (w *ResponseWriter) Bytes() int64

Bytes returns the number of bytes the handler wrote.

func (*ResponseWriter) Flush

func (w *ResponseWriter) Flush()

Flush forwards a flush to the wrapped writer.

func (*ResponseWriter) ReadFrom

func (w *ResponseWriter) ReadFrom(r io.Reader) (int64, error)

ReadFrom counts a body streamed with io.Copy.

func (*ResponseWriter) Release

func (w *ResponseWriter) Release()

Release returns the wrapper to the pool. After Release the wrapper is recycled memory, the way the http.ResponseWriter it wraps is invalid after the handler returns.

func (*ResponseWriter) Status

func (w *ResponseWriter) Status() int

Status returns the status the handler wrote.

func (*ResponseWriter) Unwrap

func (w *ResponseWriter) Unwrap() http.ResponseWriter

Unwrap lets http.ResponseController reach the optional interfaces implemented by the original response writer.

func (*ResponseWriter) Write

func (w *ResponseWriter) Write(p []byte) (int, error)

Write counts the response body.

func (*ResponseWriter) WriteHeader

func (w *ResponseWriter) WriteHeader(status int)

WriteHeader records the response status once.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL