github.com/ydb-platform/ydb-go-sdk/v3@v3.57.0/log/topic.go (about)

     1  package log
     2  
     3  import (
     4  	"context"
     5  	"time"
     6  
     7  	"github.com/ydb-platform/ydb-go-sdk/v3/trace"
     8  )
     9  
    10  // Topic returns trace.Topic with logging events from details
    11  func Topic(l Logger, d trace.Detailer, opts ...Option) (t trace.Topic) {
    12  	return internalTopic(wrapLogger(l, opts...), d)
    13  }
    14  
    15  func internalTopic(l Logger, d trace.Detailer) (t trace.Topic) { //nolint:gocyclo
    16  	t.OnReaderReconnect = func(
    17  		info trace.TopicReaderReconnectStartInfo,
    18  	) func(doneInfo trace.TopicReaderReconnectDoneInfo) {
    19  		if d.Details()&trace.TopicReaderStreamLifeCycleEvents == 0 {
    20  			return nil
    21  		}
    22  		ctx := with(context.Background(), TRACE, "ydb", "topic", "reader", "reconnect")
    23  		start := time.Now()
    24  		l.Log(ctx, "start")
    25  
    26  		return func(doneInfo trace.TopicReaderReconnectDoneInfo) {
    27  			l.Log(WithLevel(ctx, INFO), "reconnected",
    28  				NamedError("reason", info.Reason),
    29  				latencyField(start),
    30  			)
    31  		}
    32  	}
    33  	t.OnReaderReconnectRequest = func(info trace.TopicReaderReconnectRequestInfo) {
    34  		if d.Details()&trace.TopicReaderStreamLifeCycleEvents == 0 {
    35  			return
    36  		}
    37  		ctx := with(context.Background(), TRACE, "ydb", "topic", "reader", "reconnect", "request")
    38  		l.Log(ctx, "start",
    39  			NamedError("reason", info.Reason),
    40  			Bool("was_sent", info.WasSent),
    41  		)
    42  	}
    43  	t.OnReaderPartitionReadStartResponse = func(
    44  		info trace.TopicReaderPartitionReadStartResponseStartInfo,
    45  	) func(stopInfo trace.TopicReaderPartitionReadStartResponseDoneInfo) {
    46  		if d.Details()&trace.TopicReaderPartitionEvents == 0 {
    47  			return nil
    48  		}
    49  		ctx := with(context.Background(), TRACE, "ydb", "topic", "reader", "partition", "read", "start", "response")
    50  		start := time.Now()
    51  		l.Log(ctx, "start",
    52  			String("topic", info.Topic),
    53  			String("reader_connection_id", info.ReaderConnectionID),
    54  			Int64("partition_id", info.PartitionID),
    55  			Int64("partition_session_id", info.PartitionSessionID),
    56  		)
    57  
    58  		return func(doneInfo trace.TopicReaderPartitionReadStartResponseDoneInfo) {
    59  			fields := []Field{
    60  				String("topic", info.Topic),
    61  				String("reader_connection_id", info.ReaderConnectionID),
    62  				Int64("partition_id", info.PartitionID),
    63  				Int64("partition_session_id", info.PartitionSessionID),
    64  				latencyField(start),
    65  			}
    66  			if doneInfo.CommitOffset != nil {
    67  				fields = append(fields,
    68  					Int64("commit_offset", *doneInfo.CommitOffset),
    69  				)
    70  			}
    71  			if doneInfo.ReadOffset != nil {
    72  				fields = append(fields,
    73  					Int64("read_offset", *doneInfo.ReadOffset),
    74  				)
    75  			}
    76  			if doneInfo.Error == nil {
    77  				l.Log(WithLevel(ctx, INFO), "read partition response completed", fields...)
    78  			} else {
    79  				l.Log(WithLevel(ctx, WARN), "read partition response completed",
    80  					append(fields,
    81  						Error(doneInfo.Error),
    82  						versionField(),
    83  					)...,
    84  				)
    85  			}
    86  		}
    87  	}
    88  	t.OnReaderPartitionReadStopResponse = func(
    89  		info trace.TopicReaderPartitionReadStopResponseStartInfo,
    90  	) func(trace.TopicReaderPartitionReadStopResponseDoneInfo) {
    91  		if d.Details()&trace.TopicReaderPartitionEvents == 0 {
    92  			return nil
    93  		}
    94  		ctx := with(context.Background(), TRACE, "ydb", "topic", "reader", "partition", "read", "stop", "response")
    95  		start := time.Now()
    96  		l.Log(ctx, "start",
    97  			String("reader_connection_id", info.ReaderConnectionID),
    98  			String("topic", info.Topic),
    99  			Int64("partition_id", info.PartitionID),
   100  			Int64("partition_session_id", info.PartitionSessionID),
   101  			Int64("committed_offset", info.CommittedOffset),
   102  			Bool("graceful", info.Graceful))
   103  
   104  		return func(doneInfo trace.TopicReaderPartitionReadStopResponseDoneInfo) {
   105  			fields := []Field{
   106  				String("reader_connection_id", info.ReaderConnectionID),
   107  				String("topic", info.Topic),
   108  				Int64("partition_id", info.PartitionID),
   109  				Int64("partition_session_id", info.PartitionSessionID),
   110  				Int64("committed_offset", info.CommittedOffset),
   111  				Bool("graceful", info.Graceful),
   112  				latencyField(start),
   113  			}
   114  			if doneInfo.Error == nil {
   115  				l.Log(WithLevel(ctx, INFO), "reader partition stopped", fields...)
   116  			} else {
   117  				l.Log(WithLevel(ctx, WARN), "reader partition stopped",
   118  					append(fields,
   119  						Error(doneInfo.Error),
   120  						versionField(),
   121  					)...,
   122  				)
   123  			}
   124  		}
   125  	}
   126  	t.OnReaderCommit = func(info trace.TopicReaderCommitStartInfo) func(doneInfo trace.TopicReaderCommitDoneInfo) {
   127  		if d.Details()&trace.TopicReaderStreamEvents == 0 {
   128  			return nil
   129  		}
   130  		ctx := with(context.Background(), TRACE, "ydb", "topic", "reader", "commit")
   131  		start := time.Now()
   132  		l.Log(ctx, "start",
   133  			String("topic", info.Topic),
   134  			Int64("partition_id", info.PartitionID),
   135  			Int64("partition_session_id", info.PartitionSessionID),
   136  			Int64("commit_start_offset", info.StartOffset),
   137  			Int64("commit_end_offset", info.EndOffset),
   138  		)
   139  
   140  		return func(doneInfo trace.TopicReaderCommitDoneInfo) {
   141  			fields := []Field{
   142  				String("topic", info.Topic),
   143  				Int64("partition_id", info.PartitionID),
   144  				Int64("partition_session_id", info.PartitionSessionID),
   145  				Int64("commit_start_offset", info.StartOffset),
   146  				Int64("commit_end_offset", info.EndOffset),
   147  				latencyField(start),
   148  			}
   149  			if doneInfo.Error == nil {
   150  				l.Log(ctx, "committed", fields...)
   151  			} else {
   152  				l.Log(WithLevel(ctx, WARN), "committed",
   153  					append(fields,
   154  						Error(doneInfo.Error),
   155  						versionField(),
   156  					)...,
   157  				)
   158  			}
   159  		}
   160  	}
   161  	t.OnReaderSendCommitMessage = func(
   162  		info trace.TopicReaderSendCommitMessageStartInfo,
   163  	) func(trace.TopicReaderSendCommitMessageDoneInfo) {
   164  		if d.Details()&trace.TopicReaderStreamEvents == 0 {
   165  			return nil
   166  		}
   167  		ctx := with(context.Background(), TRACE, "ydb", "topic", "reader", "send", "commit", "message")
   168  		start := time.Now()
   169  
   170  		commitInfo := info.CommitsInfo.GetCommitsInfo()
   171  		for i := range commitInfo {
   172  			l.Log(ctx, "start",
   173  				String("topic", commitInfo[i].Topic),
   174  				Int64("partitions_id", commitInfo[i].PartitionID),
   175  				Int64("partitions_session_id", commitInfo[i].PartitionSessionID),
   176  				Int64("commit_start_offset", commitInfo[i].StartOffset),
   177  				Int64("commit_end_offset", commitInfo[i].EndOffset),
   178  			)
   179  		}
   180  
   181  		return func(doneInfo trace.TopicReaderSendCommitMessageDoneInfo) {
   182  			for i := range commitInfo {
   183  				fields := []Field{
   184  					String("topic", commitInfo[i].Topic),
   185  					Int64("partitions_id", commitInfo[i].PartitionID),
   186  					Int64("partitions_session_id", commitInfo[i].PartitionSessionID),
   187  					Int64("commit_start_offset", commitInfo[i].StartOffset),
   188  					Int64("commit_end_offset", commitInfo[i].EndOffset),
   189  					latencyField(start),
   190  				}
   191  				if doneInfo.Error == nil {
   192  					l.Log(ctx, "done", fields...)
   193  				} else {
   194  					l.Log(WithLevel(ctx, WARN), "commit message sent",
   195  						append(fields,
   196  							Error(doneInfo.Error),
   197  							versionField(),
   198  						)...,
   199  					)
   200  				}
   201  			}
   202  		}
   203  	}
   204  	t.OnReaderCommittedNotify = func(info trace.TopicReaderCommittedNotifyInfo) {
   205  		if d.Details()&trace.TopicReaderStreamEvents == 0 {
   206  			return
   207  		}
   208  		ctx := with(context.Background(), TRACE, "ydb", "topic", "reader", "committed", "notify")
   209  		l.Log(ctx, "ack",
   210  			String("reader_connection_id", info.ReaderConnectionID),
   211  			String("topic", info.Topic),
   212  			Int64("partition_id", info.PartitionID),
   213  			Int64("partition_session_id", info.PartitionSessionID),
   214  			Int64("committed_offset", info.CommittedOffset),
   215  		)
   216  	}
   217  	t.OnReaderClose = func(info trace.TopicReaderCloseStartInfo) func(doneInfo trace.TopicReaderCloseDoneInfo) {
   218  		if d.Details()&trace.TopicReaderStreamEvents == 0 {
   219  			return nil
   220  		}
   221  		ctx := with(context.Background(), TRACE, "ydb", "topic", "reader", "close")
   222  		start := time.Now()
   223  		l.Log(ctx, "done",
   224  			String("reader_connection_id", info.ReaderConnectionID),
   225  			NamedError("close_reason", info.CloseReason),
   226  		)
   227  
   228  		return func(doneInfo trace.TopicReaderCloseDoneInfo) {
   229  			fields := []Field{
   230  				String("reader_connection_id", info.ReaderConnectionID),
   231  				latencyField(start),
   232  			}
   233  			if doneInfo.CloseError == nil {
   234  				l.Log(ctx, "closed", fields...)
   235  			} else {
   236  				l.Log(WithLevel(ctx, WARN), "closed",
   237  					append(fields,
   238  						Error(doneInfo.CloseError),
   239  						versionField(),
   240  					)...,
   241  				)
   242  			}
   243  		}
   244  	}
   245  
   246  	t.OnReaderInit = func(info trace.TopicReaderInitStartInfo) func(doneInfo trace.TopicReaderInitDoneInfo) {
   247  		if d.Details()&trace.TopicReaderStreamEvents == 0 {
   248  			return nil
   249  		}
   250  		ctx := with(context.Background(), TRACE, "ydb", "topic", "reader", "init")
   251  		start := time.Now()
   252  		l.Log(ctx, "start",
   253  			String("pre_init_reader_connection_id", info.PreInitReaderConnectionID),
   254  			String("consumer", info.InitRequestInfo.GetConsumer()),
   255  			Strings("topics", info.InitRequestInfo.GetTopics()),
   256  		)
   257  
   258  		return func(doneInfo trace.TopicReaderInitDoneInfo) {
   259  			fields := []Field{
   260  				String("pre_init_reader_connection_id", info.PreInitReaderConnectionID),
   261  				String("consumer", info.InitRequestInfo.GetConsumer()),
   262  				Strings("topics", info.InitRequestInfo.GetTopics()),
   263  				latencyField(start),
   264  			}
   265  			if doneInfo.Error == nil {
   266  				l.Log(ctx, "topic reader stream initialized", fields...)
   267  			} else {
   268  				l.Log(WithLevel(ctx, WARN), "topic reader stream initialized",
   269  					append(fields,
   270  						Error(doneInfo.Error),
   271  						versionField(),
   272  					)...,
   273  				)
   274  			}
   275  		}
   276  	}
   277  	t.OnReaderError = func(info trace.TopicReaderErrorInfo) {
   278  		if d.Details()&trace.TopicReaderStreamEvents == 0 {
   279  			return
   280  		}
   281  		ctx := with(context.Background(), TRACE, "ydb", "topic", "reader", "error")
   282  		l.Log(WithLevel(ctx, INFO), "stream error",
   283  			Error(info.Error),
   284  			String("reader_connection_id", info.ReaderConnectionID),
   285  			versionField(),
   286  		)
   287  	}
   288  	t.OnReaderUpdateToken = func(
   289  		info trace.OnReadUpdateTokenStartInfo,
   290  	) func(
   291  		updateTokenInfo trace.OnReadUpdateTokenMiddleTokenReceivedInfo,
   292  	) func(doneInfo trace.OnReadStreamUpdateTokenDoneInfo) {
   293  		if d.Details()&trace.TopicReaderStreamEvents == 0 {
   294  			return nil
   295  		}
   296  		ctx := with(context.Background(), TRACE, "ydb", "topic", "reader", "update", "token")
   297  		start := time.Now()
   298  		l.Log(ctx, "token updating...",
   299  			String("reader_connection_id", info.ReaderConnectionID),
   300  		)
   301  
   302  		return func(
   303  			updateTokenInfo trace.OnReadUpdateTokenMiddleTokenReceivedInfo,
   304  		) func(doneInfo trace.OnReadStreamUpdateTokenDoneInfo) {
   305  			if updateTokenInfo.Error == nil {
   306  				l.Log(ctx, "got token",
   307  					String("reader_connection_id", info.ReaderConnectionID),
   308  					Int("token_len", updateTokenInfo.TokenLen),
   309  					latencyField(start),
   310  				)
   311  			} else {
   312  				l.Log(WithLevel(ctx, WARN), "got token",
   313  					Error(updateTokenInfo.Error),
   314  					String("reader_connection_id", info.ReaderConnectionID),
   315  					Int("token_len", updateTokenInfo.TokenLen),
   316  					latencyField(start),
   317  					versionField(),
   318  				)
   319  			}
   320  
   321  			return func(doneInfo trace.OnReadStreamUpdateTokenDoneInfo) {
   322  				if doneInfo.Error == nil {
   323  					l.Log(ctx, "token updated on stream",
   324  						String("reader_connection_id", info.ReaderConnectionID),
   325  						Int("token_len", updateTokenInfo.TokenLen),
   326  						latencyField(start),
   327  					)
   328  				} else {
   329  					l.Log(WithLevel(ctx, WARN), "token updated on stream",
   330  						Error(doneInfo.Error),
   331  						String("reader_connection_id", info.ReaderConnectionID),
   332  						Int("token_len", updateTokenInfo.TokenLen),
   333  						latencyField(start),
   334  						versionField(),
   335  					)
   336  				}
   337  			}
   338  		}
   339  	}
   340  	t.OnReaderSentDataRequest = func(info trace.TopicReaderSentDataRequestInfo) {
   341  		if d.Details()&trace.TopicReaderMessageEvents == 0 {
   342  			return
   343  		}
   344  		ctx := with(context.Background(), TRACE, "ydb", "topic", "reader", "sent", "data", "request")
   345  		l.Log(ctx, "sent data request",
   346  			String("reader_connection_id", info.ReaderConnectionID),
   347  			Int("request_bytes", info.RequestBytes),
   348  			Int("local_capacity", info.LocalBufferSizeAfterSent),
   349  		)
   350  	}
   351  	t.OnReaderReceiveDataResponse = func(
   352  		info trace.TopicReaderReceiveDataResponseStartInfo,
   353  	) func(trace.TopicReaderReceiveDataResponseDoneInfo) {
   354  		if d.Details()&trace.TopicReaderMessageEvents == 0 {
   355  			return nil
   356  		}
   357  		ctx := with(context.Background(), TRACE, "ydb", "topic", "reader", "receive", "data", "response")
   358  		start := time.Now()
   359  		partitionsCount, batchesCount, messagesCount := info.DataResponse.GetPartitionBatchMessagesCounts()
   360  		l.Log(ctx, "data response received, process starting...",
   361  			String("reader_connection_id", info.ReaderConnectionID),
   362  			Int("received_bytes", info.DataResponse.GetBytesSize()),
   363  			Int("local_capacity", info.LocalBufferSizeAfterReceive),
   364  			Int("partitions_count", partitionsCount),
   365  			Int("batches_count", batchesCount),
   366  			Int("messages_count", messagesCount),
   367  		)
   368  
   369  		return func(doneInfo trace.TopicReaderReceiveDataResponseDoneInfo) {
   370  			if doneInfo.Error == nil {
   371  				l.Log(ctx, "data response received and processed",
   372  					String("reader_connection_id", info.ReaderConnectionID),
   373  					Int("received_bytes", info.DataResponse.GetBytesSize()),
   374  					Int("local_capacity", info.LocalBufferSizeAfterReceive),
   375  					Int("partitions_count", partitionsCount),
   376  					Int("batches_count", batchesCount),
   377  					Int("messages_count", messagesCount),
   378  					latencyField(start),
   379  				)
   380  			} else {
   381  				l.Log(WithLevel(ctx, WARN), "data response received and processed",
   382  					Error(doneInfo.Error),
   383  					String("reader_connection_id", info.ReaderConnectionID),
   384  					Int("received_bytes", info.DataResponse.GetBytesSize()),
   385  					Int("local_capacity", info.LocalBufferSizeAfterReceive),
   386  					Int("partitions_count", partitionsCount),
   387  					Int("batches_count", batchesCount),
   388  					Int("messages_count", messagesCount),
   389  					latencyField(start),
   390  					versionField(),
   391  				)
   392  			}
   393  		}
   394  	}
   395  	t.OnReaderReadMessages = func(
   396  		info trace.TopicReaderReadMessagesStartInfo,
   397  	) func(doneInfo trace.TopicReaderReadMessagesDoneInfo) {
   398  		if d.Details()&trace.TopicReaderMessageEvents == 0 {
   399  			return nil
   400  		}
   401  		ctx := with(context.Background(), TRACE, "ydb", "topic", "reader", "read", "messages")
   402  		start := time.Now()
   403  		l.Log(ctx, "read messages called, waiting...",
   404  			Int("min_count", info.MinCount),
   405  			Int("max_count", info.MaxCount),
   406  			Int("local_capacity_before", info.FreeBufferCapacity),
   407  		)
   408  
   409  		return func(doneInfo trace.TopicReaderReadMessagesDoneInfo) {
   410  			if doneInfo.Error == nil {
   411  				l.Log(ctx, "read messages returned",
   412  					Int("min_count", info.MinCount),
   413  					Int("max_count", info.MaxCount),
   414  					Int("local_capacity_before", info.FreeBufferCapacity),
   415  					latencyField(start),
   416  				)
   417  			} else {
   418  				l.Log(WithLevel(ctx, WARN), "read messages returned",
   419  					Error(doneInfo.Error),
   420  					Int("min_count", info.MinCount),
   421  					Int("max_count", info.MaxCount),
   422  					Int("local_capacity_before", info.FreeBufferCapacity),
   423  					latencyField(start),
   424  					versionField(),
   425  				)
   426  			}
   427  		}
   428  	}
   429  	t.OnReaderUnknownGrpcMessage = func(info trace.OnReadUnknownGrpcMessageInfo) {
   430  		if d.Details()&trace.TopicReaderMessageEvents == 0 {
   431  			return
   432  		}
   433  		ctx := with(context.Background(), TRACE, "ydb", "topic", "reader", "unknown", "grpc", "message")
   434  		l.Log(WithLevel(ctx, INFO), "received unknown message",
   435  			Error(info.Error),
   436  			String("reader_connection_id", info.ReaderConnectionID),
   437  		)
   438  	}
   439  
   440  	///
   441  	/// Topic writer
   442  	///
   443  	t.OnWriterReconnect = func(
   444  		info trace.TopicWriterReconnectStartInfo,
   445  	) func(doneInfo trace.TopicWriterReconnectDoneInfo) {
   446  		if d.Details()&trace.TopicWriterStreamLifeCycleEvents == 0 {
   447  			return nil
   448  		}
   449  		ctx := with(context.Background(), TRACE, "ydb", "topic", "writer", "reconnect")
   450  		start := time.Now()
   451  		l.Log(ctx, "connect to topic writer stream starting...",
   452  			String("topic", info.Topic),
   453  			String("producer_id", info.ProducerID),
   454  			String("writer_instance_id", info.WriterInstanceID),
   455  			Int("attempt", info.Attempt),
   456  		)
   457  
   458  		return func(doneInfo trace.TopicWriterReconnectDoneInfo) {
   459  			if doneInfo.Error == nil {
   460  				l.Log(WithLevel(ctx, DEBUG), "connect to topic writer stream completed",
   461  					String("topic", info.Topic),
   462  					String("producer_id", info.ProducerID),
   463  					String("writer_instance_id", info.WriterInstanceID),
   464  					Int("attempt", info.Attempt),
   465  					latencyField(start),
   466  				)
   467  			} else {
   468  				l.Log(WithLevel(ctx, WARN), "connect to topic writer stream completed",
   469  					Error(doneInfo.Error),
   470  					String("topic", info.Topic),
   471  					String("producer_id", info.ProducerID),
   472  					String("writer_instance_id", info.WriterInstanceID),
   473  					Int("attempt", info.Attempt),
   474  					latencyField(start),
   475  				)
   476  			}
   477  		}
   478  	}
   479  	t.OnWriterInitStream = func(
   480  		info trace.TopicWriterInitStreamStartInfo,
   481  	) func(doneInfo trace.TopicWriterInitStreamDoneInfo) {
   482  		if d.Details()&trace.TopicWriterStreamLifeCycleEvents == 0 {
   483  			return nil
   484  		}
   485  		ctx := with(context.Background(), TRACE, "ydb", "topic", "writer", "stream", "init")
   486  		start := time.Now()
   487  		l.Log(ctx, "start",
   488  			String("topic", info.Topic),
   489  			String("producer_id", info.ProducerID),
   490  			String("writer_instance_id", info.WriterInstanceID),
   491  		)
   492  
   493  		return func(doneInfo trace.TopicWriterInitStreamDoneInfo) {
   494  			if doneInfo.Error == nil {
   495  				l.Log(WithLevel(ctx, DEBUG), "init stream completed",
   496  					Error(doneInfo.Error),
   497  					String("topic", info.Topic),
   498  					String("producer_id", info.ProducerID),
   499  					String("writer_instance_id", info.WriterInstanceID),
   500  					latencyField(start),
   501  					String("session_id", doneInfo.SessionID),
   502  				)
   503  			} else {
   504  				l.Log(WithLevel(ctx, WARN), "init stream completed",
   505  					Error(doneInfo.Error),
   506  					String("topic", info.Topic),
   507  					String("producer_id", info.ProducerID),
   508  					String("writer_instance_id", info.WriterInstanceID),
   509  					latencyField(start),
   510  					String("session_id", doneInfo.SessionID),
   511  				)
   512  			}
   513  		}
   514  	}
   515  	t.OnWriterClose = func(info trace.TopicWriterCloseStartInfo) func(doneInfo trace.TopicWriterCloseDoneInfo) {
   516  		if d.Details()&trace.TopicWriterStreamLifeCycleEvents == 0 {
   517  			return nil
   518  		}
   519  		ctx := with(context.Background(), TRACE, "ydb", "topic", "writer", "close")
   520  		start := time.Now()
   521  		l.Log(ctx, "start",
   522  			String("writer_instance_id", info.WriterInstanceID),
   523  			NamedError("reason", info.Reason),
   524  		)
   525  
   526  		return func(doneInfo trace.TopicWriterCloseDoneInfo) {
   527  			if doneInfo.Error == nil {
   528  				l.Log(WithLevel(ctx, DEBUG), "close topic writer completed",
   529  					Error(doneInfo.Error),
   530  					String("writer_instance_id", info.WriterInstanceID),
   531  					NamedError("reason", info.Reason),
   532  					latencyField(start),
   533  				)
   534  			} else {
   535  				l.Log(WithLevel(ctx, WARN), "close topic writer completed",
   536  					Error(doneInfo.Error),
   537  					String("writer_instance_id", info.WriterInstanceID),
   538  					NamedError("reason", info.Reason),
   539  					latencyField(start),
   540  				)
   541  			}
   542  		}
   543  	}
   544  	t.OnWriterCompressMessages = func(
   545  		info trace.TopicWriterCompressMessagesStartInfo,
   546  	) func(doneInfo trace.TopicWriterCompressMessagesDoneInfo) {
   547  		if d.Details()&trace.TopicWriterStreamEvents == 0 {
   548  			return nil
   549  		}
   550  		ctx := with(context.Background(), TRACE, "ydb", "topic", "writer", "compress", "messages")
   551  		start := time.Now()
   552  		l.Log(ctx, "start",
   553  			String("writer_instance_id", info.WriterInstanceID),
   554  			String("session_id", info.SessionID),
   555  			Any("reason", info.Reason),
   556  			Any("codec", info.Codec),
   557  			Int("messages_count", info.MessagesCount),
   558  			Int64("first_seqno", info.FirstSeqNo),
   559  		)
   560  
   561  		return func(doneInfo trace.TopicWriterCompressMessagesDoneInfo) {
   562  			if doneInfo.Error == nil {
   563  				l.Log(ctx, "compress message completed",
   564  					Error(doneInfo.Error),
   565  					String("writer_instance_id", info.WriterInstanceID),
   566  					String("session_id", info.SessionID),
   567  					Any("reason", info.Reason),
   568  					Any("codec", info.Codec),
   569  					Int("messages_count", info.MessagesCount),
   570  					Int64("first_seqno", info.FirstSeqNo),
   571  					latencyField(start),
   572  				)
   573  			} else {
   574  				l.Log(WithLevel(ctx, ERROR), "compress message completed",
   575  					Error(doneInfo.Error),
   576  					String("writer_instance_id", info.WriterInstanceID),
   577  					String("session_id", info.SessionID),
   578  					Any("reason", info.Reason),
   579  					Any("codec", info.Codec),
   580  					Int("messages_count", info.MessagesCount),
   581  					Int64("first_seqno", info.FirstSeqNo),
   582  					latencyField(start),
   583  				)
   584  			}
   585  		}
   586  	}
   587  	t.OnWriterSendMessages = func(
   588  		info trace.TopicWriterSendMessagesStartInfo,
   589  	) func(doneInfo trace.TopicWriterSendMessagesDoneInfo) {
   590  		if d.Details()&trace.TopicWriterStreamEvents == 0 {
   591  			return nil
   592  		}
   593  		ctx := with(context.Background(), TRACE, "ydb", "topic", "writer", "send", "messages")
   594  		start := time.Now()
   595  		l.Log(ctx, "start",
   596  			String("writer_instance_id", info.WriterInstanceID),
   597  			String("session_id", info.SessionID),
   598  			Any("codec", info.Codec),
   599  			Int("messages_count", info.MessagesCount),
   600  			Int64("first_seqno", info.FirstSeqNo),
   601  		)
   602  
   603  		return func(doneInfo trace.TopicWriterSendMessagesDoneInfo) {
   604  			if doneInfo.Error == nil {
   605  				l.Log(ctx, "send messages completed",
   606  					String("writer_instance_id", info.WriterInstanceID),
   607  					String("session_id", info.SessionID),
   608  					Any("codec", info.Codec),
   609  					Int("messages_count", info.MessagesCount),
   610  					Int64("first_seqno", info.FirstSeqNo),
   611  					latencyField(start),
   612  				)
   613  			} else {
   614  				l.Log(WithLevel(ctx, WARN), "send messages completed",
   615  					Error(doneInfo.Error),
   616  					String("writer_instance_id", info.WriterInstanceID),
   617  					String("session_id", info.SessionID),
   618  					Any("codec", info.Codec),
   619  					Int("messages_count", info.MessagesCount),
   620  					Int64("first_seqno", info.FirstSeqNo),
   621  					latencyField(start),
   622  				)
   623  			}
   624  		}
   625  	}
   626  	t.OnWriterReadUnknownGrpcMessage = func(info trace.TopicOnWriterReadUnknownGrpcMessageInfo) {
   627  		if d.Details()&trace.TopicWriterStreamEvents == 0 {
   628  			return
   629  		}
   630  		ctx := with(context.Background(), DEBUG, "ydb", "topic", "writer", "read", "unknown", "grpc", "message")
   631  		l.Log(ctx, "topic writer receive unknown message from server",
   632  			Error(info.Error),
   633  			String("writer_instance_id", info.WriterInstanceID),
   634  			String("session_id", info.SessionID),
   635  		)
   636  	}
   637  
   638  	return t
   639  }