Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: migrate proto timestamp to uint64 #134

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

kruskall
Copy link
Member

@kruskall kruskall commented Aug 1, 2023

Replace timestamppb with uint64 in protobuf models

Update modeljson to use uint64 instead of time.Time under the hood.

Update input models to store int64 to avoid int->time->int conversion.

Add utility methods for usability.

Caveat: we lose the ability to ingest timestamps before the unix epoch or after the year 2262 (sorry, future apm developers).

Closes #129

@kruskall kruskall requested a review from a team as a code owner August 1, 2023 22:27
Val time.Time
isSet bool
}
type TimeMicrosUnix Int64
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be unsigned?

event.Timestamp = timestamppb.New(event.Timestamp.AsTime().Add(
time.Duration(float64(time.Millisecond) * from.Start.Val),
))
event.Timestamp = event.Timestamp + uint64(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
event.Timestamp = event.Timestamp + uint64(
event.Timestamp += uint64(

Comment on lines +1186 to +1188
var base uint64 = 0
if event.Timestamp != 0 {
base = event.Timestamp
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove this base now, and just use event.Timestamp += below?

@@ -38,5 +37,5 @@ message Event {
google.protobuf.Duration duration = 8;
uint64 severity = 9;

google.protobuf.Timestamp received = 10;
uint64 received = 10;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add a comment to this noting that it's nanoseconds since epoch

@@ -52,7 +51,7 @@ import "useragent.proto";
option go_package = "github.com/elastic/apm-data/model/modelpb";

message APMEvent {
google.protobuf.Timestamp timestamp = 1;
uint64 timestamp = 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add a comment to this noting that it's nanoseconds since epoch

Comment on lines +22 to +49
// TimeToPBTimestamp encodes a time.Time to Unix epoch nanos in uint64 for protobuf.
func TimeToPBTimestamp(t time.Time) uint64 {
return uint64(t.UnixNano())
}

// PBTimestampToTime decodes a uint64 of Unix epoch nanos to a time.Time for protobuf.
func PBTimestampToTime(timestamp uint64) time.Time {
return time.Unix(0, int64(timestamp)).UTC()
}

func PBTimestampNow() uint64 {
return TimeToPBTimestamp(time.Now())
}

func PBTimestampTruncate(t uint64, d time.Duration) uint64 {
ns := uint64(d.Nanoseconds())
return t - t%ns
}

func PBTimestampAdd(t uint64, d time.Duration) uint64 {
ns := uint64(d.Nanoseconds())
return t + ns
}

func PBTimestampSub(t uint64, tt time.Time) time.Duration {
b := TimeToPBTimestamp(tt)
return time.Duration(t - b)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love rebuilding time.Time functions, unless there's a significant performance benefit. Would it be reasonable to just have two functions, to convert to/from time.Time, and perform all time math using the usual time.Time methods? e.g.

// FromTime converts a time.Time to uint64 nanoseconds since Unix epoch.
func FromTime(t time.Time) uint64

// ToTime converts uint64 nanoseconds since Unix epoch to a time.Time.
func ToTime(v uint64) time.Time


// PBTimestampToTime decodes a uint64 of Unix epoch nanos to a time.Time for protobuf.
func PBTimestampToTime(timestamp uint64) time.Time {
return time.Unix(0, int64(timestamp)).UTC()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be passing in seconds & nanoseconds, so we don't lose so much precision?


func (t Time) MarshalFastJSON(w *fastjson.Writer) error {
w.RawByte('"')
w.Time(time.Time(t), timestampFormat)
w.Time(time.Unix(0, int64(t)).UTC(), timestampFormat)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use PBTimestampToTime here?

Alternatively I think we could leave modeljson alone, and convert to time.Time in the caller.

signature string // combination of all attributes
timestamp uint64
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did this need to change?

@marclop
Copy link
Contributor

marclop commented Apr 8, 2024

Is this still relevant?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Consider using uint64 to store timestamps instead of timestamppb
3 participants