Changeset 407 in code for trunk/logger.go


Ignore:
Timestamp:
Aug 20, 2020, 6:05:01 PM (5 years ago)
Author:
contact
Message:

Introduce internal message IDs

For now, these can be used as cursors in the logs. Future patches will
introduce functions that perform log queries with message IDs.

The IDs are state-less tokens containing all the required information to
refer to an on-disk log line: network name, entity name, date and byte
offset. The byte offset doesn't need to point to the first byte of the
line, any byte will do (note, this makes it so message IDs aren't
necessarily unique, we may want to change that in the future).

These internal message IDs are not exposed to clients because we don't
support upstream message IDs yet.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/logger.go

    r397 r407  
    44        "bufio"
    55        "fmt"
     6        "io"
    67        "os"
    78        "path/filepath"
     
    4041}
    4142
    42 func (ml *messageLogger) Append(msg *irc.Message) error {
     43func parseMsgID(s string) (network, entity string, t time.Time, offset int64, err error) {
     44        var year, month, day int
     45        _, err = fmt.Sscanf(s, "%s %s %04d-%02d-%02d %d", &network, &entity, &year, &month, &day, &offset)
     46        if err != nil {
     47                return "", "", time.Time{}, 0, fmt.Errorf("invalid message ID: %v", err)
     48        }
     49        t = time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.Local)
     50        return network, entity, t, offset, nil
     51}
     52
     53func formatMsgID(network, entity string, t time.Time, offset int64) string {
     54        year, month, day := t.Date()
     55        return fmt.Sprintf("%s %s %04d-%02d-%02d %d", network, entity, year, month, day, offset)
     56}
     57
     58// nextMsgID queries the message ID for the next message to be written to f.
     59func nextMsgID(network *network, entity string, t time.Time, f *os.File) (string, error) {
     60        offset, err := f.Seek(0, io.SeekEnd)
     61        if err != nil {
     62                return "", err
     63        }
     64        return formatMsgID(network.GetName(), entity, t, offset), nil
     65}
     66
     67// lastMsgID queries the last message ID for the given network, entity and
     68// date. The message ID returned may not refer to a valid message, but can be
     69// used in history queries.
     70func lastMsgID(network *network, entity string, t time.Time) (string, error) {
     71        p := logPath(network, entity, t)
     72        fi, err := os.Stat(p)
     73        if os.IsNotExist(err) {
     74                return formatMsgID(network.GetName(), entity, t, -1), nil
     75        } else if err != nil {
     76                return "", err
     77        }
     78        return formatMsgID(network.GetName(), entity, t, fi.Size()-1), nil
     79}
     80
     81func (ml *messageLogger) Append(msg *irc.Message) (string, error) {
    4382        s := formatMessage(msg)
    4483        if s == "" {
    45                 return nil
     84                return "", nil
    4685        }
    4786
     
    5190                t, err = time.Parse(serverTimeLayout, string(tag))
    5291                if err != nil {
    53                         return fmt.Errorf("failed to parse message time tag: %v", err)
     92                        return "", fmt.Errorf("failed to parse message time tag: %v", err)
    5493                }
    5594                t = t.In(time.Local)
     
    68107                dir := filepath.Dir(path)
    69108                if err := os.MkdirAll(dir, 0700); err != nil {
    70                         return fmt.Errorf("failed to create logs directory %q: %v", dir, err)
     109                        return "", fmt.Errorf("failed to create logs directory %q: %v", dir, err)
    71110                }
    72111
    73112                f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600)
    74113                if err != nil {
    75                         return fmt.Errorf("failed to open log file %q: %v", path, err)
     114                        return "", fmt.Errorf("failed to open log file %q: %v", path, err)
    76115                }
    77116
     
    80119        }
    81120
    82         _, err := fmt.Fprintf(ml.file, "[%02d:%02d:%02d] %s\n", t.Hour(), t.Minute(), t.Second(), s)
    83         if err != nil {
    84                 return fmt.Errorf("failed to log message to %q: %v", ml.path, err)
    85         }
    86         return nil
     121        msgID, err := nextMsgID(ml.network, ml.entity, t, ml.file)
     122        if err != nil {
     123                return "", fmt.Errorf("failed to generate message ID: %v", err)
     124        }
     125
     126        _, err = fmt.Fprintf(ml.file, "[%02d:%02d:%02d] %s\n", t.Hour(), t.Minute(), t.Second(), s)
     127        if err != nil {
     128                return "", fmt.Errorf("failed to log message to %q: %v", ml.path, err)
     129        }
     130        return msgID, nil
    87131}
    88132
Note: See TracChangeset for help on using the changeset viewer.