@@ -66,39 +66,12 @@ type Breadcrumb struct {
6666 Message string `json:"message,omitempty"`
6767 Data map [string ]interface {} `json:"data,omitempty"`
6868 Level Level `json:"level,omitempty"`
69- Timestamp time.Time `json:"timestamp"`
69+ Timestamp time.Time `json:"timestamp,omitzero "`
7070}
7171
7272// TODO: provide constants for known breadcrumb types.
7373// See https://develop.sentry.dev/sdk/event-payloads/breadcrumbs/#breadcrumb-types.
7474
75- // MarshalJSON converts the Breadcrumb struct to JSON.
76- func (b * Breadcrumb ) MarshalJSON () ([]byte , error ) {
77- // We want to omit time.Time zero values, otherwise the server will try to
78- // interpret dates too far in the past. However, encoding/json doesn't
79- // support the "omitempty" option for struct types. See
80- // https://golang.org/issues/11939.
81- //
82- // We overcome the limitation and achieve what we want by shadowing fields
83- // and a few type tricks.
84-
85- // breadcrumb aliases Breadcrumb to allow calling json.Marshal without an
86- // infinite loop. It preserves all fields while none of the attached
87- // methods.
88- type breadcrumb Breadcrumb
89-
90- if b .Timestamp .IsZero () {
91- return json .Marshal (struct {
92- // Embed all the fields of Breadcrumb.
93- * breadcrumb
94- // Timestamp shadows the original Timestamp field and is meant to
95- // remain nil, triggering the omitempty behavior.
96- Timestamp json.RawMessage `json:"timestamp,omitempty"`
97- }{breadcrumb : (* breadcrumb )(b )})
98- }
99- return json .Marshal ((* breadcrumb )(b ))
100- }
101-
10275// Logger provides a chaining API for structured logging to Sentry.
10376type Logger interface {
10477 // Write implements the io.Writer interface. Currently, the [sentry.Hub] is
@@ -436,7 +409,7 @@ type Event struct {
436409 ServerName string `json:"server_name,omitempty"`
437410 Threads []Thread `json:"threads,omitempty"`
438411 Tags map [string ]string `json:"tags,omitempty"`
439- Timestamp time.Time `json:"timestamp"`
412+ Timestamp time.Time `json:"timestamp,omitzero "`
440413 Transaction string `json:"transaction,omitempty"`
441414 User User `json:"user,omitempty"`
442415 Logger string `json:"logger,omitempty"`
@@ -449,7 +422,7 @@ type Event struct {
449422 // The fields below are only relevant for transactions.
450423
451424 Type string `json:"type,omitempty"`
452- StartTime time.Time `json:"start_timestamp"`
425+ StartTime time.Time `json:"start_timestamp,omitzero "`
453426 Spans []* Span `json:"spans,omitempty"`
454427 TransactionInfo * TransactionInfo `json:"transaction_info,omitempty"`
455428
@@ -561,17 +534,6 @@ func (e *Event) GetDynamicSamplingContext() map[string]string {
561534
562535// MarshalJSON converts the Event struct to JSON.
563536func (e * Event ) MarshalJSON () ([]byte , error ) {
564- // We want to omit time.Time zero values, otherwise the server will try to
565- // interpret dates too far in the past. However, encoding/json doesn't
566- // support the "omitempty" option for struct types. See
567- // https://golang.org/issues/11939.
568- //
569- // We overcome the limitation and achieve what we want by shadowing fields
570- // and a few type tricks.
571- if e .Type == transactionType {
572- return e .transactionMarshalJSON ()
573- }
574-
575537 if e .Type == checkInType {
576538 return e .checkInMarshalJSON ()
577539 }
@@ -583,29 +545,24 @@ func (e *Event) defaultMarshalJSON() ([]byte, error) {
583545 // loop. It preserves all fields while none of the attached methods.
584546 type event Event
585547
548+ if e .Type == transactionType {
549+ return json .Marshal (struct { * event }{(* event )(e )})
550+ }
586551 // metrics and logs should be serialized under the same `items` json field.
587552 if e .Type == logEvent .Type {
588553 type logEvent struct {
589554 * event
590- Items []Log `json:"items,omitempty"`
591- Type json.RawMessage `json:"type,omitempty"`
592- Timestamp json.RawMessage `json:"timestamp,omitempty"`
593- StartTime json.RawMessage `json:"start_timestamp,omitempty"`
594- Spans json.RawMessage `json:"spans,omitempty"`
595- TransactionInfo json.RawMessage `json:"transaction_info,omitempty"`
555+ Items []Log `json:"items,omitempty"`
556+ Type json.RawMessage `json:"type,omitempty"`
596557 }
597558 return json .Marshal (logEvent {event : (* event )(e ), Items : e .Logs })
598559 }
599560
600561 if e .Type == traceMetricEvent .Type {
601562 type metricEvent struct {
602563 * event
603- Items []Metric `json:"items,omitempty"`
604- Type json.RawMessage `json:"type,omitempty"`
605- Timestamp json.RawMessage `json:"timestamp,omitempty"`
606- StartTime json.RawMessage `json:"start_timestamp,omitempty"`
607- Spans json.RawMessage `json:"spans,omitempty"`
608- TransactionInfo json.RawMessage `json:"transaction_info,omitempty"`
564+ Items []Metric `json:"items,omitempty"`
565+ Type json.RawMessage `json:"type,omitempty"`
609566 }
610567 return json .Marshal (metricEvent {event : (* event )(e ), Items : e .Metrics })
611568 }
@@ -615,10 +572,6 @@ func (e *Event) defaultMarshalJSON() ([]byte, error) {
615572 type errorEvent struct {
616573 * event
617574
618- // Timestamp shadows the original Timestamp field. It allows us to
619- // include the timestamp when non-zero and omit it otherwise.
620- Timestamp json.RawMessage `json:"timestamp,omitempty"`
621-
622575 // The fields below are not part of error events and only make sense to
623576 // be sent for transactions. They shadow the respective fields in Event
624577 // and are meant to remain nil, triggering the omitempty behavior.
@@ -630,48 +583,6 @@ func (e *Event) defaultMarshalJSON() ([]byte, error) {
630583 }
631584
632585 x := errorEvent {event : (* event )(e )}
633- if ! e .Timestamp .IsZero () {
634- b , err := e .Timestamp .MarshalJSON ()
635- if err != nil {
636- return nil , err
637- }
638- x .Timestamp = b
639- }
640- return json .Marshal (x )
641- }
642-
643- func (e * Event ) transactionMarshalJSON () ([]byte , error ) {
644- // event aliases Event to allow calling json.Marshal without an infinite
645- // loop. It preserves all fields while none of the attached methods.
646- type event Event
647-
648- // transactionEvent is like Event with shadowed fields for customizing JSON
649- // marshaling.
650- type transactionEvent struct {
651- * event
652-
653- // The fields below shadow the respective fields in Event. They allow us
654- // to include timestamps when non-zero and omit them otherwise.
655-
656- StartTime json.RawMessage `json:"start_timestamp,omitempty"`
657- Timestamp json.RawMessage `json:"timestamp,omitempty"`
658- }
659-
660- x := transactionEvent {event : (* event )(e )}
661- if ! e .Timestamp .IsZero () {
662- b , err := e .Timestamp .MarshalJSON ()
663- if err != nil {
664- return nil , err
665- }
666- x .Timestamp = b
667- }
668- if ! e .StartTime .IsZero () {
669- b , err := e .StartTime .MarshalJSON ()
670- if err != nil {
671- return nil , err
672- }
673- x .StartTime = b
674- }
675586 return json .Marshal (x )
676587}
677588
@@ -748,9 +659,9 @@ type EventHint struct {
748659}
749660
750661type Log struct {
751- Timestamp time.Time `json:"timestamp"`
662+ Timestamp time.Time `json:"timestamp,omitzero "`
752663 TraceID TraceID `json:"trace_id"`
753- SpanID SpanID `json:"span_id,omitempty "`
664+ SpanID SpanID `json:"span_id,omitzero "`
754665 Level LogLevel `json:"level"`
755666 Severity int `json:"severity_number,omitempty"`
756667 Body string `json:"body"`
@@ -792,35 +703,6 @@ type Attribute struct {
792703 Type AttrType `json:"type"`
793704}
794705
795- // MarshalJSON converts a Log to JSON that skips SpanID and timestamp when zero.
796- func (l * Log ) MarshalJSON () ([]byte , error ) {
797- type log Log
798-
799- var spanID string
800- if l .SpanID != zeroSpanID {
801- spanID = l .SpanID .String ()
802- }
803-
804- var ts json.RawMessage
805- if ! l .Timestamp .IsZero () {
806- b , err := l .Timestamp .MarshalJSON ()
807- if err != nil {
808- return nil , err
809- }
810- ts = b
811- }
812-
813- return json .Marshal (struct {
814- * log
815- SpanID string `json:"span_id,omitempty"`
816- Timestamp json.RawMessage `json:"timestamp,omitempty"`
817- }{
818- log : (* log )(l ),
819- SpanID : spanID ,
820- Timestamp : ts ,
821- })
822- }
823-
824706type MetricType string
825707
826708const (
@@ -831,45 +713,16 @@ const (
831713)
832714
833715type Metric struct {
834- Timestamp time.Time `json:"timestamp"`
716+ Timestamp time.Time `json:"timestamp,omitzero "`
835717 TraceID TraceID `json:"trace_id"`
836- SpanID SpanID `json:"span_id,omitempty "`
718+ SpanID SpanID `json:"span_id,omitzero "`
837719 Type MetricType `json:"type"`
838720 Name string `json:"name"`
839721 Value MetricValue `json:"value"`
840722 Unit string `json:"unit,omitempty"`
841723 Attributes map [string ]Attribute `json:"attributes,omitempty"`
842724}
843725
844- // MarshalJSON converts a Metric to JSON that skips SpanID and timestamp when zero.
845- func (m * Metric ) MarshalJSON () ([]byte , error ) {
846- type metric Metric
847-
848- var spanID string
849- if m .SpanID != zeroSpanID {
850- spanID = m .SpanID .String ()
851- }
852-
853- var ts json.RawMessage
854- if ! m .Timestamp .IsZero () {
855- b , err := m .Timestamp .MarshalJSON ()
856- if err != nil {
857- return nil , err
858- }
859- ts = b
860- }
861-
862- return json .Marshal (struct {
863- * metric
864- SpanID string `json:"span_id,omitempty"`
865- Timestamp json.RawMessage `json:"timestamp,omitempty"`
866- }{
867- metric : (* metric )(m ),
868- SpanID : spanID ,
869- Timestamp : ts ,
870- })
871- }
872-
873726// GetCategory returns the rate limit category for metrics.
874727func (m * Metric ) GetCategory () ratelimit.Category {
875728 return ratelimit .CategoryTraceMetric
0 commit comments