go.mercari.io/datastore@v1.8.2/dsmiddleware/dslog/dslog.go (about)

     1  package dslog
     2  
     3  import (
     4  	"context"
     5  	"strings"
     6  	"sync"
     7  
     8  	"go.mercari.io/datastore"
     9  )
    10  
    11  var _ datastore.Middleware = &logger{}
    12  
    13  // NewLogger returns with specified logger function.
    14  func NewLogger(prefix string, logf func(ctx context.Context, format string, args ...interface{})) datastore.Middleware {
    15  	return &logger{Prefix: prefix, Logf: logf, counter: 1}
    16  }
    17  
    18  type contextTx struct{}
    19  
    20  type logger struct {
    21  	Prefix string
    22  	Logf   func(ctx context.Context, format string, args ...interface{})
    23  
    24  	m       sync.Mutex
    25  	counter int
    26  }
    27  
    28  type txPutEntity struct {
    29  	Index      int
    30  	Key        datastore.Key
    31  	PendingKey datastore.PendingKey
    32  }
    33  
    34  func (l *logger) KeysToString(keys []datastore.Key) string {
    35  	keyStrings := make([]string, 0, len(keys))
    36  	for _, key := range keys {
    37  		keyStrings = append(keyStrings, key.String())
    38  	}
    39  
    40  	return strings.Join(keyStrings, ", ")
    41  }
    42  
    43  func (l *logger) AllocateIDs(info *datastore.MiddlewareInfo, keys []datastore.Key) ([]datastore.Key, error) {
    44  	l.m.Lock()
    45  	cnt := l.counter
    46  	l.counter++
    47  	l.m.Unlock()
    48  
    49  	l.Logf(info.Context, l.Prefix+"AllocateIDs #%d, len(keys)=%d, keys=[%s]", cnt, len(keys), l.KeysToString(keys))
    50  
    51  	keys, err := info.Next.AllocateIDs(info, keys)
    52  
    53  	if err == nil {
    54  		l.Logf(info.Context, l.Prefix+"AllocateIDs #%d, keys=[%s]", cnt, l.KeysToString(keys))
    55  	} else {
    56  		l.Logf(info.Context, l.Prefix+"AllocateIDs #%d, err=%s", cnt, err.Error())
    57  	}
    58  
    59  	return keys, err
    60  }
    61  
    62  func (l *logger) PutMultiWithoutTx(info *datastore.MiddlewareInfo, keys []datastore.Key, psList []datastore.PropertyList) ([]datastore.Key, error) {
    63  	l.m.Lock()
    64  	cnt := l.counter
    65  	l.counter++
    66  	l.m.Unlock()
    67  
    68  	l.Logf(info.Context, l.Prefix+"PutMultiWithoutTx #%d, len(keys)=%d, keys=[%s]", cnt, len(keys), l.KeysToString(keys))
    69  
    70  	keys, err := info.Next.PutMultiWithoutTx(info, keys, psList)
    71  
    72  	if err == nil {
    73  		l.Logf(info.Context, l.Prefix+"PutMultiWithoutTx #%d, keys=[%s]", cnt, l.KeysToString(keys))
    74  	} else {
    75  		l.Logf(info.Context, l.Prefix+"PutMultiWithoutTx #%d, err=%s", cnt, err.Error())
    76  	}
    77  
    78  	return keys, err
    79  }
    80  
    81  func (l *logger) PutMultiWithTx(info *datastore.MiddlewareInfo, keys []datastore.Key, psList []datastore.PropertyList) ([]datastore.PendingKey, error) {
    82  	l.m.Lock()
    83  	cnt := l.counter
    84  	l.counter++
    85  	l.m.Unlock()
    86  
    87  	l.Logf(info.Context, l.Prefix+"PutMultiWithTx #%d, len(keys)=%d, keys=[%s]", cnt, len(keys), l.KeysToString(keys))
    88  
    89  	pKeys, err := info.Next.PutMultiWithTx(info, keys, psList)
    90  	if err != nil {
    91  		l.Logf(info.Context, l.Prefix+"PutMultiWithTx #%d, err=%s", cnt, err.Error())
    92  	}
    93  	if len(keys) != len(pKeys) {
    94  		l.Logf(info.Context, l.Prefix+"PutMultiWithTx #%d, keys length mismatch len(keys)=%d, len(pKeys)=%d", cnt, len(keys), len(pKeys))
    95  		return pKeys, err
    96  	}
    97  
    98  	lgTxPutMap, ok := info.Context.Value(contextTx{}).(map[*logger]map[datastore.Transaction][]*txPutEntity)
    99  	if !ok {
   100  		lgTxPutMap = make(map[*logger]map[datastore.Transaction][]*txPutEntity)
   101  		info.Context = context.WithValue(info.Context, contextTx{}, lgTxPutMap)
   102  	}
   103  	txPutMap, ok := lgTxPutMap[l]
   104  	if !ok {
   105  		txPutMap = make(map[datastore.Transaction][]*txPutEntity)
   106  		lgTxPutMap[l] = txPutMap
   107  	}
   108  	putLogs := txPutMap[info.Transaction]
   109  	for idx, key := range keys {
   110  		if key.Incomplete() {
   111  			putLogs = append(putLogs, &txPutEntity{PendingKey: pKeys[idx]})
   112  		} else {
   113  			putLogs = append(putLogs, &txPutEntity{Key: key})
   114  		}
   115  	}
   116  	lgTxPutMap[l][info.Transaction] = putLogs
   117  
   118  	return pKeys, err
   119  }
   120  
   121  func (l *logger) GetMultiWithoutTx(info *datastore.MiddlewareInfo, keys []datastore.Key, psList []datastore.PropertyList) error {
   122  	l.m.Lock()
   123  	cnt := l.counter
   124  	l.counter++
   125  	l.m.Unlock()
   126  
   127  	l.Logf(info.Context, l.Prefix+"GetMultiWithoutTx #%d, len(keys)=%d, keys=[%s]", cnt, len(keys), l.KeysToString(keys))
   128  
   129  	err := info.Next.GetMultiWithoutTx(info, keys, psList)
   130  
   131  	if err != nil {
   132  		l.Logf(info.Context, l.Prefix+"GetMultiWithoutTx #%d, err=%s", cnt, err.Error())
   133  	}
   134  
   135  	return err
   136  }
   137  
   138  func (l *logger) GetMultiWithTx(info *datastore.MiddlewareInfo, keys []datastore.Key, psList []datastore.PropertyList) error {
   139  	l.m.Lock()
   140  	cnt := l.counter
   141  	l.counter++
   142  	l.m.Unlock()
   143  
   144  	l.Logf(info.Context, l.Prefix+"GetMultiWithTx #%d, len(keys)=%d, keys=[%s]", cnt, len(keys), l.KeysToString(keys))
   145  
   146  	err := info.Next.GetMultiWithTx(info, keys, psList)
   147  
   148  	if err != nil {
   149  		l.Logf(info.Context, l.Prefix+"GetMultiWithTx #%d, err=%s", cnt, err.Error())
   150  	}
   151  
   152  	return err
   153  }
   154  
   155  func (l *logger) DeleteMultiWithoutTx(info *datastore.MiddlewareInfo, keys []datastore.Key) error {
   156  	l.m.Lock()
   157  	cnt := l.counter
   158  	l.counter++
   159  	l.m.Unlock()
   160  
   161  	l.Logf(info.Context, l.Prefix+"DeleteMultiWithoutTx #%d, len(keys)=%d, keys=[%s]", cnt, len(keys), l.KeysToString(keys))
   162  
   163  	err := info.Next.DeleteMultiWithoutTx(info, keys)
   164  
   165  	if err != nil {
   166  		l.Logf(info.Context, l.Prefix+"DeleteMultiWithoutTx #%d, err=%s", cnt, err.Error())
   167  	}
   168  
   169  	return err
   170  }
   171  
   172  func (l *logger) DeleteMultiWithTx(info *datastore.MiddlewareInfo, keys []datastore.Key) error {
   173  	l.m.Lock()
   174  	cnt := l.counter
   175  	l.counter++
   176  	l.m.Unlock()
   177  
   178  	l.Logf(info.Context, l.Prefix+"DeleteMultiWithTx #%d, len(keys)=%d, keys=[%s]", cnt, len(keys), l.KeysToString(keys))
   179  
   180  	err := info.Next.DeleteMultiWithTx(info, keys)
   181  
   182  	if err != nil {
   183  		l.Logf(info.Context, l.Prefix+"DeleteMultiWithTx #%d, err=%s", cnt, err.Error())
   184  	}
   185  
   186  	return err
   187  }
   188  
   189  func (l *logger) PostCommit(info *datastore.MiddlewareInfo, tx datastore.Transaction, commit datastore.Commit) error {
   190  	l.m.Lock()
   191  	cnt := l.counter
   192  	l.counter++
   193  	l.m.Unlock()
   194  
   195  	lgTxPutMap, ok := info.Context.Value(contextTx{}).(map[*logger]map[datastore.Transaction][]*txPutEntity)
   196  	if ok {
   197  		txPutMap, ok := lgTxPutMap[l]
   198  		if ok {
   199  			putLogs := txPutMap[info.Transaction]
   200  			delete(txPutMap, info.Transaction)
   201  			keys := make([]datastore.Key, 0, len(putLogs))
   202  			for _, putLog := range putLogs {
   203  				if putLog.Key != nil {
   204  					keys = append(keys, putLog.Key)
   205  					continue
   206  				}
   207  
   208  				key := commit.Key(putLog.PendingKey)
   209  				keys = append(keys, key)
   210  			}
   211  
   212  			l.Logf(info.Context, l.Prefix+"PostCommit #%d Put keys=[%s]", cnt, l.KeysToString(keys))
   213  
   214  			delete(txPutMap, info.Transaction)
   215  
   216  		} else {
   217  			l.Logf(info.Context, l.Prefix+"PostCommit #%d put log not contains in ctx", cnt)
   218  		}
   219  
   220  		if len(txPutMap) == 0 {
   221  			delete(lgTxPutMap, l)
   222  		}
   223  
   224  	} else {
   225  		l.Logf(info.Context, l.Prefix+"PostCommit #%d put log not contains in ctx", cnt)
   226  	}
   227  
   228  	return info.Next.PostCommit(info, tx, commit)
   229  }
   230  
   231  func (l *logger) PostRollback(info *datastore.MiddlewareInfo, tx datastore.Transaction) error {
   232  	l.m.Lock()
   233  	cnt := l.counter
   234  	l.counter++
   235  	l.m.Unlock()
   236  
   237  	l.Logf(info.Context, l.Prefix+"PostRollback #%d", cnt)
   238  
   239  	return info.Next.PostRollback(info, tx)
   240  }
   241  
   242  func (l *logger) Run(info *datastore.MiddlewareInfo, q datastore.Query, qDump *datastore.QueryDump) datastore.Iterator {
   243  	l.m.Lock()
   244  	cnt := l.counter
   245  	l.counter++
   246  	l.m.Unlock()
   247  
   248  	l.Logf(info.Context, l.Prefix+"Run #%d, q=%s", cnt, qDump.String())
   249  
   250  	return info.Next.Run(info, q, qDump)
   251  }
   252  
   253  func (l *logger) GetAll(info *datastore.MiddlewareInfo, q datastore.Query, qDump *datastore.QueryDump, psList *[]datastore.PropertyList) ([]datastore.Key, error) {
   254  	l.m.Lock()
   255  	cnt := l.counter
   256  	l.counter++
   257  	l.m.Unlock()
   258  
   259  	l.Logf(info.Context, l.Prefix+"GetAll #%d, q=%s", cnt, qDump.String())
   260  
   261  	keys, err := info.Next.GetAll(info, q, qDump, psList)
   262  
   263  	if err == nil {
   264  		l.Logf(info.Context, l.Prefix+"GetAll #%d, len(keys)=%d, keys=[%s]", cnt, len(keys), l.KeysToString(keys))
   265  	} else {
   266  		l.Logf(info.Context, l.Prefix+"GetAll #%d, err=%s", cnt, err.Error())
   267  	}
   268  
   269  	return keys, err
   270  }
   271  
   272  func (l *logger) Next(info *datastore.MiddlewareInfo, q datastore.Query, qDump *datastore.QueryDump, iter datastore.Iterator, ps *datastore.PropertyList) (datastore.Key, error) {
   273  	l.m.Lock()
   274  	cnt := l.counter
   275  	l.counter++
   276  	l.m.Unlock()
   277  
   278  	l.Logf(info.Context, l.Prefix+"Next #%d, q=%s", cnt, qDump.String())
   279  
   280  	key, err := info.Next.Next(info, q, qDump, iter, ps)
   281  
   282  	if err == nil {
   283  		l.Logf(info.Context, l.Prefix+"Next #%d, key=%s", cnt, key.String())
   284  	} else {
   285  		l.Logf(info.Context, l.Prefix+"Next #%d, err=%s", cnt, err.Error())
   286  	}
   287  
   288  	return key, err
   289  }
   290  
   291  func (l *logger) Count(info *datastore.MiddlewareInfo, q datastore.Query, qDump *datastore.QueryDump) (int, error) {
   292  	l.m.Lock()
   293  	cnt := l.counter
   294  	l.counter++
   295  	l.m.Unlock()
   296  
   297  	l.Logf(info.Context, l.Prefix+"Count #%d, q=%s", cnt, qDump.String())
   298  
   299  	ret, err := info.Next.Count(info, q, qDump)
   300  
   301  	if err == nil {
   302  		l.Logf(info.Context, l.Prefix+"Count #%d, ret=%d", cnt, ret)
   303  	} else {
   304  		l.Logf(info.Context, l.Prefix+"Count #%d, err=%s", cnt, err.Error())
   305  	}
   306  
   307  	return ret, err
   308  }