github.com/ydb-platform/ydb-go-sdk/v3@v3.89.2/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/kv"
     8  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
     9  	"github.com/ydb-platform/ydb-go-sdk/v3/retry"
    10  	"github.com/ydb-platform/ydb-go-sdk/v3/trace"
    11  )
    12  
    13  // Table makes trace.Table with logging events from details
    14  func Table(l Logger, d trace.Detailer, opts ...Option) (t trace.Table) {
    15  	return internalTable(wrapLogger(l, opts...), d)
    16  }
    17  
    18  //nolint:gocyclo,funlen
    19  func internalTable(l *wrapper, d trace.Detailer) (t trace.Table) {
    20  	return trace.Table{
    21  		OnInit: func(info trace.TableInitStartInfo) func(trace.TableInitDoneInfo) {
    22  			if d.Details()&trace.TableEvents == 0 {
    23  				return nil
    24  			}
    25  			ctx := with(*info.Context, TRACE, "ydb", "table", "init")
    26  			l.Log(ctx, "start")
    27  			start := time.Now()
    28  
    29  			return func(info trace.TableInitDoneInfo) {
    30  				l.Log(WithLevel(ctx, INFO), "done",
    31  					kv.Latency(start),
    32  					kv.Int("size_max", info.Limit),
    33  				)
    34  			}
    35  		},
    36  		OnClose: func(info trace.TableCloseStartInfo) func(trace.TableCloseDoneInfo) {
    37  			if d.Details()&trace.TableEvents == 0 {
    38  				return nil
    39  			}
    40  			ctx := with(*info.Context, TRACE, "ydb", "table", "close")
    41  			l.Log(ctx, "start")
    42  			start := time.Now()
    43  
    44  			return func(info trace.TableCloseDoneInfo) {
    45  				if info.Error == nil {
    46  					l.Log(WithLevel(ctx, INFO), "done",
    47  						kv.Latency(start),
    48  					)
    49  				} else {
    50  					l.Log(WithLevel(ctx, ERROR), "failed",
    51  						kv.Latency(start),
    52  						kv.Error(info.Error),
    53  						kv.Version(),
    54  					)
    55  				}
    56  			}
    57  		},
    58  		OnDo: func(
    59  			info trace.TableDoStartInfo,
    60  		) func(
    61  			trace.TableDoDoneInfo,
    62  		) {
    63  			if d.Details()&trace.TablePoolAPIEvents == 0 {
    64  				return nil
    65  			}
    66  			ctx := with(*info.Context, TRACE, "ydb", "table", "do")
    67  			idempotent := info.Idempotent
    68  			label := info.Label
    69  			l.Log(ctx, "start",
    70  				kv.Bool("idempotent", idempotent),
    71  				kv.String("label", label),
    72  			)
    73  			start := time.Now()
    74  
    75  			return func(info trace.TableDoDoneInfo) {
    76  				if info.Error == nil {
    77  					l.Log(ctx, "done",
    78  						kv.Latency(start),
    79  						kv.Bool("idempotent", idempotent),
    80  						kv.String("label", label),
    81  						kv.Int("attempts", info.Attempts),
    82  					)
    83  				} else {
    84  					lvl := ERROR
    85  					if !xerrors.IsYdb(info.Error) {
    86  						lvl = DEBUG
    87  					}
    88  					m := retry.Check(info.Error)
    89  					l.Log(WithLevel(ctx, lvl), "done",
    90  						kv.Latency(start),
    91  						kv.Bool("idempotent", idempotent),
    92  						kv.String("label", label),
    93  						kv.Int("attempts", info.Attempts),
    94  						kv.Error(info.Error),
    95  						kv.Bool("retryable", m.MustRetry(idempotent)),
    96  						kv.Int64("code", m.StatusCode()),
    97  						kv.Bool("deleteSession", m.IsRetryObjectValid()),
    98  						kv.Version(),
    99  					)
   100  				}
   101  			}
   102  		},
   103  		OnDoTx: func(
   104  			info trace.TableDoTxStartInfo,
   105  		) func(
   106  			trace.TableDoTxDoneInfo,
   107  		) {
   108  			if d.Details()&trace.TablePoolAPIEvents == 0 {
   109  				return nil
   110  			}
   111  			ctx := with(*info.Context, TRACE, "ydb", "table", "do", "tx")
   112  			idempotent := info.Idempotent
   113  			label := info.Label
   114  			l.Log(ctx, "start",
   115  				kv.Bool("idempotent", idempotent),
   116  				kv.String("label", label),
   117  			)
   118  			start := time.Now()
   119  
   120  			return func(info trace.TableDoTxDoneInfo) {
   121  				if info.Error == nil {
   122  					l.Log(ctx, "done",
   123  						kv.Latency(start),
   124  						kv.Bool("idempotent", idempotent),
   125  						kv.String("label", label),
   126  						kv.Int("attempts", info.Attempts),
   127  					)
   128  				} else {
   129  					lvl := WARN
   130  					if !xerrors.IsYdb(info.Error) {
   131  						lvl = DEBUG
   132  					}
   133  					m := retry.Check(info.Error)
   134  					l.Log(WithLevel(ctx, lvl), "done",
   135  						kv.Latency(start),
   136  						kv.Bool("idempotent", idempotent),
   137  						kv.String("label", label),
   138  						kv.Int("attempts", info.Attempts),
   139  						kv.Error(info.Error),
   140  						kv.Bool("retryable", m.MustRetry(idempotent)),
   141  						kv.Int64("code", m.StatusCode()),
   142  						kv.Bool("deleteSession", m.IsRetryObjectValid()),
   143  						kv.Version(),
   144  					)
   145  				}
   146  			}
   147  		},
   148  		OnCreateSession: func(
   149  			info trace.TableCreateSessionStartInfo,
   150  		) func(
   151  			trace.TableCreateSessionDoneInfo,
   152  		) {
   153  			if d.Details()&trace.TablePoolAPIEvents == 0 {
   154  				return nil
   155  			}
   156  			ctx := with(*info.Context, TRACE, "ydb", "table", "create", "session")
   157  			l.Log(ctx, "start")
   158  			start := time.Now()
   159  
   160  			return func(info trace.TableCreateSessionDoneInfo) {
   161  				if info.Error == nil {
   162  					l.Log(ctx, "done",
   163  						kv.Latency(start),
   164  						kv.Int("attempts", info.Attempts),
   165  						kv.String("session_id", info.Session.ID()),
   166  						kv.String("session_status", info.Session.Status()),
   167  					)
   168  				} else {
   169  					l.Log(WithLevel(ctx, ERROR), "failed",
   170  						kv.Latency(start),
   171  						kv.Int("attempts", info.Attempts),
   172  						kv.Error(info.Error),
   173  						kv.Version(),
   174  					)
   175  				}
   176  			}
   177  		},
   178  		OnSessionNew: func(info trace.TableSessionNewStartInfo) func(trace.TableSessionNewDoneInfo) {
   179  			if d.Details()&trace.TableSessionEvents == 0 {
   180  				return nil
   181  			}
   182  			ctx := with(*info.Context, TRACE, "ydb", "table", "session", "new")
   183  			l.Log(ctx, "start")
   184  			start := time.Now()
   185  
   186  			return func(info trace.TableSessionNewDoneInfo) {
   187  				if info.Error == nil {
   188  					if info.Session != nil {
   189  						l.Log(ctx, "done",
   190  							kv.Latency(start),
   191  							kv.String("id", info.Session.ID()),
   192  						)
   193  					} else {
   194  						l.Log(WithLevel(ctx, WARN), "failed",
   195  							kv.Latency(start),
   196  							kv.Version(),
   197  						)
   198  					}
   199  				} else {
   200  					l.Log(WithLevel(ctx, WARN), "failed",
   201  						kv.Latency(start),
   202  						kv.Error(info.Error),
   203  						kv.Version(),
   204  					)
   205  				}
   206  			}
   207  		},
   208  		OnSessionDelete: func(info trace.TableSessionDeleteStartInfo) func(trace.TableSessionDeleteDoneInfo) {
   209  			if d.Details()&trace.TableSessionEvents == 0 {
   210  				return nil
   211  			}
   212  			ctx := with(*info.Context, TRACE, "ydb", "table", "session", "delete")
   213  			session := info.Session
   214  			l.Log(ctx, "start",
   215  				kv.String("id", info.Session.ID()),
   216  				kv.String("status", info.Session.Status()),
   217  			)
   218  			start := time.Now()
   219  
   220  			return func(info trace.TableSessionDeleteDoneInfo) {
   221  				if info.Error == nil {
   222  					l.Log(ctx, "done",
   223  						kv.Latency(start),
   224  						kv.String("id", session.ID()),
   225  						kv.String("status", session.Status()),
   226  					)
   227  				} else {
   228  					l.Log(WithLevel(ctx, WARN), "failed",
   229  						kv.Latency(start),
   230  						kv.String("id", session.ID()),
   231  						kv.String("status", session.Status()),
   232  						kv.Error(info.Error),
   233  						kv.Version(),
   234  					)
   235  				}
   236  			}
   237  		},
   238  		OnSessionKeepAlive: func(info trace.TableKeepAliveStartInfo) func(trace.TableKeepAliveDoneInfo) {
   239  			if d.Details()&trace.TableSessionEvents == 0 {
   240  				return nil
   241  			}
   242  			ctx := with(*info.Context, TRACE, "ydb", "table", "session", "keep", "alive")
   243  			session := info.Session
   244  			l.Log(ctx, "start",
   245  				kv.String("id", session.ID()),
   246  				kv.String("status", session.Status()),
   247  			)
   248  			start := time.Now()
   249  
   250  			return func(info trace.TableKeepAliveDoneInfo) {
   251  				if info.Error == nil {
   252  					l.Log(ctx, "done",
   253  						kv.Latency(start),
   254  						kv.String("id", session.ID()),
   255  						kv.String("status", session.Status()),
   256  					)
   257  				} else {
   258  					l.Log(WithLevel(ctx, WARN), "failed",
   259  						kv.Latency(start),
   260  						kv.String("id", session.ID()),
   261  						kv.String("status", session.Status()),
   262  						kv.Error(info.Error),
   263  						kv.Version(),
   264  					)
   265  				}
   266  			}
   267  		},
   268  		OnSessionQueryPrepare: func(
   269  			info trace.TablePrepareDataQueryStartInfo,
   270  		) func(
   271  			trace.TablePrepareDataQueryDoneInfo,
   272  		) {
   273  			if d.Details()&trace.TableSessionQueryInvokeEvents == 0 {
   274  				return nil
   275  			}
   276  			ctx := with(*info.Context, TRACE, "ydb", "table", "session", "query", "prepare")
   277  			session := info.Session
   278  			query := info.Query
   279  			l.Log(ctx, "start",
   280  				appendFieldByCondition(l.logQuery,
   281  					kv.String("query", info.Query),
   282  					kv.String("id", session.ID()),
   283  					kv.String("status", session.Status()),
   284  				)...,
   285  			)
   286  			start := time.Now()
   287  
   288  			return func(info trace.TablePrepareDataQueryDoneInfo) {
   289  				if info.Error == nil {
   290  					l.Log(ctx, "done",
   291  						appendFieldByCondition(l.logQuery,
   292  							kv.Stringer("result", info.Result),
   293  							appendFieldByCondition(l.logQuery,
   294  								kv.String("query", query),
   295  								kv.String("id", session.ID()),
   296  								kv.String("status", session.Status()),
   297  								kv.Latency(start),
   298  							)...,
   299  						)...,
   300  					)
   301  				} else {
   302  					l.Log(WithLevel(ctx, ERROR), "failed",
   303  						appendFieldByCondition(l.logQuery,
   304  							kv.String("query", query),
   305  							kv.Error(info.Error),
   306  							kv.String("id", session.ID()),
   307  							kv.String("status", session.Status()),
   308  							kv.Latency(start),
   309  							kv.Version(),
   310  						)...,
   311  					)
   312  				}
   313  			}
   314  		},
   315  		OnSessionQueryExecute: func(
   316  			info trace.TableExecuteDataQueryStartInfo,
   317  		) func(
   318  			trace.TableExecuteDataQueryDoneInfo,
   319  		) {
   320  			if d.Details()&trace.TableSessionQueryInvokeEvents == 0 {
   321  				return nil
   322  			}
   323  			ctx := with(*info.Context, TRACE, "ydb", "table", "session", "query", "execute")
   324  			session := info.Session
   325  			query := info.Query
   326  			l.Log(ctx, "start",
   327  				appendFieldByCondition(l.logQuery,
   328  					kv.Stringer("query", info.Query),
   329  					kv.String("id", session.ID()),
   330  					kv.String("status", session.Status()),
   331  				)...,
   332  			)
   333  			start := time.Now()
   334  
   335  			return func(info trace.TableExecuteDataQueryDoneInfo) {
   336  				if info.Error == nil {
   337  					tx := info.Tx
   338  					l.Log(ctx, "done",
   339  						appendFieldByCondition(l.logQuery,
   340  							kv.Stringer("query", query),
   341  							kv.String("id", session.ID()),
   342  							kv.String("tx", tx.ID()),
   343  							kv.String("status", session.Status()),
   344  							kv.Bool("prepared", info.Prepared),
   345  							kv.NamedError("result_err", info.Result.Err()),
   346  							kv.Latency(start),
   347  						)...,
   348  					)
   349  				} else {
   350  					l.Log(WithLevel(ctx, ERROR), "failed",
   351  						appendFieldByCondition(l.logQuery,
   352  							kv.Stringer("query", query),
   353  							kv.Error(info.Error),
   354  							kv.String("id", session.ID()),
   355  							kv.String("status", session.Status()),
   356  							kv.Bool("prepared", info.Prepared),
   357  							kv.Latency(start),
   358  							kv.Version(),
   359  						)...,
   360  					)
   361  				}
   362  			}
   363  		},
   364  		OnSessionQueryStreamExecute: func(
   365  			info trace.TableSessionQueryStreamExecuteStartInfo,
   366  		) func(
   367  			trace.TableSessionQueryStreamExecuteDoneInfo,
   368  		) {
   369  			if d.Details()&trace.TableSessionQueryStreamEvents == 0 {
   370  				return nil
   371  			}
   372  			ctx := with(*info.Context, TRACE, "ydb", "table", "session", "query", "stream", "execute")
   373  			session := info.Session
   374  			query := info.Query
   375  			l.Log(ctx, "start",
   376  				appendFieldByCondition(l.logQuery,
   377  					kv.Stringer("query", info.Query),
   378  					kv.String("id", session.ID()),
   379  					kv.String("status", session.Status()),
   380  				)...,
   381  			)
   382  			start := time.Now()
   383  
   384  			return func(info trace.TableSessionQueryStreamExecuteDoneInfo) {
   385  				if info.Error == nil {
   386  					l.Log(ctx, "done",
   387  						appendFieldByCondition(l.logQuery,
   388  							kv.Stringer("query", query),
   389  							kv.Error(info.Error),
   390  							kv.String("id", session.ID()),
   391  							kv.String("status", session.Status()),
   392  							kv.Latency(start),
   393  						)...,
   394  					)
   395  				} else {
   396  					l.Log(WithLevel(ctx, ERROR), "failed",
   397  						appendFieldByCondition(l.logQuery,
   398  							kv.Stringer("query", query),
   399  							kv.Error(info.Error),
   400  							kv.String("id", session.ID()),
   401  							kv.String("status", session.Status()),
   402  							kv.Latency(start),
   403  							kv.Version(),
   404  						)...,
   405  					)
   406  				}
   407  			}
   408  		},
   409  		OnSessionQueryStreamRead: func(
   410  			info trace.TableSessionQueryStreamReadStartInfo,
   411  		) func(
   412  			trace.TableSessionQueryStreamReadDoneInfo,
   413  		) {
   414  			if d.Details()&trace.TableSessionQueryStreamEvents == 0 {
   415  				return nil
   416  			}
   417  			ctx := with(*info.Context, TRACE, "ydb", "table", "session", "query", "stream", "read")
   418  			session := info.Session
   419  			l.Log(ctx, "start",
   420  				kv.String("id", session.ID()),
   421  				kv.String("status", session.Status()),
   422  			)
   423  			start := time.Now()
   424  
   425  			return func(info trace.TableSessionQueryStreamReadDoneInfo) {
   426  				if info.Error == nil {
   427  					l.Log(ctx, "done",
   428  						kv.Latency(start),
   429  						kv.String("id", session.ID()),
   430  						kv.String("status", session.Status()),
   431  					)
   432  				} else {
   433  					l.Log(WithLevel(ctx, ERROR), "failed",
   434  						kv.Latency(start),
   435  						kv.String("id", session.ID()),
   436  						kv.String("status", session.Status()),
   437  						kv.Error(info.Error),
   438  						kv.Version(),
   439  					)
   440  				}
   441  			}
   442  		},
   443  		OnTxBegin: func(
   444  			info trace.TableTxBeginStartInfo,
   445  		) func(
   446  			trace.TableTxBeginDoneInfo,
   447  		) {
   448  			if d.Details()&trace.TableSessionTransactionEvents == 0 {
   449  				return nil
   450  			}
   451  			ctx := with(*info.Context, TRACE, "ydb", "table", "session", "tx", "begin")
   452  			session := info.Session
   453  			l.Log(ctx, "start",
   454  				kv.String("id", session.ID()),
   455  				kv.String("status", session.Status()),
   456  			)
   457  			start := time.Now()
   458  
   459  			return func(info trace.TableTxBeginDoneInfo) {
   460  				if info.Error == nil {
   461  					l.Log(ctx, "done",
   462  						kv.Latency(start),
   463  						kv.String("id", session.ID()),
   464  						kv.String("status", session.Status()),
   465  						kv.String("tx", info.Tx.ID()),
   466  					)
   467  				} else {
   468  					l.Log(WithLevel(ctx, WARN), "failed",
   469  						kv.Latency(start),
   470  						kv.String("id", session.ID()),
   471  						kv.String("status", session.Status()),
   472  						kv.Error(info.Error),
   473  						kv.Version(),
   474  					)
   475  				}
   476  			}
   477  		},
   478  		OnTxCommit: func(info trace.TableTxCommitStartInfo) func(trace.TableTxCommitDoneInfo) {
   479  			if d.Details()&trace.TableSessionTransactionEvents == 0 {
   480  				return nil
   481  			}
   482  			ctx := with(*info.Context, TRACE, "ydb", "table", "session", "tx", "commit")
   483  			session := info.Session
   484  			tx := info.Tx
   485  			l.Log(ctx, "start",
   486  				kv.String("id", session.ID()),
   487  				kv.String("status", session.Status()),
   488  				kv.String("tx", info.Tx.ID()),
   489  			)
   490  			start := time.Now()
   491  
   492  			return func(info trace.TableTxCommitDoneInfo) {
   493  				if info.Error == nil {
   494  					l.Log(ctx, "done",
   495  						kv.Latency(start),
   496  						kv.String("id", session.ID()),
   497  						kv.String("status", session.Status()),
   498  						kv.String("tx", tx.ID()),
   499  					)
   500  				} else {
   501  					l.Log(WithLevel(ctx, ERROR), "failed",
   502  						kv.Latency(start),
   503  						kv.String("id", session.ID()),
   504  						kv.String("status", session.Status()),
   505  						kv.String("tx", tx.ID()),
   506  						kv.Error(info.Error),
   507  						kv.Version(),
   508  					)
   509  				}
   510  			}
   511  		},
   512  		OnTxRollback: func(
   513  			info trace.TableTxRollbackStartInfo,
   514  		) func(
   515  			trace.TableTxRollbackDoneInfo,
   516  		) {
   517  			if d.Details()&trace.TableSessionTransactionEvents == 0 {
   518  				return nil
   519  			}
   520  			ctx := with(*info.Context, TRACE, "ydb", "table", "session", "tx", "rollback")
   521  			session := info.Session
   522  			tx := info.Tx
   523  			l.Log(ctx, "start",
   524  				kv.String("id", session.ID()),
   525  				kv.String("status", session.Status()),
   526  				kv.String("tx", tx.ID()),
   527  			)
   528  			start := time.Now()
   529  
   530  			return func(info trace.TableTxRollbackDoneInfo) {
   531  				if info.Error == nil {
   532  					l.Log(ctx, "done",
   533  						kv.Latency(start),
   534  						kv.String("id", session.ID()),
   535  						kv.String("status", session.Status()),
   536  						kv.String("tx", tx.ID()),
   537  					)
   538  				} else {
   539  					l.Log(WithLevel(ctx, ERROR), "failed",
   540  						kv.Latency(start),
   541  						kv.String("id", session.ID()),
   542  						kv.String("status", session.Status()),
   543  						kv.String("tx", tx.ID()),
   544  						kv.Error(info.Error),
   545  						kv.Version(),
   546  					)
   547  				}
   548  			}
   549  		},
   550  		OnPoolPut: func(info trace.TablePoolPutStartInfo) func(trace.TablePoolPutDoneInfo) {
   551  			if d.Details()&trace.TablePoolAPIEvents == 0 {
   552  				return nil
   553  			}
   554  			ctx := with(*info.Context, TRACE, "ydb", "table", "pool", "put")
   555  			session := info.Session
   556  			l.Log(ctx, "start",
   557  				kv.String("id", session.ID()),
   558  				kv.String("status", session.Status()),
   559  			)
   560  			start := time.Now()
   561  
   562  			return func(info trace.TablePoolPutDoneInfo) {
   563  				if info.Error == nil {
   564  					l.Log(ctx, "done",
   565  						kv.Latency(start),
   566  						kv.String("id", session.ID()),
   567  						kv.String("status", session.Status()),
   568  					)
   569  				} else {
   570  					l.Log(WithLevel(ctx, ERROR), "failed",
   571  						kv.Latency(start),
   572  						kv.String("id", session.ID()),
   573  						kv.String("status", session.Status()),
   574  						kv.Error(info.Error),
   575  						kv.Version(),
   576  					)
   577  				}
   578  			}
   579  		},
   580  		OnPoolGet: func(info trace.TablePoolGetStartInfo) func(trace.TablePoolGetDoneInfo) {
   581  			if d.Details()&trace.TablePoolAPIEvents == 0 {
   582  				return nil
   583  			}
   584  			ctx := with(*info.Context, TRACE, "ydb", "table", "pool", "get")
   585  			l.Log(ctx, "start")
   586  			start := time.Now()
   587  
   588  			return func(info trace.TablePoolGetDoneInfo) {
   589  				if info.Error == nil {
   590  					session := info.Session
   591  					l.Log(ctx, "done",
   592  						kv.Latency(start),
   593  						kv.String("id", session.ID()),
   594  						kv.String("status", session.Status()),
   595  						kv.Int("attempts", info.Attempts),
   596  					)
   597  				} else {
   598  					l.Log(WithLevel(ctx, WARN), "failed",
   599  						kv.Latency(start),
   600  						kv.Int("attempts", info.Attempts),
   601  						kv.Error(info.Error),
   602  						kv.Version(),
   603  					)
   604  				}
   605  			}
   606  		},
   607  		OnPoolStateChange: func(info trace.TablePoolStateChangeInfo) {
   608  			if d.Details()&trace.TablePoolLifeCycleEvents == 0 {
   609  				return
   610  			}
   611  			ctx := with(context.Background(), TRACE, "ydb", "table", "pool", "state", "change")
   612  			l.Log(WithLevel(ctx, DEBUG), "",
   613  				kv.Int("limit", info.Limit),
   614  				kv.Int("index", info.Index),
   615  				kv.Int("idle", info.Idle),
   616  				kv.Int("wait", info.Wait),
   617  				kv.Int("create_in_progress", info.CreateInProgress),
   618  			)
   619  		},
   620  		OnSessionBulkUpsert:   nil,
   621  		OnSessionQueryExplain: nil,
   622  		OnTxExecute:           nil,
   623  		OnTxExecuteStatement:  nil,
   624  		OnPoolWith:            nil,
   625  	}
   626  }