package logmower import ( "context" "time" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" ) func initializeIndexes(ctx context.Context, col *mongo.Collection) error { ind := col.Indexes() // (does not create duplicates) _, err := ind.CreateOne(mongoTimeoutCtx(ctx), mongo.IndexModel{ Keys: bson.D{{Key: mLogKeyFileBasename, Value: 1}, {Key: mLogKeyOffset, Value: -1}}, }) return err } // when editing, also edit everything in this file! type ( mLog struct { RecordMetadata Content any ContainerTime time.Time StdErr bool // added by toBson() ShipTime time.Time } RecordMetadata struct { HostInfo HostInfo File string Offset int64 // byte offset where log entry ends at } ) const ( // used outside fromBson and toBson mLogKeyHostId = mLogKeyHostInfo + "." + mLogKeyId ) const ( mLogKeyHostInfo = "host_info" mLogKeyId = "id" mLogKeyName = "name" mLogKeyArch = "arch" mLogKeyFileBasename = "file" mLogKeyOffset = "offset" mLogKeyContent = "content" mLogKeyContainerTime = "container_time" mLogKeyStderr = "stderr" mLogKeyShipTime = "ship_time" ) // not using marshal, since it is <0.1x performance func (l *mLog) toBson() bson.M { // DO NOT USE QUOTED STRINGS! Move them to const and use variable instead return bson.M{ mLogKeyHostInfo: bson.M{ mLogKeyId: l.HostInfo.Id, mLogKeyName: l.HostInfo.Name, mLogKeyArch: l.HostInfo.Arch, }, mLogKeyFileBasename: l.File, mLogKeyOffset: l.Offset, mLogKeyContent: l.Content, mLogKeyContainerTime: l.ContainerTime, mLogKeyStderr: l.StdErr, mLogKeyShipTime: time.Now(), } } // really, mongo should support tagged structs func mLogfromBson(b *bson.Raw) mLog { return mLog{ RecordMetadata: RecordMetadata{ HostInfo: HostInfo{ Id: bsonLookupStringValue(b, mLogKeyHostInfo, mLogKeyId), Name: bsonLookupStringValue(b, mLogKeyHostInfo, mLogKeyName), Arch: bsonLookupStringValue(b, mLogKeyHostInfo, mLogKeyArch), }, File: bsonLookupStringValue(b, mLogKeyFileBasename), Offset: bsonLookupInt64(b, mLogKeyOffset), }, Content: bsonLookupStringValue(b, mLogKeyContent), ContainerTime: bsonLookupTime(b, mLogKeyContainerTime), StdErr: bsonLookupBoolean(b, mLogKeyStderr), ShipTime: bsonLookupTime(b, mLogKeyShipTime), } } // default values without ok func bsonLookupBoolean(b *bson.Raw, key ...string) bool { v, _ := b.Lookup(key...).BooleanOK() return v } func bsonLookupStringValue(b *bson.Raw, key ...string) string { v, _ := b.Lookup(key...).StringValueOK() return v } func bsonLookupInt64(b *bson.Raw, key ...string) int64 { v, _ := b.Lookup(key...).Int64OK() return v } func bsonLookupTime(b *bson.Raw, key ...string) time.Time { v, _ := b.Lookup(key...).TimeOK() return v }