From fa6619c1cc1b4a605ff20de958034994741a9a1a Mon Sep 17 00:00:00 2001 From: Raja Subramanian Date: Fri, 13 Sep 2024 11:57:40 +0530 Subject: [PATCH] Some metrics protocol changes (#806) * Some metrics protocol changes - Add an envelope time stamp. That should be timestamp when the packet is actually sent. - Remove `start_timestamp`/`end_timestamp` from `TimeseriesMetric` as it is not clear how it will be used. Can add later if needed. * generated protobuf * change comment * generated protobuf * comments * generated protobuf * clean up * generated protobuf * comment to mention absolute time * generated protobuf * adding server normalized timestamps * generated protobuf * comment * generated protobuf * comments * generated protobuf * Changeset * remove incorrect changeset * try again --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/sour-carrots-burn.md | 6 + livekit/livekit_metrics.pb.go | 299 +++++++++++++++++++------------- protobufs/livekit_metrics.proto | 47 ++--- 3 files changed, 207 insertions(+), 145 deletions(-) create mode 100644 .changeset/sour-carrots-burn.md diff --git a/.changeset/sour-carrots-burn.md b/.changeset/sour-carrots-burn.md new file mode 100644 index 00000000..0f793110 --- /dev/null +++ b/.changeset/sour-carrots-burn.md @@ -0,0 +1,6 @@ +--- +"github.com/livekit/protocol": patch +"@livekit/protocol": patch +--- + +Metrics server side timestamp diff --git a/livekit/livekit_metrics.pb.go b/livekit/livekit_metrics.pb.go index 218cccf1..83a662e4 100644 --- a/livekit/livekit_metrics.pb.go +++ b/livekit/livekit_metrics.pb.go @@ -9,6 +9,7 @@ package livekit import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" ) @@ -20,29 +21,29 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// index from [0; 512] are for predefined labels (`MetricLabel`) +// index from [0: MAX_LABEL_PREDEFINED_MAX_VALUE) are for predefined labels (`MetricLabel`) type MetricLabel int32 const ( - MetricLabel_AGENTS_LLM_TTFT MetricLabel = 0 // time to first token from LLM - MetricLabel_AGENTS_STT_TTFT MetricLabel = 1 // time to final transcription - MetricLabel_AGENTS_TTS_TTFB MetricLabel = 2 // time to first byte - MetricLabel_METRIC_LABEL_MAX_VALUE MetricLabel = 512 + MetricLabel_AGENTS_LLM_TTFT MetricLabel = 0 // time to first token from LLM + MetricLabel_AGENTS_STT_TTFT MetricLabel = 1 // time to final transcription + MetricLabel_AGENTS_TTS_TTFB MetricLabel = 2 // time to first byte + MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE MetricLabel = 4096 ) // Enum value maps for MetricLabel. var ( MetricLabel_name = map[int32]string{ - 0: "AGENTS_LLM_TTFT", - 1: "AGENTS_STT_TTFT", - 2: "AGENTS_TTS_TTFB", - 512: "METRIC_LABEL_MAX_VALUE", + 0: "AGENTS_LLM_TTFT", + 1: "AGENTS_STT_TTFT", + 2: "AGENTS_TTS_TTFB", + 4096: "METRIC_LABEL_PREDEFINED_MAX_VALUE", } MetricLabel_value = map[string]int32{ - "AGENTS_LLM_TTFT": 0, - "AGENTS_STT_TTFT": 1, - "AGENTS_TTS_TTFB": 2, - "METRIC_LABEL_MAX_VALUE": 512, + "AGENTS_LLM_TTFT": 0, + "AGENTS_STT_TTFT": 1, + "AGENTS_TTS_TTFB": 2, + "METRIC_LABEL_PREDEFINED_MAX_VALUE": 4096, } ) @@ -78,13 +79,15 @@ type MetricsBatch struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + TimestampMs int64 `protobuf:"varint,1,opt,name=timestamp_ms,json=timestampMs,proto3" json:"timestamp_ms,omitempty"` // time at which this batch is sent based on a monotonic clock (millisecond resolution) + NormalizedTimestamp *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=normalized_timestamp,json=normalizedTimestamp,proto3" json:"normalized_timestamp,omitempty"` // To avoid repeating string values, we store them in a separate list and reference them by index // This is useful for storing participant identities, track names, etc. // There is also a predefined list of labels that can be used to reference common metrics. - // They have reserved indices from 0 to 512 - StrData []string `protobuf:"bytes,1,rep,name=str_data,json=strData,proto3" json:"str_data,omitempty"` - TimeSeries []*TimeSeriesMetric `protobuf:"bytes,2,rep,name=time_series,json=timeSeries,proto3" json:"time_series,omitempty"` - Events []*EventMetric `protobuf:"bytes,3,rep,name=events,proto3" json:"events,omitempty"` + // They have reserved indices from 0 to (METRIC_LABEL_PREDEFINED_MAX_VALUE - 1) + StrData []string `protobuf:"bytes,3,rep,name=str_data,json=strData,proto3" json:"str_data,omitempty"` + TimeSeries []*TimeSeriesMetric `protobuf:"bytes,4,rep,name=time_series,json=timeSeries,proto3" json:"time_series,omitempty"` + Events []*EventMetric `protobuf:"bytes,5,rep,name=events,proto3" json:"events,omitempty"` } func (x *MetricsBatch) Reset() { @@ -119,6 +122,20 @@ func (*MetricsBatch) Descriptor() ([]byte, []int) { return file_livekit_metrics_proto_rawDescGZIP(), []int{0} } +func (x *MetricsBatch) GetTimestampMs() int64 { + if x != nil { + return x.TimestampMs + } + return 0 +} + +func (x *MetricsBatch) GetNormalizedTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.NormalizedTimestamp + } + return nil +} + func (x *MetricsBatch) GetStrData() []string { if x != nil { return x.StrData @@ -147,13 +164,10 @@ type TimeSeriesMetric struct { // Metric name e.g "speech_probablity". The string value is not directly stored in the message, but referenced by index // in the `str_data` field of `MetricsBatch` - Label uint32 `protobuf:"varint,1,opt,name=label,proto3" json:"label,omitempty"` - ParticipantIdentity uint32 `protobuf:"varint,2,opt,name=participant_identity,json=participantIdentity,proto3" json:"participant_identity,omitempty"` - TrackSid uint32 `protobuf:"varint,3,opt,name=track_sid,json=trackSid,proto3" json:"track_sid,omitempty"` - StartTimestamp int64 `protobuf:"varint,4,opt,name=start_timestamp,json=startTimestamp,proto3" json:"start_timestamp,omitempty"` // samples - EndTimestamp int64 `protobuf:"varint,5,opt,name=end_timestamp,json=endTimestamp,proto3" json:"end_timestamp,omitempty"` - // list of samples between start_timestamp and end_timestamp - Samples []*MetricSample `protobuf:"bytes,6,rep,name=samples,proto3" json:"samples,omitempty"` + Label uint32 `protobuf:"varint,1,opt,name=label,proto3" json:"label,omitempty"` + ParticipantIdentity uint32 `protobuf:"varint,2,opt,name=participant_identity,json=participantIdentity,proto3" json:"participant_identity,omitempty"` // index into `str_data` + TrackSid uint32 `protobuf:"varint,3,opt,name=track_sid,json=trackSid,proto3" json:"track_sid,omitempty"` // index into `str_data` + Samples []*MetricSample `protobuf:"bytes,4,rep,name=samples,proto3" json:"samples,omitempty"` } func (x *TimeSeriesMetric) Reset() { @@ -209,20 +223,6 @@ func (x *TimeSeriesMetric) GetTrackSid() uint32 { return 0 } -func (x *TimeSeriesMetric) GetStartTimestamp() int64 { - if x != nil { - return x.StartTimestamp - } - return 0 -} - -func (x *TimeSeriesMetric) GetEndTimestamp() int64 { - if x != nil { - return x.EndTimestamp - } - return 0 -} - func (x *TimeSeriesMetric) GetSamples() []*MetricSample { if x != nil { return x.Samples @@ -235,8 +235,9 @@ type MetricSample struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Value float32 `protobuf:"fixed32,2,opt,name=value,proto3" json:"value,omitempty"` + TimestampMs int64 `protobuf:"varint,1,opt,name=timestamp_ms,json=timestampMs,proto3" json:"timestamp_ms,omitempty"` // time of metric based on a monotonic clock (in milliseconds) + NormalizedTimestamp *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=normalized_timestamp,json=normalizedTimestamp,proto3" json:"normalized_timestamp,omitempty"` + Value float32 `protobuf:"fixed32,3,opt,name=value,proto3" json:"value,omitempty"` } func (x *MetricSample) Reset() { @@ -271,13 +272,20 @@ func (*MetricSample) Descriptor() ([]byte, []int) { return file_livekit_metrics_proto_rawDescGZIP(), []int{2} } -func (x *MetricSample) GetTimestamp() int64 { +func (x *MetricSample) GetTimestampMs() int64 { if x != nil { - return x.Timestamp + return x.TimestampMs } return 0 } +func (x *MetricSample) GetNormalizedTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.NormalizedTimestamp + } + return nil +} + func (x *MetricSample) GetValue() float32 { if x != nil { return x.Value @@ -290,12 +298,14 @@ type EventMetric struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Label uint32 `protobuf:"varint,1,opt,name=label,proto3" json:"label,omitempty"` - ParticipantIdentity uint32 `protobuf:"varint,2,opt,name=participant_identity,json=participantIdentity,proto3" json:"participant_identity,omitempty"` - TrackSid uint32 `protobuf:"varint,3,opt,name=track_sid,json=trackSid,proto3" json:"track_sid,omitempty"` // 0 = - StartTimestamp int64 `protobuf:"varint,4,opt,name=start_timestamp,json=startTimestamp,proto3" json:"start_timestamp,omitempty"` - EndTimestamp *int64 `protobuf:"varint,5,opt,name=end_timestamp,json=endTimestamp,proto3,oneof" json:"end_timestamp,omitempty"` - Metadata string `protobuf:"bytes,6,opt,name=metadata,proto3" json:"metadata,omitempty"` + Label uint32 `protobuf:"varint,1,opt,name=label,proto3" json:"label,omitempty"` + ParticipantIdentity uint32 `protobuf:"varint,2,opt,name=participant_identity,json=participantIdentity,proto3" json:"participant_identity,omitempty"` // index into `str_data` + TrackSid uint32 `protobuf:"varint,3,opt,name=track_sid,json=trackSid,proto3" json:"track_sid,omitempty"` // index into `str_data` + StartTimestampMs int64 `protobuf:"varint,4,opt,name=start_timestamp_ms,json=startTimestampMs,proto3" json:"start_timestamp_ms,omitempty"` // start time of event based on a monotonic clock (in milliseconds) + EndTimestampMs *int64 `protobuf:"varint,5,opt,name=end_timestamp_ms,json=endTimestampMs,proto3,oneof" json:"end_timestamp_ms,omitempty"` // end time of event based on a monotonic clock (in milliseconds), if needed + NormalizedStartTimestamp *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=normalized_start_timestamp,json=normalizedStartTimestamp,proto3" json:"normalized_start_timestamp,omitempty"` + NormalizedEndTimestamp *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=normalized_end_timestamp,json=normalizedEndTimestamp,proto3,oneof" json:"normalized_end_timestamp,omitempty"` + Metadata string `protobuf:"bytes,8,opt,name=metadata,proto3" json:"metadata,omitempty"` } func (x *EventMetric) Reset() { @@ -351,20 +361,34 @@ func (x *EventMetric) GetTrackSid() uint32 { return 0 } -func (x *EventMetric) GetStartTimestamp() int64 { +func (x *EventMetric) GetStartTimestampMs() int64 { if x != nil { - return x.StartTimestamp + return x.StartTimestampMs } return 0 } -func (x *EventMetric) GetEndTimestamp() int64 { - if x != nil && x.EndTimestamp != nil { - return *x.EndTimestamp +func (x *EventMetric) GetEndTimestampMs() int64 { + if x != nil && x.EndTimestampMs != nil { + return *x.EndTimestampMs } return 0 } +func (x *EventMetric) GetNormalizedStartTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.NormalizedStartTimestamp + } + return nil +} + +func (x *EventMetric) GetNormalizedEndTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.NormalizedEndTimestamp + } + return nil +} + func (x *EventMetric) GetMetadata() string { if x != nil { return x.Metadata @@ -377,63 +401,87 @@ var File_livekit_metrics_proto protoreflect.FileDescriptor var file_livekit_metrics_proto_rawDesc = []byte{ 0x0a, 0x15, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, - 0x22, 0x93, 0x01, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x42, 0x61, 0x74, 0x63, - 0x68, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x74, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x74, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, 0x3a, 0x0a, 0x0b, - 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x74, 0x69, - 0x6d, 0x65, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, - 0x69, 0x74, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x06, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xf7, 0x01, 0x0a, 0x10, 0x54, 0x69, 0x6d, 0x65, 0x53, - 0x65, 0x72, 0x69, 0x65, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x6c, - 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, - 0x6c, 0x12, 0x31, 0x0a, 0x14, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, - 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x13, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x53, 0x69, - 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x6e, - 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0c, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, - 0x2f, 0x0a, 0x07, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, - 0x63, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x07, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, - 0x22, 0x42, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, - 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x22, 0xf4, 0x01, 0x0a, 0x0b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, - 0x74, 0x72, 0x69, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x31, 0x0a, 0x14, 0x70, 0x61, - 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x13, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, - 0x69, 0x70, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1b, 0x0a, - 0x09, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x08, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x53, 0x69, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x74, - 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x12, 0x28, 0x0a, 0x0d, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x0c, 0x65, 0x6e, - 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x88, 0x01, 0x01, 0x12, 0x1a, 0x0a, - 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x65, 0x6e, - 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2a, 0x69, 0x0a, 0x0b, 0x4d, - 0x65, 0x74, 0x72, 0x69, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x47, - 0x45, 0x4e, 0x54, 0x53, 0x5f, 0x4c, 0x4c, 0x4d, 0x5f, 0x54, 0x54, 0x46, 0x54, 0x10, 0x00, 0x12, - 0x13, 0x0a, 0x0f, 0x41, 0x47, 0x45, 0x4e, 0x54, 0x53, 0x5f, 0x53, 0x54, 0x54, 0x5f, 0x54, 0x54, - 0x46, 0x54, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x47, 0x45, 0x4e, 0x54, 0x53, 0x5f, 0x54, - 0x54, 0x53, 0x5f, 0x54, 0x54, 0x46, 0x42, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x16, 0x4d, 0x45, 0x54, - 0x52, 0x49, 0x43, 0x5f, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4d, 0x41, 0x58, 0x5f, 0x56, 0x41, - 0x4c, 0x55, 0x45, 0x10, 0x80, 0x04, 0x42, 0x46, 0x5a, 0x23, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0xaa, 0x02, 0x0d, - 0x4c, 0x69, 0x76, 0x65, 0x4b, 0x69, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0xea, 0x02, 0x0e, - 0x4c, 0x69, 0x76, 0x65, 0x4b, 0x69, 0x74, 0x3a, 0x3a, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0x85, 0x02, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x42, 0x61, 0x74, + 0x63, 0x68, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, + 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x4d, 0x73, 0x12, 0x4d, 0x0a, 0x14, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, + 0x7a, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x13, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x74, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x74, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, + 0x3a, 0x0a, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, + 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x06, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6c, 0x69, + 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, + 0x63, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x10, 0x54, 0x69, + 0x6d, 0x65, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x14, + 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, + 0x61, 0x62, 0x65, 0x6c, 0x12, 0x31, 0x0a, 0x14, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, + 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x13, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x49, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x72, 0x61, 0x63, 0x6b, + 0x5f, 0x73, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x74, 0x72, 0x61, 0x63, + 0x6b, 0x53, 0x69, 0x64, 0x12, 0x2f, 0x0a, 0x07, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, + 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x07, 0x73, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x5f, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4d, 0x73, 0x12, 0x4d, 0x0a, 0x14, 0x6e, 0x6f, 0x72, + 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x13, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xd3, + 0x03, 0x0a, 0x0b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x14, + 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, + 0x61, 0x62, 0x65, 0x6c, 0x12, 0x31, 0x0a, 0x14, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, + 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x13, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x49, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x72, 0x61, 0x63, 0x6b, + 0x5f, 0x73, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x74, 0x72, 0x61, 0x63, + 0x6b, 0x53, 0x69, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x10, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x4d, 0x73, 0x12, 0x2d, 0x0a, 0x10, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x0e, + 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4d, 0x73, 0x88, 0x01, + 0x01, 0x12, 0x58, 0x0a, 0x1a, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x52, 0x18, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x59, 0x0a, 0x18, 0x6e, + 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48, 0x01, 0x52, 0x16, 0x6e, 0x6f, 0x72, + 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x88, 0x01, 0x01, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6d, 0x73, 0x42, 0x1b, 0x0a, 0x19, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, + 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x2a, 0x74, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4c, 0x61, + 0x62, 0x65, 0x6c, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x47, 0x45, 0x4e, 0x54, 0x53, 0x5f, 0x4c, 0x4c, + 0x4d, 0x5f, 0x54, 0x54, 0x46, 0x54, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x47, 0x45, 0x4e, + 0x54, 0x53, 0x5f, 0x53, 0x54, 0x54, 0x5f, 0x54, 0x54, 0x46, 0x54, 0x10, 0x01, 0x12, 0x13, 0x0a, + 0x0f, 0x41, 0x47, 0x45, 0x4e, 0x54, 0x53, 0x5f, 0x54, 0x54, 0x53, 0x5f, 0x54, 0x54, 0x46, 0x42, + 0x10, 0x02, 0x12, 0x26, 0x0a, 0x21, 0x4d, 0x45, 0x54, 0x52, 0x49, 0x43, 0x5f, 0x4c, 0x41, 0x42, + 0x45, 0x4c, 0x5f, 0x50, 0x52, 0x45, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x5f, 0x4d, 0x41, + 0x58, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x80, 0x20, 0x42, 0x46, 0x5a, 0x23, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, + 0x74, 0xaa, 0x02, 0x0d, 0x4c, 0x69, 0x76, 0x65, 0x4b, 0x69, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0xea, 0x02, 0x0e, 0x4c, 0x69, 0x76, 0x65, 0x4b, 0x69, 0x74, 0x3a, 0x3a, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -451,21 +499,26 @@ func file_livekit_metrics_proto_rawDescGZIP() []byte { var file_livekit_metrics_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_livekit_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_livekit_metrics_proto_goTypes = []any{ - (MetricLabel)(0), // 0: livekit.MetricLabel - (*MetricsBatch)(nil), // 1: livekit.MetricsBatch - (*TimeSeriesMetric)(nil), // 2: livekit.TimeSeriesMetric - (*MetricSample)(nil), // 3: livekit.MetricSample - (*EventMetric)(nil), // 4: livekit.EventMetric + (MetricLabel)(0), // 0: livekit.MetricLabel + (*MetricsBatch)(nil), // 1: livekit.MetricsBatch + (*TimeSeriesMetric)(nil), // 2: livekit.TimeSeriesMetric + (*MetricSample)(nil), // 3: livekit.MetricSample + (*EventMetric)(nil), // 4: livekit.EventMetric + (*timestamppb.Timestamp)(nil), // 5: google.protobuf.Timestamp } var file_livekit_metrics_proto_depIdxs = []int32{ - 2, // 0: livekit.MetricsBatch.time_series:type_name -> livekit.TimeSeriesMetric - 4, // 1: livekit.MetricsBatch.events:type_name -> livekit.EventMetric - 3, // 2: livekit.TimeSeriesMetric.samples:type_name -> livekit.MetricSample - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 5, // 0: livekit.MetricsBatch.normalized_timestamp:type_name -> google.protobuf.Timestamp + 2, // 1: livekit.MetricsBatch.time_series:type_name -> livekit.TimeSeriesMetric + 4, // 2: livekit.MetricsBatch.events:type_name -> livekit.EventMetric + 3, // 3: livekit.TimeSeriesMetric.samples:type_name -> livekit.MetricSample + 5, // 4: livekit.MetricSample.normalized_timestamp:type_name -> google.protobuf.Timestamp + 5, // 5: livekit.EventMetric.normalized_start_timestamp:type_name -> google.protobuf.Timestamp + 5, // 6: livekit.EventMetric.normalized_end_timestamp:type_name -> google.protobuf.Timestamp + 7, // [7:7] is the sub-list for method output_type + 7, // [7:7] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name } func init() { file_livekit_metrics_proto_init() } diff --git a/protobufs/livekit_metrics.proto b/protobufs/livekit_metrics.proto index 8b9a64d5..71a6c52e 100644 --- a/protobufs/livekit_metrics.proto +++ b/protobufs/livekit_metrics.proto @@ -5,59 +5,62 @@ option go_package = "github.com/livekit/protocol/livekit"; option csharp_namespace = "LiveKit.Proto"; option ruby_package = "LiveKit::Proto"; +import "google/protobuf/timestamp.proto"; + /* Protocol used to record metrics for a specific session. Clients send their timestamp in their own monotonically increasing time (e.g `performance.now` on JS). - These timestamps are then converted by the SFU to align with the session's timeline, relative to the session start time. - (at receive time) + These timestamps are then augmented by the SFU to its time base. A metric can be linked to a specific track by setting `track_sid`. */ -// index from [0; 512] are for predefined labels (`MetricLabel`) +// index from [0: MAX_LABEL_PREDEFINED_MAX_VALUE) are for predefined labels (`MetricLabel`) enum MetricLabel { AGENTS_LLM_TTFT = 0; // time to first token from LLM AGENTS_STT_TTFT = 1; // time to final transcription AGENTS_TTS_TTFB = 2; // time to first byte - METRIC_LABEL_MAX_VALUE = 512; + METRIC_LABEL_PREDEFINED_MAX_VALUE = 4096; } message MetricsBatch { + int64 timestamp_ms = 1; // time at which this batch is sent based on a monotonic clock (millisecond resolution) + google.protobuf.Timestamp normalized_timestamp = 2; // To avoid repeating string values, we store them in a separate list and reference them by index // This is useful for storing participant identities, track names, etc. // There is also a predefined list of labels that can be used to reference common metrics. - // They have reserved indices from 0 to 512 - repeated string str_data = 1; - repeated TimeSeriesMetric time_series = 2; - repeated EventMetric events = 3; + // They have reserved indices from 0 to (METRIC_LABEL_PREDEFINED_MAX_VALUE - 1) + repeated string str_data = 3; + repeated TimeSeriesMetric time_series = 4; + repeated EventMetric events = 5; } message TimeSeriesMetric { // Metric name e.g "speech_probablity". The string value is not directly stored in the message, but referenced by index // in the `str_data` field of `MetricsBatch` uint32 label = 1; - uint32 participant_identity = 2; - uint32 track_sid = 3; - int64 start_timestamp = 4; // samples - int64 end_timestamp = 5; - // list of samples between start_timestamp and end_timestamp - repeated MetricSample samples = 6; + uint32 participant_identity = 2; // index into `str_data` + uint32 track_sid = 3; // index into `str_data` + repeated MetricSample samples = 4; } message MetricSample { - int64 timestamp = 1; - float value = 2; + int64 timestamp_ms = 1; // time of metric based on a monotonic clock (in milliseconds) + google.protobuf.Timestamp normalized_timestamp = 2; + float value = 3; } message EventMetric { uint32 label = 1; - uint32 participant_identity = 2; - uint32 track_sid = 3; // 0 = - int64 start_timestamp = 4; - optional int64 end_timestamp = 5; - string metadata = 6; -} \ No newline at end of file + uint32 participant_identity = 2; // index into `str_data` + uint32 track_sid = 3; // index into `str_data` + int64 start_timestamp_ms = 4; // start time of event based on a monotonic clock (in milliseconds) + optional int64 end_timestamp_ms = 5; // end time of event based on a monotonic clock (in milliseconds), if needed + google.protobuf.Timestamp normalized_start_timestamp = 6; + optional google.protobuf.Timestamp normalized_end_timestamp = 7; + string metadata = 8; +}