9da206dc7c
PVCs and CloudNativePG Clusters need S3 buckets and backup schedules
provisioned consistently. This operator watches the
backups.unkin.net/{schedule,destination} annotations on those objects and
provisions everything needed to back them up, with no new CRDs.
- Add a PVC controller that provisions cephrgw ObjectStoreUser/Bucket/BucketAccess,
auto-generates a restic repo-password Secret and creates a k8up Schedule scoped
to the PVC via spec.backup.volumes[].persistentVolumeClaim.claimName.
- Add a CNPG Cluster controller that provisions the same bucket stack, idempotently
patches spec.backup.barmanObjectStore (leaving a user-set destinationPath alone
with a Warning event) and creates a ScheduledBackup.
- Resolve destinations through a ConfigMap lookup table; requeue until the
BucketAccess is Ready before creating schedule resources; own-reference created
resources and retain bucket data by default.
- Add schedule-mapping helpers (k8up 5-field/shortcut pass-through, CNPG 6-field
seconds-first) and deterministic, length-bounded name derivation.
- Add unit tests (schedule mapping, name derivation, destination resolution) and
envtest controller tests for both paths, wiring the external CRDs into envtest.
- Add kubebuilder-generated RBAC, a Dockerfile (distroless/nonroot), Woodpecker
lint/test/build pipelines and a tag-triggered image push to the artifactapi
docker-internal registry, plus a version-bump Makefile and deploy manifests.
67 lines
1.8 KiB
Markdown
67 lines
1.8 KiB
Markdown
# Trace
|
|
|
|
This package provides an interface for recording the latency of operations and logging details
|
|
about all operations where the latency exceeds a limit.
|
|
|
|
## Usage
|
|
|
|
To create a trace:
|
|
|
|
```go
|
|
func doSomething() {
|
|
opTrace := trace.New("operation", Field{Key: "fieldKey1", Value: "fieldValue1"})
|
|
defer opTrace.LogIfLong(100 * time.Millisecond)
|
|
// do something
|
|
}
|
|
```
|
|
|
|
To split an trace into multiple steps:
|
|
|
|
```go
|
|
func doSomething() {
|
|
opTrace := trace.New("operation")
|
|
defer opTrace.LogIfLong(100 * time.Millisecond)
|
|
// do step 1
|
|
opTrace.Step("step1", Field{Key: "stepFieldKey1", Value: "stepFieldValue1"})
|
|
// do step 2
|
|
opTrace.Step("step2")
|
|
}
|
|
```
|
|
|
|
To nest traces:
|
|
|
|
```go
|
|
func doSomething() {
|
|
rootTrace := trace.New("rootOperation")
|
|
defer rootTrace.LogIfLong(100 * time.Millisecond)
|
|
|
|
func() {
|
|
nestedTrace := rootTrace.Nest("nested", Field{Key: "nestedFieldKey1", Value: "nestedFieldValue1"})
|
|
defer nestedTrace.LogIfLong(50 * time.Millisecond)
|
|
// do nested operation
|
|
}()
|
|
}
|
|
```
|
|
|
|
Traces can also be logged unconditionally or introspected:
|
|
|
|
```go
|
|
opTrace.TotalTime() // Duration since the Trace was created
|
|
opTrace.Log() // unconditionally log the trace
|
|
```
|
|
|
|
### Using context.Context to nest traces
|
|
|
|
`context.Context` can be used to manage nested traces. Create traces by calling `trace.GetTraceFromContext(ctx).Nest`.
|
|
This is safe even if there is no parent trace already in the context because `(*(Trace)nil).Nest()` returns
|
|
a top level trace.
|
|
|
|
```go
|
|
func doSomething(ctx context.Context) {
|
|
opTrace := trace.FromContext(ctx).Nest("operation") // create a trace, possibly nested
|
|
ctx = trace.ContextWithTrace(ctx, opTrace) // make this trace the parent trace of the context
|
|
defer opTrace.LogIfLong(50 * time.Millisecond)
|
|
|
|
doSomethingElse(ctx)
|
|
}
|
|
``` |