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

     1  package log
     2  
     3  import (
     4  	"context"
     5  	"time"
     6  
     7  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
     8  	"github.com/ydb-platform/ydb-go-sdk/v3/retry"
     9  	"github.com/ydb-platform/ydb-go-sdk/v3/trace"
    10  )
    11  
    12  // Table makes trace.Table with logging events from details
    13  func Table(l Logger, d trace.Detailer, opts ...Option) (t trace.Table) {
    14  	return internalTable(wrapLogger(l, opts...), d)
    15  }
    16  
    17  //nolint:gocyclo
    18  func internalTable(l *wrapper, d trace.Detailer) (t trace.Table) {
    19  	t.OnDo = func(
    20  		info trace.TableDoStartInfo,
    21  	) func(
    22  		info trace.TableDoIntermediateInfo,
    23  	) func(
    24  		trace.TableDoDoneInfo,
    25  	) {
    26  		if d.Details()&trace.TablePoolAPIEvents == 0 {
    27  			return nil
    28  		}
    29  		ctx := with(*info.Context, TRACE, "ydb", "table", "do")
    30  		idempotent := info.Idempotent
    31  		label := info.Label
    32  		l.Log(ctx, "start",
    33  			Bool("idempotent", idempotent),
    34  			String("label", label),
    35  		)
    36  		start := time.Now()
    37  
    38  		return func(info trace.TableDoIntermediateInfo) func(trace.TableDoDoneInfo) {
    39  			if info.Error == nil {
    40  				l.Log(ctx, "done",
    41  					latencyField(start),
    42  					Bool("idempotent", idempotent),
    43  					String("label", label),
    44  				)
    45  			} else {
    46  				lvl := WARN
    47  				if !xerrors.IsYdb(info.Error) {
    48  					lvl = DEBUG
    49  				}
    50  				m := retry.Check(info.Error)
    51  				l.Log(WithLevel(ctx, lvl), "failed",
    52  					latencyField(start),
    53  					Bool("idempotent", idempotent),
    54  					String("label", label),
    55  					Error(info.Error),
    56  					Bool("retryable", m.MustRetry(idempotent)),
    57  					Int64("code", m.StatusCode()),
    58  					Bool("deleteSession", m.MustDeleteSession()),
    59  					versionField(),
    60  				)
    61  			}
    62  
    63  			return func(info trace.TableDoDoneInfo) {
    64  				if info.Error == nil {
    65  					l.Log(ctx, "done",
    66  						latencyField(start),
    67  						Bool("idempotent", idempotent),
    68  						String("label", label),
    69  						Int("attempts", info.Attempts),
    70  					)
    71  				} else {
    72  					lvl := ERROR
    73  					if !xerrors.IsYdb(info.Error) {
    74  						lvl = DEBUG
    75  					}
    76  					m := retry.Check(info.Error)
    77  					l.Log(WithLevel(ctx, lvl), "done",
    78  						latencyField(start),
    79  						Bool("idempotent", idempotent),
    80  						String("label", label),
    81  						Int("attempts", info.Attempts),
    82  						Error(info.Error),
    83  						Bool("retryable", m.MustRetry(idempotent)),
    84  						Int64("code", m.StatusCode()),
    85  						Bool("deleteSession", m.MustDeleteSession()),
    86  						versionField(),
    87  					)
    88  				}
    89  			}
    90  		}
    91  	}
    92  	t.OnDoTx = func(
    93  		info trace.TableDoTxStartInfo,
    94  	) func(
    95  		info trace.TableDoTxIntermediateInfo,
    96  	) func(
    97  		trace.TableDoTxDoneInfo,
    98  	) {
    99  		if d.Details()&trace.TablePoolAPIEvents == 0 {
   100  			return nil
   101  		}
   102  		ctx := with(*info.Context, TRACE, "ydb", "table", "do", "tx")
   103  		idempotent := info.Idempotent
   104  		label := info.Label
   105  		l.Log(ctx, "start",
   106  			Bool("idempotent", idempotent),
   107  			String("label", label),
   108  		)
   109  		start := time.Now()
   110  
   111  		return func(info trace.TableDoTxIntermediateInfo) func(trace.TableDoTxDoneInfo) {
   112  			if info.Error == nil {
   113  				l.Log(ctx, "done",
   114  					latencyField(start),
   115  					Bool("idempotent", idempotent),
   116  					String("label", label),
   117  				)
   118  			} else {
   119  				lvl := ERROR
   120  				if !xerrors.IsYdb(info.Error) {
   121  					lvl = DEBUG
   122  				}
   123  				m := retry.Check(info.Error)
   124  				l.Log(WithLevel(ctx, lvl), "done",
   125  					latencyField(start),
   126  					Bool("idempotent", idempotent),
   127  					String("label", label),
   128  					Error(info.Error),
   129  					Bool("retryable", m.MustRetry(idempotent)),
   130  					Int64("code", m.StatusCode()),
   131  					Bool("deleteSession", m.MustDeleteSession()),
   132  					versionField(),
   133  				)
   134  			}
   135  
   136  			return func(info trace.TableDoTxDoneInfo) {
   137  				if info.Error == nil {
   138  					l.Log(ctx, "done",
   139  						latencyField(start),
   140  						Bool("idempotent", idempotent),
   141  						String("label", label),
   142  						Int("attempts", info.Attempts),
   143  					)
   144  				} else {
   145  					lvl := WARN
   146  					if !xerrors.IsYdb(info.Error) {
   147  						lvl = DEBUG
   148  					}
   149  					m := retry.Check(info.Error)
   150  					l.Log(WithLevel(ctx, lvl), "done",
   151  						latencyField(start),
   152  						Bool("idempotent", idempotent),
   153  						String("label", label),
   154  						Int("attempts", info.Attempts),
   155  						Error(info.Error),
   156  						Bool("retryable", m.MustRetry(idempotent)),
   157  						Int64("code", m.StatusCode()),
   158  						Bool("deleteSession", m.MustDeleteSession()),
   159  						versionField(),
   160  					)
   161  				}
   162  			}
   163  		}
   164  	}
   165  	t.OnCreateSession = func(
   166  		info trace.TableCreateSessionStartInfo,
   167  	) func(
   168  		info trace.TableCreateSessionIntermediateInfo,
   169  	) func(
   170  		trace.TableCreateSessionDoneInfo,
   171  	) {
   172  		if d.Details()&trace.TablePoolAPIEvents == 0 {
   173  			return nil
   174  		}
   175  		ctx := with(*info.Context, TRACE, "ydb", "table", "create", "session")
   176  		l.Log(ctx, "start")
   177  		start := time.Now()
   178  
   179  		return func(info trace.TableCreateSessionIntermediateInfo) func(trace.TableCreateSessionDoneInfo) {
   180  			if info.Error == nil {
   181  				l.Log(ctx, "intermediate",
   182  					latencyField(start),
   183  				)
   184  			} else {
   185  				l.Log(WithLevel(ctx, ERROR), "intermediate",
   186  					latencyField(start),
   187  					Error(info.Error),
   188  					versionField(),
   189  				)
   190  			}
   191  
   192  			return func(info trace.TableCreateSessionDoneInfo) {
   193  				if info.Error == nil {
   194  					l.Log(ctx, "done",
   195  						latencyField(start),
   196  						Int("attempts", info.Attempts),
   197  						String("session_id", info.Session.ID()),
   198  						String("session_status", info.Session.Status()),
   199  					)
   200  				} else {
   201  					l.Log(WithLevel(ctx, ERROR), "failed",
   202  						latencyField(start),
   203  						Int("attempts", info.Attempts),
   204  						Error(info.Error),
   205  						versionField(),
   206  					)
   207  				}
   208  			}
   209  		}
   210  	}
   211  	t.OnSessionNew = func(info trace.TableSessionNewStartInfo) func(trace.TableSessionNewDoneInfo) {
   212  		if d.Details()&trace.TableSessionEvents == 0 {
   213  			return nil
   214  		}
   215  		ctx := with(*info.Context, TRACE, "ydb", "table", "session", "new")
   216  		l.Log(ctx, "start")
   217  		start := time.Now()
   218  
   219  		return func(info trace.TableSessionNewDoneInfo) {
   220  			if info.Error == nil {
   221  				if info.Session != nil {
   222  					l.Log(ctx, "done",
   223  						latencyField(start),
   224  						String("id", info.Session.ID()),
   225  					)
   226  				} else {
   227  					l.Log(WithLevel(ctx, WARN), "failed",
   228  						latencyField(start),
   229  						versionField(),
   230  					)
   231  				}
   232  			} else {
   233  				l.Log(WithLevel(ctx, WARN), "failed",
   234  					latencyField(start),
   235  					Error(info.Error),
   236  					versionField(),
   237  				)
   238  			}
   239  		}
   240  	}
   241  	t.OnSessionDelete = func(info trace.TableSessionDeleteStartInfo) func(trace.TableSessionDeleteDoneInfo) {
   242  		if d.Details()&trace.TableSessionEvents == 0 {
   243  			return nil
   244  		}
   245  		ctx := with(*info.Context, TRACE, "ydb", "table", "session", "delete")
   246  		session := info.Session
   247  		l.Log(ctx, "start",
   248  			String("id", info.Session.ID()),
   249  			String("status", info.Session.Status()),
   250  		)
   251  		start := time.Now()
   252  
   253  		return func(info trace.TableSessionDeleteDoneInfo) {
   254  			if info.Error == nil {
   255  				l.Log(ctx, "done",
   256  					latencyField(start),
   257  					String("id", session.ID()),
   258  					String("status", session.Status()),
   259  				)
   260  			} else {
   261  				l.Log(WithLevel(ctx, WARN), "failed",
   262  					latencyField(start),
   263  					String("id", session.ID()),
   264  					String("status", session.Status()),
   265  					Error(info.Error),
   266  					versionField(),
   267  				)
   268  			}
   269  		}
   270  	}
   271  	t.OnSessionKeepAlive = func(info trace.TableKeepAliveStartInfo) func(trace.TableKeepAliveDoneInfo) {
   272  		if d.Details()&trace.TableSessionEvents == 0 {
   273  			return nil
   274  		}
   275  		ctx := with(*info.Context, TRACE, "ydb", "table", "session", "keep", "alive")
   276  		session := info.Session
   277  		l.Log(ctx, "start",
   278  			String("id", session.ID()),
   279  			String("status", session.Status()),
   280  		)
   281  		start := time.Now()
   282  
   283  		return func(info trace.TableKeepAliveDoneInfo) {
   284  			if info.Error == nil {
   285  				l.Log(ctx, "done",
   286  					latencyField(start),
   287  					String("id", session.ID()),
   288  					String("status", session.Status()),
   289  				)
   290  			} else {
   291  				l.Log(WithLevel(ctx, WARN), "failed",
   292  					latencyField(start),
   293  					String("id", session.ID()),
   294  					String("status", session.Status()),
   295  					Error(info.Error),
   296  					versionField(),
   297  				)
   298  			}
   299  		}
   300  	}
   301  	t.OnSessionQueryPrepare = func(
   302  		info trace.TablePrepareDataQueryStartInfo,
   303  	) func(
   304  		trace.TablePrepareDataQueryDoneInfo,
   305  	) {
   306  		if d.Details()&trace.TableSessionQueryInvokeEvents == 0 {
   307  			return nil
   308  		}
   309  		ctx := with(*info.Context, TRACE, "ydb", "table", "session", "query", "prepare")
   310  		session := info.Session
   311  		query := info.Query
   312  		l.Log(ctx, "start",
   313  			appendFieldByCondition(l.logQuery,
   314  				String("query", info.Query),
   315  				String("id", session.ID()),
   316  				String("status", session.Status()),
   317  			)...,
   318  		)
   319  		start := time.Now()
   320  
   321  		return func(info trace.TablePrepareDataQueryDoneInfo) {
   322  			if info.Error == nil {
   323  				l.Log(ctx, "done",
   324  					appendFieldByCondition(l.logQuery,
   325  						Stringer("result", info.Result),
   326  						appendFieldByCondition(l.logQuery,
   327  							String("query", query),
   328  							String("id", session.ID()),
   329  							String("status", session.Status()),
   330  							latencyField(start),
   331  						)...,
   332  					)...,
   333  				)
   334  			} else {
   335  				l.Log(WithLevel(ctx, ERROR), "failed",
   336  					appendFieldByCondition(l.logQuery,
   337  						String("query", query),
   338  						Error(info.Error),
   339  						String("id", session.ID()),
   340  						String("status", session.Status()),
   341  						latencyField(start),
   342  						versionField(),
   343  					)...,
   344  				)
   345  			}
   346  		}
   347  	}
   348  	t.OnSessionQueryExecute = func(
   349  		info trace.TableExecuteDataQueryStartInfo,
   350  	) func(
   351  		trace.TableExecuteDataQueryDoneInfo,
   352  	) {
   353  		if d.Details()&trace.TableSessionQueryInvokeEvents == 0 {
   354  			return nil
   355  		}
   356  		ctx := with(*info.Context, TRACE, "ydb", "table", "session", "query", "execute")
   357  		session := info.Session
   358  		query := info.Query
   359  		l.Log(ctx, "start",
   360  			appendFieldByCondition(l.logQuery,
   361  				Stringer("query", info.Query),
   362  				String("id", session.ID()),
   363  				String("status", session.Status()),
   364  			)...,
   365  		)
   366  		start := time.Now()
   367  
   368  		return func(info trace.TableExecuteDataQueryDoneInfo) {
   369  			if info.Error == nil {
   370  				tx := info.Tx
   371  				l.Log(ctx, "done",
   372  					appendFieldByCondition(l.logQuery,
   373  						Stringer("query", query),
   374  						String("id", session.ID()),
   375  						String("tx", tx.ID()),
   376  						String("status", session.Status()),
   377  						Bool("prepared", info.Prepared),
   378  						NamedError("result_err", info.Result.Err()),
   379  						latencyField(start),
   380  					)...,
   381  				)
   382  			} else {
   383  				l.Log(WithLevel(ctx, ERROR), "failed",
   384  					appendFieldByCondition(l.logQuery,
   385  						Stringer("query", query),
   386  						Error(info.Error),
   387  						String("id", session.ID()),
   388  						String("status", session.Status()),
   389  						Bool("prepared", info.Prepared),
   390  						latencyField(start),
   391  						versionField(),
   392  					)...,
   393  				)
   394  			}
   395  		}
   396  	}
   397  	t.OnSessionQueryStreamExecute = func(
   398  		info trace.TableSessionQueryStreamExecuteStartInfo,
   399  	) func(
   400  		trace.TableSessionQueryStreamExecuteIntermediateInfo,
   401  	) func(
   402  		trace.TableSessionQueryStreamExecuteDoneInfo,
   403  	) {
   404  		if d.Details()&trace.TableSessionQueryStreamEvents == 0 {
   405  			return nil
   406  		}
   407  		ctx := with(*info.Context, TRACE, "ydb", "table", "session", "query", "stream", "execute")
   408  		session := info.Session
   409  		query := info.Query
   410  		l.Log(ctx, "start",
   411  			appendFieldByCondition(l.logQuery,
   412  				Stringer("query", info.Query),
   413  				String("id", session.ID()),
   414  				String("status", session.Status()),
   415  			)...,
   416  		)
   417  		start := time.Now()
   418  
   419  		return func(
   420  			info trace.TableSessionQueryStreamExecuteIntermediateInfo,
   421  		) func(
   422  			trace.TableSessionQueryStreamExecuteDoneInfo,
   423  		) {
   424  			if info.Error == nil {
   425  				l.Log(ctx, "intermediate")
   426  			} else {
   427  				l.Log(WithLevel(ctx, WARN), "failed",
   428  					Error(info.Error),
   429  					versionField(),
   430  				)
   431  			}
   432  
   433  			return func(info trace.TableSessionQueryStreamExecuteDoneInfo) {
   434  				if info.Error == nil {
   435  					l.Log(ctx, "done",
   436  						appendFieldByCondition(l.logQuery,
   437  							Stringer("query", query),
   438  							Error(info.Error),
   439  							String("id", session.ID()),
   440  							String("status", session.Status()),
   441  							latencyField(start),
   442  						)...,
   443  					)
   444  				} else {
   445  					l.Log(WithLevel(ctx, ERROR), "failed",
   446  						appendFieldByCondition(l.logQuery,
   447  							Stringer("query", query),
   448  							Error(info.Error),
   449  							String("id", session.ID()),
   450  							String("status", session.Status()),
   451  							latencyField(start),
   452  							versionField(),
   453  						)...,
   454  					)
   455  				}
   456  			}
   457  		}
   458  	}
   459  	t.OnSessionQueryStreamRead = func(
   460  		info trace.TableSessionQueryStreamReadStartInfo,
   461  	) func(
   462  		intermediateInfo trace.TableSessionQueryStreamReadIntermediateInfo,
   463  	) func(
   464  		trace.TableSessionQueryStreamReadDoneInfo,
   465  	) {
   466  		if d.Details()&trace.TableSessionQueryStreamEvents == 0 {
   467  			return nil
   468  		}
   469  		ctx := with(*info.Context, TRACE, "ydb", "table", "session", "query", "stream", "read")
   470  		session := info.Session
   471  		l.Log(ctx, "start",
   472  			String("id", session.ID()),
   473  			String("status", session.Status()),
   474  		)
   475  		start := time.Now()
   476  
   477  		return func(
   478  			info trace.TableSessionQueryStreamReadIntermediateInfo,
   479  		) func(
   480  			trace.TableSessionQueryStreamReadDoneInfo,
   481  		) {
   482  			if info.Error == nil {
   483  				l.Log(ctx, "intermediate")
   484  			} else {
   485  				l.Log(WithLevel(ctx, WARN), "failed",
   486  					Error(info.Error),
   487  					versionField(),
   488  				)
   489  			}
   490  
   491  			return func(info trace.TableSessionQueryStreamReadDoneInfo) {
   492  				if info.Error == nil {
   493  					l.Log(ctx, "done",
   494  						latencyField(start),
   495  						String("id", session.ID()),
   496  						String("status", session.Status()),
   497  					)
   498  				} else {
   499  					l.Log(WithLevel(ctx, ERROR), "failed",
   500  						latencyField(start),
   501  						String("id", session.ID()),
   502  						String("status", session.Status()),
   503  						Error(info.Error),
   504  						versionField(),
   505  					)
   506  				}
   507  			}
   508  		}
   509  	}
   510  	t.OnSessionTransactionBegin = func(
   511  		info trace.TableSessionTransactionBeginStartInfo,
   512  	) func(
   513  		trace.TableSessionTransactionBeginDoneInfo,
   514  	) {
   515  		if d.Details()&trace.TableSessionTransactionEvents == 0 {
   516  			return nil
   517  		}
   518  		ctx := with(*info.Context, TRACE, "ydb", "table", "session", "tx", "begin")
   519  		session := info.Session
   520  		l.Log(ctx, "start",
   521  			String("id", session.ID()),
   522  			String("status", session.Status()),
   523  		)
   524  		start := time.Now()
   525  
   526  		return func(info trace.TableSessionTransactionBeginDoneInfo) {
   527  			if info.Error == nil {
   528  				l.Log(ctx, "done",
   529  					latencyField(start),
   530  					String("id", session.ID()),
   531  					String("status", session.Status()),
   532  					String("tx", info.Tx.ID()),
   533  				)
   534  			} else {
   535  				l.Log(WithLevel(ctx, WARN), "failed",
   536  					latencyField(start),
   537  					String("id", session.ID()),
   538  					String("status", session.Status()),
   539  					Error(info.Error),
   540  					versionField(),
   541  				)
   542  			}
   543  		}
   544  	}
   545  	t.OnSessionTransactionCommit = func(
   546  		info trace.TableSessionTransactionCommitStartInfo,
   547  	) func(
   548  		trace.TableSessionTransactionCommitDoneInfo,
   549  	) {
   550  		if d.Details()&trace.TableSessionTransactionEvents == 0 {
   551  			return nil
   552  		}
   553  		ctx := with(*info.Context, TRACE, "ydb", "table", "session", "tx", "commit")
   554  		session := info.Session
   555  		tx := info.Tx
   556  		l.Log(ctx, "start",
   557  			String("id", session.ID()),
   558  			String("status", session.Status()),
   559  			String("tx", info.Tx.ID()),
   560  		)
   561  		start := time.Now()
   562  
   563  		return func(info trace.TableSessionTransactionCommitDoneInfo) {
   564  			if info.Error == nil {
   565  				l.Log(ctx, "done",
   566  					latencyField(start),
   567  					String("id", session.ID()),
   568  					String("status", session.Status()),
   569  					String("tx", tx.ID()),
   570  				)
   571  			} else {
   572  				l.Log(WithLevel(ctx, ERROR), "failed",
   573  					latencyField(start),
   574  					String("id", session.ID()),
   575  					String("status", session.Status()),
   576  					String("tx", tx.ID()),
   577  					Error(info.Error),
   578  					versionField(),
   579  				)
   580  			}
   581  		}
   582  	}
   583  	t.OnSessionTransactionRollback = func(
   584  		info trace.TableSessionTransactionRollbackStartInfo,
   585  	) func(
   586  		trace.TableSessionTransactionRollbackDoneInfo,
   587  	) {
   588  		if d.Details()&trace.TableSessionTransactionEvents == 0 {
   589  			return nil
   590  		}
   591  		ctx := with(*info.Context, TRACE, "ydb", "table", "session", "tx", "rollback")
   592  		session := info.Session
   593  		tx := info.Tx
   594  		l.Log(ctx, "start",
   595  			String("id", session.ID()),
   596  			String("status", session.Status()),
   597  			String("tx", tx.ID()),
   598  		)
   599  		start := time.Now()
   600  
   601  		return func(info trace.TableSessionTransactionRollbackDoneInfo) {
   602  			if info.Error == nil {
   603  				l.Log(ctx, "done",
   604  					latencyField(start),
   605  					String("id", session.ID()),
   606  					String("status", session.Status()),
   607  					String("tx", tx.ID()),
   608  				)
   609  			} else {
   610  				l.Log(WithLevel(ctx, ERROR), "failed",
   611  					latencyField(start),
   612  					String("id", session.ID()),
   613  					String("status", session.Status()),
   614  					String("tx", tx.ID()),
   615  					Error(info.Error),
   616  					versionField(),
   617  				)
   618  			}
   619  		}
   620  	}
   621  	t.OnInit = func(info trace.TableInitStartInfo) func(trace.TableInitDoneInfo) {
   622  		if d.Details()&trace.TableEvents == 0 {
   623  			return nil
   624  		}
   625  		ctx := with(*info.Context, TRACE, "ydb", "table", "init")
   626  		l.Log(ctx, "start")
   627  		start := time.Now()
   628  
   629  		return func(info trace.TableInitDoneInfo) {
   630  			l.Log(WithLevel(ctx, INFO), "done",
   631  				latencyField(start),
   632  				Int("size_max", info.Limit),
   633  			)
   634  		}
   635  	}
   636  	t.OnClose = func(info trace.TableCloseStartInfo) func(trace.TableCloseDoneInfo) {
   637  		if d.Details()&trace.TableEvents == 0 {
   638  			return nil
   639  		}
   640  		ctx := with(*info.Context, TRACE, "ydb", "table", "close")
   641  		l.Log(ctx, "start")
   642  		start := time.Now()
   643  
   644  		return func(info trace.TableCloseDoneInfo) {
   645  			if info.Error == nil {
   646  				l.Log(WithLevel(ctx, INFO), "done",
   647  					latencyField(start),
   648  				)
   649  			} else {
   650  				l.Log(WithLevel(ctx, ERROR), "failed",
   651  					latencyField(start),
   652  					Error(info.Error),
   653  					versionField(),
   654  				)
   655  			}
   656  		}
   657  	}
   658  	t.OnPoolStateChange = func(info trace.TablePoolStateChangeInfo) {
   659  		if d.Details()&trace.TablePoolLifeCycleEvents == 0 {
   660  			return
   661  		}
   662  		ctx := with(context.Background(), TRACE, "ydb", "table", "pool", "state", "change")
   663  		l.Log(WithLevel(ctx, DEBUG), "",
   664  			Int("size", info.Size),
   665  			String("event", info.Event),
   666  		)
   667  	}
   668  	t.OnPoolSessionAdd = func(info trace.TablePoolSessionAddInfo) {
   669  		if d.Details()&trace.TablePoolLifeCycleEvents == 0 {
   670  			return
   671  		}
   672  		ctx := with(context.Background(), TRACE, "ydb", "table", "pool", "session", "add")
   673  		l.Log(ctx, "start",
   674  			String("id", info.Session.ID()),
   675  			String("status", info.Session.Status()),
   676  		)
   677  	}
   678  	t.OnPoolSessionRemove = func(info trace.TablePoolSessionRemoveInfo) {
   679  		if d.Details()&trace.TablePoolLifeCycleEvents == 0 {
   680  			return
   681  		}
   682  		ctx := with(context.Background(), TRACE, "ydb", "table", "pool", "session", "remove")
   683  		l.Log(ctx, "start",
   684  			String("id", info.Session.ID()),
   685  			String("status", info.Session.Status()),
   686  		)
   687  	}
   688  	t.OnPoolPut = func(info trace.TablePoolPutStartInfo) func(trace.TablePoolPutDoneInfo) {
   689  		if d.Details()&trace.TablePoolAPIEvents == 0 {
   690  			return nil
   691  		}
   692  		ctx := with(*info.Context, TRACE, "ydb", "table", "pool", "put")
   693  		session := info.Session
   694  		l.Log(ctx, "start",
   695  			String("id", session.ID()),
   696  			String("status", session.Status()),
   697  		)
   698  		start := time.Now()
   699  
   700  		return func(info trace.TablePoolPutDoneInfo) {
   701  			if info.Error == nil {
   702  				l.Log(ctx, "done",
   703  					latencyField(start),
   704  					String("id", session.ID()),
   705  					String("status", session.Status()),
   706  				)
   707  			} else {
   708  				l.Log(WithLevel(ctx, ERROR), "failed",
   709  					latencyField(start),
   710  					String("id", session.ID()),
   711  					String("status", session.Status()),
   712  					Error(info.Error),
   713  					versionField(),
   714  				)
   715  			}
   716  		}
   717  	}
   718  	t.OnPoolGet = func(info trace.TablePoolGetStartInfo) func(trace.TablePoolGetDoneInfo) {
   719  		if d.Details()&trace.TablePoolAPIEvents == 0 {
   720  			return nil
   721  		}
   722  		ctx := with(*info.Context, TRACE, "ydb", "table", "pool", "get")
   723  		l.Log(ctx, "start")
   724  		start := time.Now()
   725  
   726  		return func(info trace.TablePoolGetDoneInfo) {
   727  			if info.Error == nil {
   728  				session := info.Session
   729  				l.Log(ctx, "done",
   730  					latencyField(start),
   731  					String("id", session.ID()),
   732  					String("status", session.Status()),
   733  					Int("attempts", info.Attempts),
   734  				)
   735  			} else {
   736  				l.Log(WithLevel(ctx, WARN), "failed",
   737  					latencyField(start),
   738  					Int("attempts", info.Attempts),
   739  					Error(info.Error),
   740  					versionField(),
   741  				)
   742  			}
   743  		}
   744  	}
   745  	t.OnPoolWait = func(info trace.TablePoolWaitStartInfo) func(trace.TablePoolWaitDoneInfo) {
   746  		if d.Details()&trace.TablePoolAPIEvents == 0 {
   747  			return nil
   748  		}
   749  		ctx := with(*info.Context, TRACE, "ydb", "table", "pool", "wait")
   750  		l.Log(ctx, "start")
   751  		start := time.Now()
   752  
   753  		return func(info trace.TablePoolWaitDoneInfo) {
   754  			fields := []Field{
   755  				latencyField(start),
   756  			}
   757  			if info.Session != nil {
   758  				fields = append(fields,
   759  					String("id", info.Session.ID()),
   760  					String("status", info.Session.Status()),
   761  				)
   762  			}
   763  			if info.Error == nil {
   764  				l.Log(ctx, "done", fields...)
   765  			} else {
   766  				fields = append(fields, Error(info.Error))
   767  				l.Log(WithLevel(ctx, WARN), "failed", fields...)
   768  			}
   769  		}
   770  	}
   771  
   772  	return t
   773  }