Files
kopia/internal/blobparam/blobid_params.go
Jarek Kowalski 0f7253eb66 feat(general): rewrote content logs to always be JSON-based and reorganized log structure (#4822)
This is a breaking change to users who might be using Kopia as a library.

### Log Format

```json
{"t":"<timestamp-rfc-3389-microseconds>", "span:T1":"V1", "span:T2":"V2", "n":"<source>", "m":"<message>", /*parameters*/}
```

Where each record is associated with one or more spans that describe its scope:

* `"span:client": "<hash-of-username@hostname>"`
* `"span:repo": "<random>"` - random identifier of a repository connection (from `repo.Open`)
* `"span:maintenance": "<random>"` - random identifier of a maintenance session
* `"span:upload": "<hash-of-username@host:/path>"` - uniquely identifies upload session of a given directory
* `"span:checkpoint": "<random>"` - encapsulates each checkpoint operation during Upload
* `"span:server-session": "<random>"` -single client connection to the server
* `"span:flush": "<random>"` - encapsulates each Flush session
* `"span:maintenance": "<random>"` - encapsulates each maintenance operation
* `"span:loadIndex" : "<random>"` - encapsulates index loading operation
* `"span:emr" : "<random>"` - encapsulates epoch manager refresh
* `"span:writePack": "<pack-blob-ID>"` - encapsulates pack blob preparation and writing

(plus additional minor spans for various phases of the maintenance).

Notable points:

- Used internal zero allocation JSON writer for reduced memory usage.
- renamed `--disable-internal-log` to `--disable-repository-log` (controls saving blobs to repository)
- added `--disable-content-log` (controls writing of `content-log` files)
- all storage operations are also logged in a structural way and associated with the corresponding spans.
- all content IDs are logged in a truncated format (since first N bytes that are usually enough to be unique) to improve compressibility of logs (blob IDs are frequently repeated but content IDs usually appear just once).

This format should make it possible to recreate the journey of any single content throughout pack blobs, indexes and compaction events.
2025-09-27 17:11:13 -07:00

92 lines
2.0 KiB
Go

// Package blobparam provides parameters for logging blob-specific operations.
package blobparam
import (
"github.com/kopia/kopia/internal/contentlog"
"github.com/kopia/kopia/repo/blob"
)
type blobMetadataListParam struct {
key string
list []blob.Metadata
}
func (v blobMetadataListParam) WriteValueTo(jw *contentlog.JSONWriter) {
jw.BeginListField(v.key)
for _, bm := range v.list {
jw.BeginObject()
jw.StringField("blobID", string(bm.BlobID))
jw.Int64Field("l", bm.Length)
jw.TimeField("ts", bm.Timestamp)
jw.EndObject()
}
jw.EndList()
}
// BlobMetadataList creates a parameter for a list of blob metadata.
//
//nolint:revive
func BlobMetadataList(name string, list []blob.Metadata) blobMetadataListParam {
return blobMetadataListParam{key: name, list: list}
}
type blobIDParam struct {
key string
val blob.ID
}
func (v blobIDParam) WriteValueTo(jw *contentlog.JSONWriter) {
jw.StringField(v.key, string(v.val))
}
// BlobID creates a parameter for a blob ID.
//
//nolint:revive
func BlobID(name string, id blob.ID) blobIDParam {
return blobIDParam{key: name, val: id}
}
type blobIDListParam struct {
key string
list []blob.ID
}
func (v blobIDListParam) WriteValueTo(jw *contentlog.JSONWriter) {
jw.BeginListField(v.key)
for _, blobID := range v.list {
jw.StringElement(string(blobID))
}
jw.EndList()
}
// BlobIDList creates a parameter for a list of blob IDs.
//
//nolint:revive
func BlobIDList(name string, list []blob.ID) blobIDListParam {
return blobIDListParam{key: name, list: list}
}
type blobMetadataParam struct {
key string
val blob.Metadata
}
func (v blobMetadataParam) WriteValueTo(jw *contentlog.JSONWriter) {
jw.BeginObjectField(v.key)
jw.StringField("blobID", string(v.val.BlobID))
jw.Int64Field("l", v.val.Length)
jw.TimeField("ts", v.val.Timestamp)
jw.EndObject()
}
// BlobMetadata creates a parameter for a blob metadata.
//
//nolint:revive
func BlobMetadata(name string, bm blob.Metadata) blobMetadataParam {
return blobMetadataParam{key: name, val: bm}
}