capture

package
v0.22.0 Latest Latest
Warning

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

Go to latest
Published: Nov 11, 2026 License: MIT Imports: 34 Imported by: 0

Documentation

Overview

Package capture stores bounded, best-effort diagnostics for every attempt an application's outbound HTTP clients make, and serves guarded viewer routes. Capture is on by default inside an application with a database. Deployment settings can only reduce it (a deny-list, forced redaction, extra masked names, off); exact bodies need application.Builder.FullOutboundCapture.

Index

Constants

View Source
const (
	// MaxExclusions bounds the deny-list.
	MaxExclusions = 64
	// MaxMaskNames bounds the extra credential names.
	MaxMaskNames = 64
)
View Source
const (
	// MigrationOrigin owns the framework's outbound capture table.
	MigrationOrigin migrate.Origin = "foundry.outbound_capture"
	// CreateTable creates foundry_outbound_captures.
	CreateTable migrate.ID = "000001_create_outbound_captures"
	// Introduced is the release that added the table.
	Introduced migrate.Version = "v0.19.0"
)

Variables

This section is empty.

Functions

func Migrations

func Migrations() []migrate.Definition

Migrations returns the framework-owned capture table. Application assembly registers it whenever the application has a database, also while capture is disabled, so toggling capture never changes the migration set. Apply it with the ordinary migration command before capture can store rows.

func Module

func Module(name foundation.ProviderID, key foundation.Key[*Store], requires []foundation.ProviderID, construct func(foundation.Resolver) (*Store, error)) foundation.Module

Module registers the store factory and, at boot, its cleanup before any work starts. Every process writes, because every process constructs its clients; the table is checked on the first capture, so a process that makes no call never queries it. Retention runs beside every kernel except CLI, or after Start without a selected kernel. Requires must name only the borrowed database provider, so the store boots before and closes after every client.

Example: capture.Module("app.outbound-captures", key, requires, construct)

func NewRecorder

func NewRecorder(config Config, full []httpclient.Name) (*httpcapture.Outbound, error)

NewRecorder validates config and builds the static, I/O-free recorder that application assembly contributes to every httpclient.Module. full lists the Go full-body declarations; config.ForceRedacted empties it.

func OutboundBodyOmissionCodec

func OutboundBodyOmissionCodec() codec.Codec[OutboundBodyOmission]

OutboundBodyOmissionCodec applies the generated membership rule at both SQL boundaries. Example: OutboundBodyOmissionCodec()

func OutboundBodyStateCodec

func OutboundBodyStateCodec() codec.Codec[OutboundBodyState]

OutboundBodyStateCodec applies the generated membership rule at both SQL boundaries. Example: OutboundBodyStateCodec()

func OutboundCaptureBodyJSON

func OutboundCaptureBodyJSON() foundrycontract.JSON[OutboundCaptureBody]

OutboundCaptureBodyJSON describes the concrete OutboundCaptureBody JSON boundary. Reuse this immutable descriptor for decoding and client contract export. Fields are discovered from Go declarations; persistence models are not response DTOs. Example: OutboundCaptureBodyJSON()

func OutboundCaptureCauseJSON

func OutboundCaptureCauseJSON() foundrycontract.JSON[OutboundCaptureCause]

OutboundCaptureCauseJSON describes the concrete OutboundCaptureCause JSON boundary. Reuse this immutable descriptor for decoding and client contract export. Fields are discovered from Go declarations; persistence models are not response DTOs. Example: OutboundCaptureCauseJSON()

func OutboundCaptureDetailJSON

func OutboundCaptureDetailJSON() foundrycontract.JSON[OutboundCaptureDetail]

OutboundCaptureDetailJSON describes the concrete OutboundCaptureDetail JSON boundary. Reuse this immutable descriptor for decoding and client contract export. Fields are discovered from Go declarations; persistence models are not response DTOs. Example: OutboundCaptureDetailJSON()

func OutboundCaptureFieldJSON

func OutboundCaptureFieldJSON() foundrycontract.JSON[OutboundCaptureField]

OutboundCaptureFieldJSON describes the concrete OutboundCaptureField JSON boundary. Reuse this immutable descriptor for decoding and client contract export. Fields are discovered from Go declarations; persistence models are not response DTOs. Example: OutboundCaptureFieldJSON()

func OutboundCaptureFiltersDescriptor

func OutboundCaptureFiltersDescriptor() foundryhttp.Query[OutboundCaptureFilters]

OutboundCaptureFiltersDescriptor binds query parameters to concrete OutboundCaptureFilters fields. Reuse this descriptor for request decoding and query URL encoding. Optional fields preserve omission; repeated fields retain slice order.

Example: OutboundCaptureFiltersDescriptor()

func OutboundCaptureJSON

func OutboundCaptureJSON() foundrycontract.JSON[OutboundCapture]

OutboundCaptureJSON describes the concrete OutboundCapture JSON boundary. Reuse this immutable descriptor for decoding and client contract export. Fields are discovered from Go declarations; persistence models are not response DTOs. Example: OutboundCaptureJSON()

func OutboundCaptureModeCodec

func OutboundCaptureModeCodec() codec.Codec[OutboundCaptureMode]

OutboundCaptureModeCodec applies the generated membership rule at both SQL boundaries. Example: OutboundCaptureModeCodec()

func OutboundCaptureOmissionCodec

func OutboundCaptureOmissionCodec() codec.Codec[OutboundCaptureOmission]

OutboundCaptureOmissionCodec applies the generated membership rule at both SQL boundaries. Example: OutboundCaptureOmissionCodec()

func OutboundCapturePathDescriptor

func OutboundCapturePathDescriptor() foundryhttp.Path[OutboundCapturePath]

OutboundCapturePathDescriptor binds the declared pattern to concrete OutboundCapturePath fields. Reuse this descriptor for route registration and named URL generation.

func OutboundResultCodec

func OutboundResultCodec() codec.Codec[OutboundResult]

OutboundResultCodec applies the generated membership rule at both SQL boundaries. Example: OutboundResultCodec()

func Routes

func Routes[M any](group http.Scope, captures *Store, guard http.GuardBinding[M], access ...http.GuardOption[M]) ([]http.RouteRegistration, error)

Routes declares the read-only viewer within group under /outbound-captures:

GET ""           ID <group>.outbound-captures.list  newest-first cursor page of OutboundCapture
GET "/{capture}" ID <group>.outbound-captures.show  OutboundCaptureDetail, 404 when unknown or expired

Both routes authenticate through guard, require every access option before decoding the query or path, and send Cache-Control: no-store. access must not be empty: mounting the viewer always states who may read captured calls. List requires a from time and a window of at most 30 days; pages hold 30 items by default and at most 100. Declarations are validated before return.

Example: capture.Routes(group, captures, admins, http.Scopes(developerRead), http.Permissions(developerPermission))

Types

type Config

type Config struct {
	// BodyBytes bounds each stored body (1 KiB to 8 MiB). A larger body is
	// omitted in redacted mode and stored as an exact prefix in full mode.
	BodyBytes int
	// ValueBytes bounds a redacted string or field value (64 bytes to 1 MiB);
	// longer values read "[omitted N bytes]".
	ValueBytes int
	// ForceRedacted stores every client redacted, overriding
	// Builder.FullOutboundCapture.
	ForceRedacted bool
	// MaskNames adds credential names for headers, query values and body
	// fields, matched exactly and case-insensitively (at most 64, each 1 to
	// 128 bytes).
	MaskNames []string `config:",json"`
	// Exclude is the deny-list (at most 64 rules). A call matching any rule
	// is not captured.
	Exclude []Exclusion `config:",json"`
	// Rate admits at most this many captures per second per client per
	// process (1 to 10,000). Refused calls are made normally and counted as lost.
	Rate int
	// Burst is the per-client admission burst (1 to 10,000).
	Burst int
	// QueueRows bounds captures in flight, queued or being written per
	// process (1 to 256). One client may hold at most a quarter.
	QueueRows int
	// RetainedBytes bounds memory those captures hold per process (up to
	// 1 GiB). One client may hold at most a quarter, which must fit one body.
	RetainedBytes int64
	// Retention deletes captures older than this (1 hour to 365 days).
	Retention time.Duration
	// MaxRows keeps about this many newest captures per client (1,000 to
	// 10,000,000). Pruning catches up every minute while over the cap.
	MaxRows int
}

Config holds deployment policy and limits for outbound capture. Settings load it as features.outbound_capture.config.

Example: config := capture.DefaultConfig(); config.Exclude = []capture.Exclusion{{Client: "crawler"}}

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns 1 MiB bodies, 4 KiB values, 20 captures per second per client with a burst of 40, 256 captures within 64 MiB per process, 30-day retention and 20,000 rows per client, with no exclusions.

func (Config) Validate

func (c Config) Validate() error

Validate checks every limit, extra name and rule at the settings boundary.

type Dependencies

type Dependencies struct {
	DB *database.DB
	// Schema holds foundry_outbound_captures; it must be a valid identifier.
	Schema string
	// Clock supplies retention cutoffs. Attempt times come from the client.
	Clock  clock.Clock
	Logger *slog.Logger
}

Dependencies are borrowed; the Store never closes them.

type Exchange

type Exchange struct{}

Exchange owns exchange identifiers: one stored wire attempt.

type ExchangeID

type ExchangeID = model.ID[Exchange]

ExchangeID identifies one stored attempt.

type Exclusion

type Exclusion struct {
	// Client matches the client's configured name exactly. A rule with only a
	// client excludes that client entirely.
	Client httpclient.Name `json:"client,omitzero"`
	// Host matches the URL host without port, case-insensitively:
	// "api.example.com", or "*.example.com" for any subdomain (the apex needs
	// its own rule).
	Host string `json:"host,omitzero"`
	// Method matches the upper-case request method.
	Method string `json:"method,omitzero"`
	// PathPrefix matches the decoded path segment by segment; it is validated
	// like http.ParsePathPrefix.
	PathPrefix string `json:"path_prefix,omitzero"`
}

Exclusion is one deny-list rule. A rule matches when every field it sets matches; an empty rule is invalid. Rules see only request facts, never the response.

type Operation

type Operation struct{}

Operation owns operation identifiers: one Do, Stream or Download call, which groups its attempts.

type OperationID

type OperationID = model.ID[Operation]

OperationID groups the attempts of one call.

type OutboundBodyOmission

type OutboundBodyOmission string

OutboundBodyOmission explains why a body was not stored. Completeness comes only from an observed end of stream, never from a successful parse.

const (
	// OmittedNotSent: the call never reached the wire (attempt 0).
	OmittedNotSent OutboundBodyOmission = "not_sent"
	// OmittedNoResponse: no response headers arrived.
	OmittedNoResponse OutboundBodyOmission = "no_response"
	// OmittedIncomplete: the body was not read to its end, as with a Stream
	// callback that stopped early or a Download of a non-2xx response.
	OmittedIncomplete OutboundBodyOmission = "incomplete"
	// OmittedOverCaptureLimit: the body exceeded config.body_bytes.
	OmittedOverCaptureLimit OutboundBodyOmission = "over_capture_limit"
	// OmittedContentEncoded: redacted mode cannot inspect compressed bodies.
	OmittedContentEncoded OutboundBodyOmission = "content_encoded"
	// OmittedUnsupportedMediaType: redacted mode stores only JSON, URL-encoded
	// and multipart form bodies.
	OmittedUnsupportedMediaType OutboundBodyOmission = "unsupported_media_type"
	// OmittedMalformed: the body did not parse as its declared media type and
	// is never stored raw.
	OmittedMalformed OutboundBodyOmission = "malformed"
	// OmittedRedactionLimit: nesting, token, part or output bounds were exceeded.
	OmittedRedactionLimit OutboundBodyOmission = "redaction_limit"
	// OmittedCaptureMemory: the capture memory budget had no room for the body.
	OmittedCaptureMemory OutboundBodyOmission = "capture_memory"
	// OmittedDeclined: the request was declared with WithoutBodyCapture.
	OmittedDeclined OutboundBodyOmission = "declined"
)

func OutboundBodyOmissionValues

func OutboundBodyOmissionValues() []OutboundBodyOmission

OutboundBodyOmissionValues returns declared values in source order, with independent slice ownership. Example: OutboundBodyOmissionValues()

func ParseOutboundBodyOmission

func ParseOutboundBodyOmission(text string) (OutboundBodyOmission, error)

ParseOutboundBodyOmission decodes and validates an enum's text representation. Example: ParseOutboundBodyOmission(text)

func (OutboundBodyOmission) EnumDescriptor

EnumDescriptor describes this enum type independently of the receiver's value.

func (OutboundBodyOmission) IsValid

func (v OutboundBodyOmission) IsValid() bool

IsValid checks membership; a Go cast alone does not validate external values.

func (OutboundBodyOmission) MarshalJSON

func (v OutboundBodyOmission) MarshalJSON() ([]byte, error)

MarshalJSON encodes a validated enum as JSON.

func (OutboundBodyOmission) MarshalText

func (v OutboundBodyOmission) MarshalText() ([]byte, error)

MarshalText encodes a validated enum as text.

func (*OutboundBodyOmission) Scan

func (v *OutboundBodyOmission) Scan(source any) error

Scan changes the receiver only after successful decoding. SQL NULL is rejected.

func (*OutboundBodyOmission) UnmarshalJSON

func (v *OutboundBodyOmission) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes validated JSON and rejects null.

func (*OutboundBodyOmission) UnmarshalText

func (v *OutboundBodyOmission) UnmarshalText(data []byte) error

UnmarshalText decodes validated enum text and changes the receiver only on success.

func (OutboundBodyOmission) Validate

func (v OutboundBodyOmission) Validate() error

Validate reports invalid values without formatting the input.

func (OutboundBodyOmission) Value

func (v OutboundBodyOmission) Value() (driver.Value, error)

Value implements database/sql/driver.Valuer through the shared typed codec.

type OutboundBodyState

type OutboundBodyState string

OutboundBodyState says what one stored body holds.

const (
	// BodyEmpty is a complete body without bytes.
	BodyEmpty OutboundBodyState = "empty"
	// BodyExact holds the complete body exactly (full mode).
	BodyExact OutboundBodyState = "exact"
	// BodyExactPrefix holds the first bytes of a body that was larger than
	// the capture limit or not read to its end (full mode).
	BodyExactPrefix OutboundBodyState = "exact_prefix"
	// BodyJSON holds the redacted JSON document.
	BodyJSON OutboundBodyState = "json"
	// BodyForm holds redacted URL-encoded fields as a JSON array of
	// {"name","values"} objects.
	BodyForm OutboundBodyState = "form"
	// BodyMultipart holds a JSON array describing each part; file contents
	// are never stored.
	BodyMultipart OutboundBodyState = "multipart"
	// BodyOmitted stores nothing; OutboundBodyOmission says why.
	BodyOmitted OutboundBodyState = "omitted"
)

func OutboundBodyStateValues

func OutboundBodyStateValues() []OutboundBodyState

OutboundBodyStateValues returns declared values in source order, with independent slice ownership. Example: OutboundBodyStateValues()

func ParseOutboundBodyState

func ParseOutboundBodyState(text string) (OutboundBodyState, error)

ParseOutboundBodyState decodes and validates an enum's text representation. Example: ParseOutboundBodyState(text)

func (OutboundBodyState) EnumDescriptor

EnumDescriptor describes this enum type independently of the receiver's value.

func (OutboundBodyState) IsValid

func (v OutboundBodyState) IsValid() bool

IsValid checks membership; a Go cast alone does not validate external values.

func (OutboundBodyState) MarshalJSON

func (v OutboundBodyState) MarshalJSON() ([]byte, error)

MarshalJSON encodes a validated enum as JSON.

func (OutboundBodyState) MarshalText

func (v OutboundBodyState) MarshalText() ([]byte, error)

MarshalText encodes a validated enum as text.

func (*OutboundBodyState) Scan

func (v *OutboundBodyState) Scan(source any) error

Scan changes the receiver only after successful decoding. SQL NULL is rejected.

func (*OutboundBodyState) UnmarshalJSON

func (v *OutboundBodyState) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes validated JSON and rejects null.

func (*OutboundBodyState) UnmarshalText

func (v *OutboundBodyState) UnmarshalText(data []byte) error

UnmarshalText decodes validated enum text and changes the receiver only on success.

func (OutboundBodyState) Validate

func (v OutboundBodyState) Validate() error

Validate reports invalid values without formatting the input.

func (OutboundBodyState) Value

func (v OutboundBodyState) Value() (driver.Value, error)

Value implements database/sql/driver.Valuer through the shared typed codec.

type OutboundCapture

type OutboundCapture struct {
	ID          ExchangeID  `json:"id"`
	OperationID OperationID `json:"operation_id"`
	// Attempt is 1 to 10, or 0 for a call that never reached the wire.
	Attempt int32 `json:"attempt"`
	// Retried means the client made another attempt after this one.
	Retried   bool              `json:"retried"`
	StartedAt temporal.DateTime `json:"started_at"`
	Client    httpclient.Name   `json:"client"`
	Method    string            `json:"method"`
	Host      string            `json:"host"`
	// Path is the escaped request path, at most 4 KiB.
	Path string `json:"path"`
	// Status is the response status; null when no response arrived.
	Status value.Nullable[int32] `json:"status"`
	Result OutboundResult        `json:"result"`
	// HeadersMS is the time to response headers; null without a response.
	HeadersMS  value.Nullable[int64] `json:"headers_ms"`
	DurationMS int64                 `json:"duration_ms"`
	// RequestID is the inbound request that made the call, if any.
	RequestID         value.Nullable[attribution.RequestID] `json:"request_id"`
	Mode              OutboundCaptureMode                   `json:"mode"`
	RequestSentBytes  int64                                 `json:"request_sent_bytes"`
	ResponseReadBytes int64                                 `json:"response_read_bytes"`
	// DroppedBefore counts captures of the same client the writing process
	// lost after its previous stored capture and before this one.
	DroppedBefore int64 `json:"dropped_before"`
}

OutboundCapture is one list item and the head of a detail. It never carries headers, query values or bodies.

type OutboundCaptureBody

type OutboundCaptureBody struct {
	State OutboundBodyState `json:"state"`
	// Omission is set exactly when State is omitted.
	Omission value.Nullable[OutboundBodyOmission] `json:"omission"`
	// DeclaredBytes is the Content-Length; null when unknown.
	DeclaredBytes value.Nullable[int64] `json:"declared_bytes"`
	// TransferredBytes is what the transport sent (request) or the caller
	// read (response).
	TransferredBytes int64 `json:"transferred_bytes"`
	// Complete means the end of the body was observed: the transport sent
	// the whole request body, or the caller read the whole response. An
	// in-memory request body is stored whole even when it is false.
	Complete bool   `json:"complete"`
	Content  []byte `json:"content"`
}

OutboundCaptureBody is one stored body. Content is base64 in JSON.

type OutboundCaptureBodyValidationFieldSet

type OutboundCaptureBodyValidationFieldSet struct {
	// Complete validates the declared JSON property "complete".
	//
	// Complete means the end of the body was observed: the transport sent
	// the whole request body, or the caller read the whole response. An
	// in-memory request body is stored whole even when it is false.
	//
	Complete foundryvalidation.Field[OutboundCaptureBody, bool]
	// Content validates the declared JSON property "content".
	Content foundryvalidation.Field[OutboundCaptureBody, []byte]
	// DeclaredBytes validates the declared JSON property "declared_bytes".
	//
	// DeclaredBytes is the Content-Length; null when unknown.
	//
	DeclaredBytes foundryvalidation.Field[OutboundCaptureBody, foundryvalue.Nullable[int64]]
	// Omission validates the declared JSON property "omission".
	//
	// Omission is set exactly when State is omitted.
	//
	Omission foundryvalidation.Field[OutboundCaptureBody, foundryvalue.Nullable[OutboundBodyOmission]]
	// State validates the declared JSON property "state".
	State foundryvalidation.Field[OutboundCaptureBody, OutboundBodyState]
	// TransferredBytes validates the declared JSON property "transferred_bytes".
	//
	// TransferredBytes is what the transport sent (request) or the caller
	// read (response).
	//
	TransferredBytes foundryvalidation.Field[OutboundCaptureBody, int64]
}

OutboundCaptureBodyValidationFieldSet retains concrete DTO and value types for validation. Example: OutboundCaptureBodyValidationFields()

func OutboundCaptureBodyValidationFields

func OutboundCaptureBodyValidationFields() OutboundCaptureBodyValidationFieldSet

OutboundCaptureBodyValidationFields returns typed field descriptors. Example: OutboundCaptureBodyValidationFields() Compose rules with these fields; JSON names and selectors are generated.

type OutboundCaptureCause

type OutboundCaptureCause struct {
	RequestID value.Nullable[attribution.RequestID] `json:"request_id"`
	// TraceID is the W3C trace ID as 32 lowercase hexadecimal characters.
	TraceID value.Nullable[string] `json:"trace_id"`
	// Route is the matched inbound route's declared name.
	Route value.Nullable[string] `json:"route"`
}

OutboundCaptureCause links a call to the inbound request that made it.

type OutboundCaptureCauseValidationFieldSet

type OutboundCaptureCauseValidationFieldSet struct {
	// RequestID validates the declared JSON property "request_id".
	RequestID foundryvalidation.Field[OutboundCaptureCause, foundryvalue.Nullable[attribution.RequestID]]
	// Route validates the declared JSON property "route".
	//
	// Route is the matched inbound route's declared name.
	//
	Route foundryvalidation.Field[OutboundCaptureCause, foundryvalue.Nullable[string]]
	// TraceID validates the declared JSON property "trace_id".
	//
	// TraceID is the W3C trace ID as 32 lowercase hexadecimal characters.
	//
	TraceID foundryvalidation.Field[OutboundCaptureCause, foundryvalue.Nullable[string]]
}

OutboundCaptureCauseValidationFieldSet retains concrete DTO and value types for validation. Example: OutboundCaptureCauseValidationFields()

func OutboundCaptureCauseValidationFields

func OutboundCaptureCauseValidationFields() OutboundCaptureCauseValidationFieldSet

OutboundCaptureCauseValidationFields returns typed field descriptors. Example: OutboundCaptureCauseValidationFields() Compose rules with these fields; JSON names and selectors are generated.

type OutboundCaptureDetail

type OutboundCaptureDetail struct {
	Capture          OutboundCapture        `json:"capture"`
	Scheme           string                 `json:"scheme"`
	Query            []OutboundCaptureField `json:"query"`
	RequestHeaders   []OutboundCaptureField `json:"request_headers"`
	RequestBody      OutboundCaptureBody    `json:"request_body"`
	Protocol         value.Nullable[string] `json:"protocol"`
	RemoteIP         value.Nullable[string] `json:"remote_ip"`
	ConnectionReused value.Nullable[bool]   `json:"connection_reused"`
	// ResponseHeaders are the headers the client received, with credential
	// names such as Set-Cookie masked.
	ResponseHeaders []OutboundCaptureField `json:"response_headers"`
	ResponseBody    OutboundCaptureBody    `json:"response_body"`
	Cause           OutboundCaptureCause   `json:"cause"`
	// Attempts are the operation's other stored attempts, oldest first.
	Attempts  []OutboundCapture         `json:"attempts"`
	Omissions []OutboundCaptureOmission `json:"omissions"`
}

OutboundCaptureDetail is one capture with its stored metadata and bodies.

type OutboundCaptureDetailValidationFieldSet

type OutboundCaptureDetailValidationFieldSet struct {
	// Attempts validates the declared JSON property "attempts".
	//
	// Attempts are the operation's other stored attempts, oldest first.
	//
	Attempts foundryvalidation.Field[OutboundCaptureDetail, []OutboundCapture]
	// Capture validates the declared JSON property "capture".
	Capture foundryvalidation.Field[OutboundCaptureDetail, OutboundCapture]
	// Cause validates the declared JSON property "cause".
	Cause foundryvalidation.Field[OutboundCaptureDetail, OutboundCaptureCause]
	// ConnectionReused validates the declared JSON property "connection_reused".
	ConnectionReused foundryvalidation.Field[OutboundCaptureDetail, foundryvalue.Nullable[bool]]
	// Omissions validates the declared JSON property "omissions".
	Omissions foundryvalidation.Field[OutboundCaptureDetail, []OutboundCaptureOmission]
	// Protocol validates the declared JSON property "protocol".
	Protocol foundryvalidation.Field[OutboundCaptureDetail, foundryvalue.Nullable[string]]
	// Query validates the declared JSON property "query".
	Query foundryvalidation.Field[OutboundCaptureDetail, []OutboundCaptureField]
	// RemoteIP validates the declared JSON property "remote_ip".
	RemoteIP foundryvalidation.Field[OutboundCaptureDetail, foundryvalue.Nullable[string]]
	// RequestBody validates the declared JSON property "request_body".
	RequestBody foundryvalidation.Field[OutboundCaptureDetail, OutboundCaptureBody]
	// RequestHeaders validates the declared JSON property "request_headers".
	RequestHeaders foundryvalidation.Field[OutboundCaptureDetail, []OutboundCaptureField]
	// ResponseBody validates the declared JSON property "response_body".
	ResponseBody foundryvalidation.Field[OutboundCaptureDetail, OutboundCaptureBody]
	// ResponseHeaders validates the declared JSON property "response_headers".
	//
	// ResponseHeaders are the headers the client received, with credential
	// names such as Set-Cookie masked.
	//
	ResponseHeaders foundryvalidation.Field[OutboundCaptureDetail, []OutboundCaptureField]
	// Scheme validates the declared JSON property "scheme".
	Scheme foundryvalidation.Field[OutboundCaptureDetail, string]
}

OutboundCaptureDetailValidationFieldSet retains concrete DTO and value types for validation. Example: OutboundCaptureDetailValidationFields()

func OutboundCaptureDetailValidationFields

func OutboundCaptureDetailValidationFields() OutboundCaptureDetailValidationFieldSet

OutboundCaptureDetailValidationFields returns typed field descriptors. Example: OutboundCaptureDetailValidationFields() Compose rules with these fields; JSON names and selectors are generated.

type OutboundCaptureField

type OutboundCaptureField struct {
	Name   string   `json:"name"`
	Values []string `json:"values"`
}

OutboundCaptureField is one header or query name with its values. Masked credential values read "[masked]".

type OutboundCaptureFieldValidationFieldSet

type OutboundCaptureFieldValidationFieldSet struct {
	// Name validates the declared JSON property "name".
	Name foundryvalidation.Field[OutboundCaptureField, string]
	// Values validates the declared JSON property "values".
	Values foundryvalidation.Field[OutboundCaptureField, []string]
}

OutboundCaptureFieldValidationFieldSet retains concrete DTO and value types for validation. Example: OutboundCaptureFieldValidationFields()

func OutboundCaptureFieldValidationFields

func OutboundCaptureFieldValidationFields() OutboundCaptureFieldValidationFieldSet

OutboundCaptureFieldValidationFields returns typed field descriptors. Example: OutboundCaptureFieldValidationFields() Compose rules with these fields; JSON names and selectors are generated.

type OutboundCaptureFilters

type OutboundCaptureFilters struct {
	From  temporal.DateTime                 `query:"from"`
	Until value.Optional[temporal.DateTime] `query:"until"`
	// Client matches the client name exactly.
	Client value.Optional[httpclient.Name] `query:"client"`
	// Host matches the stored host exactly, including a port when the URL had one.
	Host   value.Optional[string]         `query:"host"`
	Method value.Optional[string]         `query:"method"`
	Status value.Optional[int32]          `query:"status"`
	Result value.Optional[OutboundResult] `query:"result"`
	// Problems keeps attempts that did not complete or answered 400 or above.
	Problems value.Optional[bool] `query:"problems"`
	// RequestID keeps calls made while handling one inbound request.
	RequestID value.Optional[attribution.RequestID] `query:"request_id"`
	// Operation keeps the attempts of one call.
	Operation value.Optional[OperationID] `query:"operation"`
}

OutboundCaptureFilters narrows the list. From is required and the window spans at most 30 days; Until defaults to no upper bound.

Example: capture.OutboundCaptureFilters{From: since, Client: value.Set(httpclient.Name("smartpay"))}

type OutboundCaptureMode

type OutboundCaptureMode string

OutboundCaptureMode is the body disclosure policy a capture was stored under.

const (
	// Redacted masks credential-named fields, shortens long values and
	// summarizes multipart files. It is the default for every client.
	Redacted OutboundCaptureMode = "redacted"
	// Full stores bodies within the capture limit exactly. Only
	// application.Builder.FullOutboundCapture selects it.
	Full OutboundCaptureMode = "full"
)

func OutboundCaptureModeValues

func OutboundCaptureModeValues() []OutboundCaptureMode

OutboundCaptureModeValues returns declared values in source order, with independent slice ownership. Example: OutboundCaptureModeValues()

func ParseOutboundCaptureMode

func ParseOutboundCaptureMode(text string) (OutboundCaptureMode, error)

ParseOutboundCaptureMode decodes and validates an enum's text representation. Example: ParseOutboundCaptureMode(text)

func (OutboundCaptureMode) EnumDescriptor

EnumDescriptor describes this enum type independently of the receiver's value.

func (OutboundCaptureMode) IsValid

func (v OutboundCaptureMode) IsValid() bool

IsValid checks membership; a Go cast alone does not validate external values.

func (OutboundCaptureMode) MarshalJSON

func (v OutboundCaptureMode) MarshalJSON() ([]byte, error)

MarshalJSON encodes a validated enum as JSON.

func (OutboundCaptureMode) MarshalText

func (v OutboundCaptureMode) MarshalText() ([]byte, error)

MarshalText encodes a validated enum as text.

func (*OutboundCaptureMode) Scan

func (v *OutboundCaptureMode) Scan(source any) error

Scan changes the receiver only after successful decoding. SQL NULL is rejected.

func (*OutboundCaptureMode) UnmarshalJSON

func (v *OutboundCaptureMode) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes validated JSON and rejects null.

func (*OutboundCaptureMode) UnmarshalText

func (v *OutboundCaptureMode) UnmarshalText(data []byte) error

UnmarshalText decodes validated enum text and changes the receiver only on success.

func (OutboundCaptureMode) Validate

func (v OutboundCaptureMode) Validate() error

Validate reports invalid values without formatting the input.

func (OutboundCaptureMode) Value

func (v OutboundCaptureMode) Value() (driver.Value, error)

Value implements database/sql/driver.Valuer through the shared typed codec.

type OutboundCaptureOmission

type OutboundCaptureOmission string

OutboundCaptureOmission marks request or response metadata that was cut to its bound or left out.

const (
	PathTruncated            OutboundCaptureOmission = "path_truncated"
	QueryTruncated           OutboundCaptureOmission = "query_truncated"
	QueryMalformed           OutboundCaptureOmission = "query_malformed"
	RequestHeadersTruncated  OutboundCaptureOmission = "request_headers_truncated"
	ResponseHeadersTruncated OutboundCaptureOmission = "response_headers_truncated"
)

func OutboundCaptureOmissionValues

func OutboundCaptureOmissionValues() []OutboundCaptureOmission

OutboundCaptureOmissionValues returns declared values in source order, with independent slice ownership. Example: OutboundCaptureOmissionValues()

func ParseOutboundCaptureOmission

func ParseOutboundCaptureOmission(text string) (OutboundCaptureOmission, error)

ParseOutboundCaptureOmission decodes and validates an enum's text representation. Example: ParseOutboundCaptureOmission(text)

func (OutboundCaptureOmission) EnumDescriptor

EnumDescriptor describes this enum type independently of the receiver's value.

func (OutboundCaptureOmission) IsValid

func (v OutboundCaptureOmission) IsValid() bool

IsValid checks membership; a Go cast alone does not validate external values.

func (OutboundCaptureOmission) MarshalJSON

func (v OutboundCaptureOmission) MarshalJSON() ([]byte, error)

MarshalJSON encodes a validated enum as JSON.

func (OutboundCaptureOmission) MarshalText

func (v OutboundCaptureOmission) MarshalText() ([]byte, error)

MarshalText encodes a validated enum as text.

func (*OutboundCaptureOmission) Scan

func (v *OutboundCaptureOmission) Scan(source any) error

Scan changes the receiver only after successful decoding. SQL NULL is rejected.

func (*OutboundCaptureOmission) UnmarshalJSON

func (v *OutboundCaptureOmission) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes validated JSON and rejects null.

func (*OutboundCaptureOmission) UnmarshalText

func (v *OutboundCaptureOmission) UnmarshalText(data []byte) error

UnmarshalText decodes validated enum text and changes the receiver only on success.

func (OutboundCaptureOmission) Validate

func (v OutboundCaptureOmission) Validate() error

Validate reports invalid values without formatting the input.

func (OutboundCaptureOmission) Value

Value implements database/sql/driver.Valuer through the shared typed codec.

type OutboundCapturePath

type OutboundCapturePath struct {
	Capture ExchangeID `path:"capture"`
}

OutboundCapturePath binds the show route's capture ID.

type OutboundCaptureValidationFieldSet

type OutboundCaptureValidationFieldSet struct {
	// Attempt validates the declared JSON property "attempt".
	//
	// Attempt is 1 to 10, or 0 for a call that never reached the wire.
	//
	Attempt foundryvalidation.Field[OutboundCapture, int32]
	// Client validates the declared JSON property "client".
	Client foundryvalidation.Field[OutboundCapture, httpclient.Name]
	// DroppedBefore validates the declared JSON property "dropped_before".
	//
	// DroppedBefore counts captures of the same client the writing process
	// lost after its previous stored capture and before this one.
	//
	DroppedBefore foundryvalidation.Field[OutboundCapture, int64]
	// DurationMS validates the declared JSON property "duration_ms".
	DurationMS foundryvalidation.Field[OutboundCapture, int64]
	// HeadersMS validates the declared JSON property "headers_ms".
	//
	// HeadersMS is the time to response headers; null without a response.
	//
	HeadersMS foundryvalidation.Field[OutboundCapture, foundryvalue.Nullable[int64]]
	// Host validates the declared JSON property "host".
	Host foundryvalidation.Field[OutboundCapture, string]
	// ID validates the declared JSON property "id".
	ID foundryvalidation.Field[OutboundCapture, model.ID[Exchange]]
	// Method validates the declared JSON property "method".
	Method foundryvalidation.Field[OutboundCapture, string]
	// Mode validates the declared JSON property "mode".
	Mode foundryvalidation.Field[OutboundCapture, OutboundCaptureMode]
	// OperationID validates the declared JSON property "operation_id".
	OperationID foundryvalidation.Field[OutboundCapture, model.ID[Operation]]
	// Path validates the declared JSON property "path".
	//
	// Path is the escaped request path, at most 4 KiB.
	//
	Path foundryvalidation.Field[OutboundCapture, string]
	// RequestID validates the declared JSON property "request_id".
	//
	// RequestID is the inbound request that made the call, if any.
	//
	RequestID foundryvalidation.Field[OutboundCapture, foundryvalue.Nullable[attribution.RequestID]]
	// RequestSentBytes validates the declared JSON property "request_sent_bytes".
	RequestSentBytes foundryvalidation.Field[OutboundCapture, int64]
	// ResponseReadBytes validates the declared JSON property "response_read_bytes".
	ResponseReadBytes foundryvalidation.Field[OutboundCapture, int64]
	// Result validates the declared JSON property "result".
	Result foundryvalidation.Field[OutboundCapture, OutboundResult]
	// Retried validates the declared JSON property "retried".
	//
	// Retried means the client made another attempt after this one.
	//
	Retried foundryvalidation.Field[OutboundCapture, bool]
	// StartedAt validates the declared JSON property "started_at".
	StartedAt foundryvalidation.Field[OutboundCapture, temporal.DateTime]
	// Status validates the declared JSON property "status".
	//
	// Status is the response status; null when no response arrived.
	//
	Status foundryvalidation.Field[OutboundCapture, foundryvalue.Nullable[int32]]
}

OutboundCaptureValidationFieldSet retains concrete DTO and value types for validation. Example: OutboundCaptureValidationFields()

func OutboundCaptureValidationFields

func OutboundCaptureValidationFields() OutboundCaptureValidationFieldSet

OutboundCaptureValidationFields returns typed field descriptors. Example: OutboundCaptureValidationFields() Compose rules with these fields; JSON names and selectors are generated.

type OutboundResult

type OutboundResult string

OutboundResult is how one attempt ended. Exactly one applies per row.

const (
	// ResultCompleted: response headers arrived and the attempt ended without
	// a failure, at any HTTP status, including a retried status.
	ResultCompleted OutboundResult = "completed"
	// ResultConsumerFailed: the Stream callback or Download destination failed.
	ResultConsumerFailed OutboundResult = "consumer_failed"
	// ResultResponseBodyFailed: reading the response body failed.
	ResultResponseBodyFailed OutboundResult = "response_body_failed"
	// ResultResponseTooLarge: Content-Length or the body exceeded the client's limit.
	ResultResponseTooLarge OutboundResult = "response_too_large"
	// ResultRequestBodyFailed: opening or reading the request body failed.
	ResultRequestBodyFailed OutboundResult = "request_body_failed"
	// ResultTransportFailed: connect, TLS, protocol or response header failure.
	ResultTransportFailed OutboundResult = "transport_failed"
	// ResultTimedOut: the attempt or operation deadline passed.
	ResultTimedOut OutboundResult = "timed_out"
	// ResultCanceled: the caller's context was canceled.
	ResultCanceled OutboundResult = "canceled"
	// ResultDestinationDenied: the destination policy refused the URL or address.
	ResultDestinationDenied OutboundResult = "destination_denied"
	// ResultOverloaded: the client's admission was full; nothing was sent.
	ResultOverloaded OutboundResult = "overloaded"
)

func OutboundResultValues

func OutboundResultValues() []OutboundResult

OutboundResultValues returns declared values in source order, with independent slice ownership. Example: OutboundResultValues()

func ParseOutboundResult

func ParseOutboundResult(text string) (OutboundResult, error)

ParseOutboundResult decodes and validates an enum's text representation. Example: ParseOutboundResult(text)

func (OutboundResult) EnumDescriptor

func (OutboundResult) EnumDescriptor() enum.Descriptor[OutboundResult]

EnumDescriptor describes this enum type independently of the receiver's value.

func (OutboundResult) IsValid

func (v OutboundResult) IsValid() bool

IsValid checks membership; a Go cast alone does not validate external values.

func (OutboundResult) MarshalJSON

func (v OutboundResult) MarshalJSON() ([]byte, error)

MarshalJSON encodes a validated enum as JSON.

func (OutboundResult) MarshalText

func (v OutboundResult) MarshalText() ([]byte, error)

MarshalText encodes a validated enum as text.

func (*OutboundResult) Scan

func (v *OutboundResult) Scan(source any) error

Scan changes the receiver only after successful decoding. SQL NULL is rejected.

func (*OutboundResult) UnmarshalJSON

func (v *OutboundResult) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes validated JSON and rejects null.

func (*OutboundResult) UnmarshalText

func (v *OutboundResult) UnmarshalText(data []byte) error

UnmarshalText decodes validated enum text and changes the receiver only on success.

func (OutboundResult) Validate

func (v OutboundResult) Validate() error

Validate reports invalid values without formatting the input.

func (OutboundResult) Value

func (v OutboundResult) Value() (driver.Value, error)

Value implements database/sql/driver.Valuer through the shared typed codec.

type Store

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

Store owns foundry_outbound_captures: the single writer that drains the recorder, retention, and the bounded reads behind Routes. Applications hold it to mount Routes; Module drives its lifecycle. Construct it with New.

func New

func New(recorder *httpcapture.Outbound, deps Dependencies, config Config) (*Store, error)

New validates its inputs without I/O. A nil recorder gives a store that reads and prunes but never writes, as when capture is disabled.

Example: capture.New(recorder, capture.Dependencies{DB: db, Schema: "public", Clock: clock.System{}, Logger: logger}, capture.DefaultConfig())

func (*Store) Close

func (s *Store) Close(ctx context.Context) error

Close stops admission, writes what remains within a short drain budget and counts the rest as lost. It runs after every client has drained.

func (*Store) Done

func (s *Store) Done() <-chan struct{}

Done closes once Close has finished.

func (*Store) Format

func (*Store) Format(s fmt.State, _ rune)

Format writes a fixed label without exposing dependencies or captures.

func (*Store) Run

func (s *Store) Run(ctx context.Context) error

Run writes captures and prunes the table until ctx ends. Database trouble never stops it: an unavailable table degrades capture with one logged reason, a failed batch is retried twice and then row by row, and only the rows that still fail are counted as lost.

Jump to

Keyboard shortcuts

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