github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/debug/log/memory/memory.go (about)

     1  // Licensed under the Apache License, Version 2.0 (the "License");
     2  // you may not use this file except in compliance with the License.
     3  // You may obtain a copy of the License at
     4  //
     5  //     https://www.apache.org/licenses/LICENSE-2.0
     6  //
     7  // Unless required by applicable law or agreed to in writing, software
     8  // distributed under the License is distributed on an "AS IS" BASIS,
     9  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10  // See the License for the specific language governing permissions and
    11  // limitations under the License.
    12  //
    13  // Original source: github.com/micro/go-micro/v3/debug/log/memory/memory.go
    14  
    15  // Package memory provides an in memory log buffer
    16  package memory
    17  
    18  import (
    19  	"fmt"
    20  
    21  	"github.com/tickoalcantara12/micro/v3/service/debug/log"
    22  	"github.com/tickoalcantara12/micro/v3/util/ring"
    23  )
    24  
    25  // memoryLog is default micro log
    26  type memoryLog struct {
    27  	*ring.Buffer
    28  }
    29  
    30  // NewLog returns default Logger with
    31  func NewLog(opts ...log.Option) log.Log {
    32  	// get default options
    33  	options := log.DefaultOptions()
    34  
    35  	// apply requested options
    36  	for _, o := range opts {
    37  		o(&options)
    38  	}
    39  
    40  	return &memoryLog{
    41  		Buffer: ring.New(options.Size),
    42  	}
    43  }
    44  
    45  // Write writes logs into logger
    46  func (l *memoryLog) Write(r log.Record) error {
    47  	l.Buffer.Put(fmt.Sprint(r.Message))
    48  	return nil
    49  }
    50  
    51  // Read reads logs and returns them
    52  func (l *memoryLog) Read(opts ...log.ReadOption) ([]log.Record, error) {
    53  	options := log.ReadOptions{}
    54  	// initialize the read options
    55  	for _, o := range opts {
    56  		o(&options)
    57  	}
    58  
    59  	var entries []*ring.Entry
    60  	// if Since options ha sbeen specified we honor it
    61  	if !options.Since.IsZero() {
    62  		entries = l.Buffer.Since(options.Since)
    63  	}
    64  
    65  	// only if we specified valid count constraint
    66  	// do we end up doing some serious if-else kung-fu
    67  	// if since constraint has been provided
    68  	// we return *count* number of logs since the given timestamp;
    69  	// otherwise we return last count number of logs
    70  	if options.Count > 0 {
    71  		switch len(entries) > 0 {
    72  		case true:
    73  			// if we request fewer logs than what since constraint gives us
    74  			if options.Count < len(entries) {
    75  				entries = entries[0:options.Count]
    76  			}
    77  		default:
    78  			entries = l.Buffer.Get(options.Count)
    79  		}
    80  	}
    81  
    82  	records := make([]log.Record, 0, len(entries))
    83  	for _, entry := range entries {
    84  		record := log.Record{
    85  			Timestamp: entry.Timestamp,
    86  			Message:   entry.Value,
    87  		}
    88  		records = append(records, record)
    89  	}
    90  
    91  	return records, nil
    92  }
    93  
    94  // Stream returns channel for reading log records
    95  // along with a stop channel, close it when done
    96  func (l *memoryLog) Stream() (log.Stream, error) {
    97  	// get stream channel from ring buffer
    98  	stream, stop := l.Buffer.Stream()
    99  	// make a buffered channel
   100  	records := make(chan log.Record, 128)
   101  	// get last 10 records
   102  	last10 := l.Buffer.Get(10)
   103  
   104  	// stream the log records
   105  	go func() {
   106  		// first send last 10 records
   107  		for _, entry := range last10 {
   108  			records <- log.Record{
   109  				Timestamp: entry.Timestamp,
   110  				Message:   entry.Value,
   111  				Metadata:  make(map[string]string),
   112  			}
   113  		}
   114  		// now stream continuously
   115  		for entry := range stream {
   116  			records <- log.Record{
   117  				Timestamp: entry.Timestamp,
   118  				Message:   entry.Value,
   119  				Metadata:  make(map[string]string),
   120  			}
   121  		}
   122  	}()
   123  
   124  	return &logStream{
   125  		stream: records,
   126  		stop:   stop,
   127  	}, nil
   128  }