From 37cfa29c481dd504f80bca89dd3ab095736568c4 Mon Sep 17 00:00:00 2001 From: Giwook-Han <73291175+Giwook-Han@users.noreply.github.com> Date: Mon, 15 Apr 2024 19:53:44 +0900 Subject: [PATCH 1/7] use protobuf while communicate between peers --- network/p2p/p2p.go | 56 ++++++++++++++++++++++++++++++---------------- proto/interface.go | 6 +++++ proto/pbcodec.go | 13 +++++++++++ 3 files changed, 56 insertions(+), 19 deletions(-) create mode 100644 proto/interface.go create mode 100644 proto/pbcodec.go diff --git a/network/p2p/p2p.go b/network/p2p/p2p.go index 0ad3a3f..6a58f22 100644 --- a/network/p2p/p2p.go +++ b/network/p2p/p2p.go @@ -15,18 +15,21 @@ import ( dutil "github.com/libp2p/go-libp2p/p2p/discovery/util" "github.com/topology-gg/gram/config" ex "github.com/topology-gg/gram/execution" + pbcodec "github.com/topology-gg/gram/proto" + "github.com/topology-gg/gram/proto/gen/gram/base" ) type P2P struct { - ctx context.Context - errCh chan error - executor ex.Execution - host host.Host - namespace string - maxPeers int - port int - pubsub *pubsub.PubSub - streams []Stream + ctx context.Context + errCh chan error + executor ex.Execution + host host.Host + namespace string + maxPeers int + port int + pubsub *pubsub.PubSub + streams []Stream + serializer pbcodec.Serializer } type Stream struct { @@ -59,16 +62,19 @@ func NewP2P(ctx context.Context, errCh chan error, executor ex.Execution, cfg *c streams[i] = Stream{name: name} } + serializer := &pbcodec.ProtoBufSerializer{} + return &P2P{ - ctx: ctx, - errCh: errCh, - executor: executor, - host: host, - namespace: namespace, - maxPeers: maxPeers, - port: port, - pubsub: gossipsub, - streams: streams, + ctx: ctx, + errCh: errCh, + executor: executor, + host: host, + namespace: namespace, + maxPeers: maxPeers, + port: port, + pubsub: gossipsub, + streams: streams, + serializer: serializer, }, nil } @@ -78,8 +84,14 @@ func (p2p *P2P) Start() { } func (p2p *P2P) Publish(message string) { + msg, err := p2p.serializer.Marshal(&base.HelloRequest{Name: message}) + if err != nil { + p2p.errCh <- err + return + } + for i := range p2p.streams { - if err := p2p.streams[i].topic.Publish(p2p.ctx, []byte(message)); err != nil { + if err := p2p.streams[i].topic.Publish(p2p.ctx, msg); err != nil { fmt.Println("(Network) Failed to publish to topic:", p2p.streams[i].name, err) } } @@ -211,6 +223,12 @@ func (p2p *P2P) p2pMessageHandler(subscription *pubsub.Subscription) { continue } + var msg base.HelloRequest + if err := p2p.serializer.Unmarshal(message.Data, &msg); err != nil { + p2p.errCh <- err + continue + } + p2p.executor.Execute(string(message.Message.Data)) } } diff --git a/proto/interface.go b/proto/interface.go new file mode 100644 index 0000000..75ab953 --- /dev/null +++ b/proto/interface.go @@ -0,0 +1,6 @@ +package pbcodec + +type Serializer interface { + Marshal(data interface{}) ([]byte, error) + Unmarshal(data []byte, v interface{}) error +} diff --git a/proto/pbcodec.go b/proto/pbcodec.go new file mode 100644 index 0000000..2baae81 --- /dev/null +++ b/proto/pbcodec.go @@ -0,0 +1,13 @@ +package pbcodec + +import "google.golang.org/protobuf/proto" + +type ProtoBufSerializer struct{} + +func (p *ProtoBufSerializer) Marshal(data interface{}) ([]byte, error) { + return proto.Marshal(data.(proto.Message)) +} + +func (p *ProtoBufSerializer) Unmarshal(data []byte, v interface{}) error { + return proto.Unmarshal(data, v.(proto.Message)) +} From f90fa7c2a2ad516e5e0d9b708209431a66f0c883 Mon Sep 17 00:00:00 2001 From: Giwook-Han <73291175+Giwook-Han@users.noreply.github.com> Date: Tue, 16 Apr 2024 12:05:53 +0900 Subject: [PATCH 2/7] mod handling marshaling error --- network/p2p/p2p.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/network/p2p/p2p.go b/network/p2p/p2p.go index 6a58f22..88ebfec 100644 --- a/network/p2p/p2p.go +++ b/network/p2p/p2p.go @@ -86,7 +86,7 @@ func (p2p *P2P) Start() { func (p2p *P2P) Publish(message string) { msg, err := p2p.serializer.Marshal(&base.HelloRequest{Name: message}) if err != nil { - p2p.errCh <- err + fmt.Println("(Network) Failed to serialize message:", err) return } @@ -225,7 +225,7 @@ func (p2p *P2P) p2pMessageHandler(subscription *pubsub.Subscription) { var msg base.HelloRequest if err := p2p.serializer.Unmarshal(message.Data, &msg); err != nil { - p2p.errCh <- err + fmt.Println("(Network) Failed to serialize message:", err) continue } From e4125b75c471b91e61627ae96ca3217c8991de43 Mon Sep 17 00:00:00 2001 From: Giwook-Han <73291175+Giwook-Han@users.noreply.github.com> Date: Tue, 16 Apr 2024 16:24:19 +0900 Subject: [PATCH 3/7] fix typo --- network/p2p/p2p.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/p2p/p2p.go b/network/p2p/p2p.go index 88ebfec..b467896 100644 --- a/network/p2p/p2p.go +++ b/network/p2p/p2p.go @@ -225,7 +225,7 @@ func (p2p *P2P) p2pMessageHandler(subscription *pubsub.Subscription) { var msg base.HelloRequest if err := p2p.serializer.Unmarshal(message.Data, &msg); err != nil { - fmt.Println("(Network) Failed to serialize message:", err) + fmt.Println("(Network) Failed to deserialize message:", err) continue } From a9808b5731ccafaedcf3be461616c7946ffa498b Mon Sep 17 00:00:00 2001 From: Oak Date: Tue, 16 Apr 2024 12:32:32 +0100 Subject: [PATCH 4/7] feat: add custom logger (#25) closes: #5 - Added custom logger based on ethereum logger (https://github.com/ethereum/go-ethereum/tree/master/log) - Replaced fmt occurrences with the correspondent log --- LICENSE.LESSER | 165 +++++++++++++++++++++++++++++++++++++++++ README.md | 6 ++ config/config.go | 5 ++ execution/execution.go | 4 +- internal/app/app.go | 12 ++- log/format.go | 87 ++++++++++++++++++++++ log/handler.go | 89 ++++++++++++++++++++++ log/logger.go | 139 ++++++++++++++++++++++++++++++++++ log/root.go | 67 +++++++++++++++++ network/grpc/grpc.go | 5 +- network/network.go | 4 +- network/p2p/p2p.go | 27 ++++--- storage/storage.go | 6 +- 13 files changed, 590 insertions(+), 26 deletions(-) create mode 100644 LICENSE.LESSER create mode 100644 log/format.go create mode 100644 log/handler.go create mode 100644 log/logger.go create mode 100644 log/root.go diff --git a/LICENSE.LESSER b/LICENSE.LESSER new file mode 100644 index 0000000..0a04128 --- /dev/null +++ b/LICENSE.LESSER @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/README.md b/README.md index dc3b9cf..f8f8eed 100644 --- a/README.md +++ b/README.md @@ -10,3 +10,9 @@ Make sure you have Go installed. make ./bin/gram ``` + +## License + +Go RAM is licensed under the MIT License. + +All the code under the `log` folder is a modified version of the [`go-ethereum` log](https://github.com/ethereum/go-ethereum/tree/bd91810462187086b2715fd343aa427e181d89a2/log), and therefore licensed under the GNU Lesser General Public License v3.0. diff --git a/config/config.go b/config/config.go index 6f3af38..520a5a2 100644 --- a/config/config.go +++ b/config/config.go @@ -38,10 +38,15 @@ type RpcConfig struct { Port int `json:"port"` } +type LogConfig struct { + LogLevel string `json:"logLevel"` +} + type AppConfig struct { Execution ExecutionConfig `json:"executionConfig"` Network NetworkConfig `json:"networkConfig"` Storage StorageConfig `json:"storageConfig"` + Log LogConfig `json:"logConfig"` } func LoadConfig[T any]() (*T, error) { diff --git a/execution/execution.go b/execution/execution.go index 643b540..e7e9d44 100644 --- a/execution/execution.go +++ b/execution/execution.go @@ -2,10 +2,10 @@ package execution import ( "context" - "fmt" "strings" "github.com/topology-gg/gram/config" + "github.com/topology-gg/gram/log" "github.com/topology-gg/gram/storage" ) @@ -26,7 +26,7 @@ func NewExecution(ctx context.Context, storage storage.Storage, config *config.E func (execution *ExecutionModule) Execute(message string) { // TODO: Proper message handling comes here. - fmt.Printf("(Execution) %s", message) + log.Info("(Execution)", "message", message) kv := strings.Split(message, ": ") _ = execution.storage.Set([]byte(kv[0]), []byte(kv[1])) } diff --git a/internal/app/app.go b/internal/app/app.go index afd2ab4..e7b9bbb 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -7,6 +7,7 @@ import ( "github.com/topology-gg/gram/config" "github.com/topology-gg/gram/execution" + "github.com/topology-gg/gram/log" "github.com/topology-gg/gram/network" "github.com/topology-gg/gram/storage" "github.com/topology-gg/gram/util" @@ -14,8 +15,6 @@ import ( // Gram configures initial values and bootstraps the project func Gram() { - fmt.Println("Starting gram node") - ctx := context.Background() // load configuration from file @@ -24,6 +23,11 @@ func Gram() { ch := make(chan error) + // setup the log + log.SetDefault(&cfg.Log) + + log.Info("Starting gram node") + // instantiate modules storage, err := storage.NewStorage(ctx, &cfg.Storage) logErrorAndPanic(err) @@ -49,7 +53,7 @@ func Gram() { fmt.Fprintln(os.Stderr, err) } - fmt.Println("Shutting down gram") + log.Info("Shutting down gram") } // This is a private fucntion that is used only during app setup @@ -59,6 +63,6 @@ func logErrorAndPanic(err error) { return } - fmt.Fprintln(os.Stderr, err) + log.Error("Error initializing gram", "error", err) panic(err) } diff --git a/log/format.go b/log/format.go new file mode 100644 index 0000000..e2f4ef8 --- /dev/null +++ b/log/format.go @@ -0,0 +1,87 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package log + +import ( + "bytes" + "log/slog" +) + +const ( + timeFormat = "2006-01-02T15:04:05" + termMsgJust = 40 +) + +func (h *Handler) format(buf []byte, r slog.Record, usecolor bool) []byte { + var color = "" + if usecolor { + switch r.Level { + case slog.LevelError: + color = "\x1b[31m" + case slog.LevelWarn: + color = "\x1b[33m" + case slog.LevelInfo: + color = "\x1b[32m" + case slog.LevelDebug: + color = "\x1b[36m" + } + } + + if buf == nil { + buf = make([]byte, 0, 30+termMsgJust) + } + b := bytes.NewBuffer(buf) + + if color != "" { // Start color + b.WriteString(color) + b.WriteString(LevelString(r.Level)) + b.WriteString("\x1b[0m") + } else { + b.WriteString(LevelString(r.Level)) + } + b.WriteString("[") + b.WriteString(r.Time.Format(timeFormat)) + b.WriteString("] ") + b.WriteString(r.Message) + + h.formatAttributes(b, r, color) + return b.Bytes() +} + +func (h *Handler) formatAttributes(buf *bytes.Buffer, r slog.Record, color string) { + writeAttr := func(attr slog.Attr) { + buf.WriteByte(' ') + + if color != "" { + buf.WriteString(color) + buf.WriteString(attr.Key) + buf.WriteString("\x1b[0m=") + } else { + buf.WriteString(attr.Key) + buf.WriteByte('=') + } + + buf.WriteString(attr.Value.String()) + } + + r.Attrs(func(attr slog.Attr) bool { + writeAttr(attr) + return true + }) + + buf.WriteByte('\n') +} diff --git a/log/handler.go b/log/handler.go new file mode 100644 index 0000000..c74903f --- /dev/null +++ b/log/handler.go @@ -0,0 +1,89 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package log + +import ( + "context" + "io" + "log/slog" + "sync" +) + +type emptyHandler struct{} + +// DiscardHandler returns a no-op handler +func EmptyHandler() slog.Handler { + return &emptyHandler{} +} + +func (h *emptyHandler) Handle(_ context.Context, r slog.Record) error { + return nil +} + +func (h *emptyHandler) Enabled(_ context.Context, level slog.Level) bool { + return false +} + +func (h *emptyHandler) WithGroup(name string) slog.Handler { + panic("not implemented") +} + +func (h *emptyHandler) WithAttrs(attrs []slog.Attr) slog.Handler { + return &emptyHandler{} +} + +type Handler struct { + mutex sync.Mutex + writer io.Writer + lvl slog.Level + useColor bool + buf []byte +} + +func NewHandler(writer io.Writer, lvl slog.Level, useColor bool) *Handler { + return &Handler{ + writer: writer, + lvl: lvl, + useColor: useColor, + } +} + +func (h *Handler) Handle(_ context.Context, record slog.Record) error { + h.mutex.Lock() + defer h.mutex.Unlock() + buf := h.format(h.buf, record, h.useColor) + _, err := h.writer.Write(buf) + + if err != nil { + return err + } + + h.buf = buf[:0] + return nil +} + +func (h *Handler) Enabled(_ context.Context, level slog.Level) bool { + return level >= h.lvl +} + +func (h *Handler) WithGroup(name string) slog.Handler { + panic("not implemented") +} + +func (h *Handler) WithAttrs(attrs []slog.Attr) slog.Handler { + panic("not implemented") +} diff --git a/log/logger.go b/log/logger.go new file mode 100644 index 0000000..bcbcc7d --- /dev/null +++ b/log/logger.go @@ -0,0 +1,139 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package log + +import ( + "context" + "log/slog" + "runtime" + "strings" + "time" +) + +const errorKey = "LOG_ERROR" + +// LevelString returns a string containing the name of a Lvl. +func LevelString(l slog.Level) string { + switch l { + case slog.LevelDebug: + return "debug" + case slog.LevelInfo: + return "info" + case slog.LevelWarn: + return "warn" + case slog.LevelError: + return "error" + default: + return "unknown" + } +} + +func StringLevel(l string) slog.Level { + switch strings.ToLower(l) { + case "debug": + return slog.LevelDebug + case "info": + return slog.LevelInfo + case "warn": + return slog.LevelWarn + case "error": + return slog.LevelError + default: + // defaults to info + return slog.LevelInfo + } +} + +type Logger interface { + With(ctx ...interface{}) Logger + + New(ctx ...interface{}) Logger + + Log(level slog.Level, msg string, ctx ...interface{}) + + Debug(msg string, ctx ...interface{}) + + Info(msg string, ctx ...interface{}) + + Warn(msg string, ctx ...interface{}) + + Error(msg string, ctx ...interface{}) + + Write(level slog.Level, msg string, attrs ...any) + + Handler() slog.Handler +} + +type logger struct { + inner *slog.Logger +} + +// NewLogger returns a logger with the specified handler set +func NewLogger(h slog.Handler) Logger { + return &logger{ + slog.New(h), + } +} + +func (l *logger) Handler() slog.Handler { + return l.inner.Handler() +} + +// Write logs a message at the specified level: +func (l *logger) Write(level slog.Level, msg string, attrs ...any) { + var pcs [1]uintptr + runtime.Callers(3, pcs[:]) + + if len(attrs)%2 != 0 { + attrs = append(attrs, nil, errorKey, "Normalized odd number of arguments by adding nil") + } + + r := slog.NewRecord(time.Now(), level, msg, pcs[0]) + r.Add(attrs...) + err := l.inner.Handler().Handle(context.Background(), r) + if err != nil { + Error("(Logger) Error writing a message", "error", err) + } +} + +func (l *logger) Log(level slog.Level, msg string, attrs ...any) { + l.Write(level, msg, attrs...) +} + +func (l *logger) With(ctx ...interface{}) Logger { + return &logger{l.inner.With(ctx...)} +} + +func (l *logger) New(ctx ...interface{}) Logger { + return l.With(ctx...) +} + +func (l *logger) Debug(msg string, ctx ...interface{}) { + l.Write(slog.LevelDebug, msg, ctx...) +} + +func (l *logger) Info(msg string, ctx ...interface{}) { + l.Write(slog.LevelInfo, msg, ctx...) +} + +func (l *logger) Warn(msg string, ctx ...any) { + l.Write(slog.LevelWarn, msg, ctx...) +} + +func (l *logger) Error(msg string, ctx ...interface{}) { + l.Write(slog.LevelError, msg, ctx...) +} diff --git a/log/root.go b/log/root.go new file mode 100644 index 0000000..56743e1 --- /dev/null +++ b/log/root.go @@ -0,0 +1,67 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package log + +import ( + "log/slog" + "os" + "sync/atomic" + + "github.com/topology-gg/gram/config" +) + +var root atomic.Value + +func init() { + root.Store(&logger{slog.New(EmptyHandler())}) +} + +// SetDefault sets the default global logger +func SetDefault(config *config.LogConfig) { + level := StringLevel(config.LogLevel) + l := NewLogger(NewHandler(os.Stdout, level, true)) + + root.Store(l) + if lg, ok := l.(*logger); ok { + slog.SetDefault(lg.inner) + } +} + +// Root returns the root logger +func Root() Logger { + return root.Load().(Logger) +} + +// Debug is a convenient alias for Root().Debug +func Debug(msg string, ctx ...interface{}) { + Root().Write(slog.LevelDebug, msg, ctx...) +} + +// Info is a convenient alias for Root().Info +func Info(msg string, ctx ...interface{}) { + Root().Write(slog.LevelInfo, msg, ctx...) +} + +// Warn is a convenient alias for Root().Warn +func Warn(msg string, ctx ...interface{}) { + Root().Write(slog.LevelWarn, msg, ctx...) +} + +// Error is a convenient alias for Root().Error +func Error(msg string, ctx ...interface{}) { + Root().Write(slog.LevelError, msg, ctx...) +} diff --git a/network/grpc/grpc.go b/network/grpc/grpc.go index a47ff3d..3066be4 100644 --- a/network/grpc/grpc.go +++ b/network/grpc/grpc.go @@ -6,6 +6,7 @@ import ( "net" "github.com/topology-gg/gram/config" + "github.com/topology-gg/gram/log" helloPb "github.com/topology-gg/gram/proto/gen/gram/base" "google.golang.org/grpc" ) @@ -38,7 +39,7 @@ func (g *GRPC) Start() { g.server = grpc.NewServer() helloPb.RegisterServiceServer(g.server, &helloServer{}) - fmt.Printf("GRPC Server is listening on port: %v\n", listener.Addr()) + log.Info("(GRPC Server)", "address", listener.Addr()) if err := g.server.Serve(listener); err != nil { g.errCh <- err @@ -49,6 +50,6 @@ func (g *GRPC) Start() { func (g *GRPC) Shutdown() error { g.server.GracefulStop() - fmt.Println("GRPC server successfully shutted down") + log.Info("(GRPC Server) successfully shutted down") return nil } diff --git a/network/network.go b/network/network.go index d6ebead..35a8ceb 100644 --- a/network/network.go +++ b/network/network.go @@ -7,6 +7,7 @@ import ( "github.com/topology-gg/gram/config" "github.com/topology-gg/gram/execution" + "github.com/topology-gg/gram/log" grpc "github.com/topology-gg/gram/network/grpc" p2p "github.com/topology-gg/gram/network/p2p" rpc "github.com/topology-gg/gram/network/rpc" @@ -66,10 +67,11 @@ func (network *NetworkModule) Shutdown() { } if err := network.grpc.Shutdown(); err != nil { - fmt.Fprintln(os.Stderr, err) + log.Error("(Network) GRPC shutdown", "error", err) } if err := network.p2p.Shutdown(); err != nil { + log.Error("(Network) P2P shutdown", "error", err) fmt.Fprintln(os.Stderr, err) } } diff --git a/network/p2p/p2p.go b/network/p2p/p2p.go index b467896..2d1d9e3 100644 --- a/network/p2p/p2p.go +++ b/network/p2p/p2p.go @@ -3,7 +3,6 @@ package p2p import ( "context" "fmt" - "os" "sync" "github.com/libp2p/go-libp2p" @@ -15,6 +14,7 @@ import ( dutil "github.com/libp2p/go-libp2p/p2p/discovery/util" "github.com/topology-gg/gram/config" ex "github.com/topology-gg/gram/execution" + "github.com/topology-gg/gram/log" pbcodec "github.com/topology-gg/gram/proto" "github.com/topology-gg/gram/proto/gen/gram/base" ) @@ -92,7 +92,7 @@ func (p2p *P2P) Publish(message string) { for i := range p2p.streams { if err := p2p.streams[i].topic.Publish(p2p.ctx, msg); err != nil { - fmt.Println("(Network) Failed to publish to topic:", p2p.streams[i].name, err) + log.Error("(Network) Failed to publish to topic", "topic", p2p.streams[i].name, "error", err) } } } @@ -113,7 +113,7 @@ func (p2p *P2P) joinNetwork() { return } - fmt.Println("(Network) Successfully joinned network:", p2p.namespace) + log.Info("(Network) Successfully joined network", "namespace", p2p.namespace) } func (p2p *P2P) subscribeTopics() { @@ -136,7 +136,7 @@ func (p2p *P2P) subscribeTopics() { go p2p.p2pMessageHandler(subscription) - fmt.Println("(Network) Successfully subscribed to gossipsub topic:", p2p.streams[i].name) + log.Info("(Network) Successfully subscribed to gossipsub topic", "topic", p2p.streams[i].name) } } @@ -161,9 +161,9 @@ func (p2p *P2P) getKademliaDHT() (*dht.IpfsDHT, error) { defer wg.Done() if err := p2p.host.Connect(p2p.ctx, *peerInfo); err != nil { - fmt.Println("(Network) Failed to connect to bootstrap node:", err) + log.Error("(Network) Failed to connect to bootstrap node", "error", err) } else { - fmt.Println("(Network) Successfully connected to bootstrap node:", peerInfo) + log.Info("(Network) Successfully connected to bootstrap node", "peerInfo", peerInfo) } }() @@ -179,7 +179,7 @@ func (p2p *P2P) connectPeers(routingDiscovery *drouting.RoutingDiscovery) error isConnected := false for !isConnected { - fmt.Println("(Network) Searching for peers to connect...") + log.Info("(Network) Searching for peers to connect...") peerInfoChan, err := routingDiscovery.FindPeers(p2p.ctx, p2p.namespace) if err != nil { @@ -192,11 +192,11 @@ func (p2p *P2P) connectPeers(routingDiscovery *drouting.RoutingDiscovery) error } if err := p2p.host.Connect(p2p.ctx, peerInfo); err != nil { - fmt.Println("(Network) Failed to connect to peer:", err) + log.Error("(Network) Failed to connect to peer", "error", err) } else { peers++ isConnected = true - fmt.Println("(Network) Successfully connected to peer:", peerInfo) + log.Info("(Network) Successfully connected to peer", "peerInfo", peerInfo) } if peers >= p2p.maxPeers { @@ -205,7 +205,7 @@ func (p2p *P2P) connectPeers(routingDiscovery *drouting.RoutingDiscovery) error } } - fmt.Println("(Network) Connecting peers is completed") + log.Info("(Network) Connecting peers is completed") return nil } @@ -213,8 +213,7 @@ func (p2p *P2P) p2pMessageHandler(subscription *pubsub.Subscription) { for { message, err := subscription.Next(p2p.ctx) if err != nil { - // TODO: log error properly with logger - fmt.Fprintln(os.Stderr, err) + log.Error("(Network) Error handling P2P message", "error", err) continue } @@ -243,7 +242,7 @@ func (p2p *P2P) Shutdown() error { if p2p.streams[i].topic != nil { if err := p2p.streams[i].topic.Close(); err != nil { // just log the error here, since we need to try to close other topics - fmt.Fprintln(os.Stderr, err) + log.Error("(Network) Error closing topic", "error", err) } } } @@ -252,7 +251,7 @@ func (p2p *P2P) Shutdown() error { return err } - fmt.Println("P2P host successfully shutted down") + log.Info("(Network) P2P host successfully shutted down") return nil } diff --git a/storage/storage.go b/storage/storage.go index 7fafa9c..221b180 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -2,10 +2,10 @@ package storage import ( "context" - "fmt" "slices" "github.com/topology-gg/gram/config" + "github.com/topology-gg/gram/log" "github.com/cockroachdb/pebble" ) @@ -51,7 +51,7 @@ func (storage *StorageModule) Get(key []byte) ([]byte, error) { } func (storage *StorageModule) Set(key, value []byte) error { - fmt.Printf("(Storage) %s: %s", key, value) + log.Info("(Storage)", "key", key, "value", value) return storage.db.Set(key, value, pebble.Sync) } @@ -65,6 +65,6 @@ func (storage *StorageModule) Close() error { return err } - fmt.Println("DB connection successfully closed") + log.Info("DB connection successfully closed") return nil } From 63cf0b27f0e53137399c4476f2dfc1a5f2aa4357 Mon Sep 17 00:00:00 2001 From: Giwook-Han <73291175+Giwook-Han@users.noreply.github.com> Date: Mon, 15 Apr 2024 19:53:44 +0900 Subject: [PATCH 5/7] use protobuf while communicate between peers --- network/p2p/p2p.go | 1 + 1 file changed, 1 insertion(+) diff --git a/network/p2p/p2p.go b/network/p2p/p2p.go index 2d1d9e3..4fd32ed 100644 --- a/network/p2p/p2p.go +++ b/network/p2p/p2p.go @@ -93,6 +93,7 @@ func (p2p *P2P) Publish(message string) { for i := range p2p.streams { if err := p2p.streams[i].topic.Publish(p2p.ctx, msg); err != nil { log.Error("(Network) Failed to publish to topic", "topic", p2p.streams[i].name, "error", err) + } } } From 0796548de1814f67815492fc121eca31e454bfaa Mon Sep 17 00:00:00 2001 From: Giwook-Han <73291175+Giwook-Han@users.noreply.github.com> Date: Thu, 18 Apr 2024 11:36:30 +0900 Subject: [PATCH 6/7] integrate with logger --- network/p2p/p2p.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/network/p2p/p2p.go b/network/p2p/p2p.go index 4fd32ed..0923c73 100644 --- a/network/p2p/p2p.go +++ b/network/p2p/p2p.go @@ -86,7 +86,7 @@ func (p2p *P2P) Start() { func (p2p *P2P) Publish(message string) { msg, err := p2p.serializer.Marshal(&base.HelloRequest{Name: message}) if err != nil { - fmt.Println("(Network) Failed to serialize message:", err) + log.Error("(Network) Failed to serialize message", "message", err) return } @@ -225,7 +225,7 @@ func (p2p *P2P) p2pMessageHandler(subscription *pubsub.Subscription) { var msg base.HelloRequest if err := p2p.serializer.Unmarshal(message.Data, &msg); err != nil { - fmt.Println("(Network) Failed to deserialize message:", err) + log.Error("(Network) Failed to deserialize message", "message", err) continue } From be042dd695c8dd356029e6785c80fb5e85f0e9fe Mon Sep 17 00:00:00 2001 From: Giwook-Han <73291175+Giwook-Han@users.noreply.github.com> Date: Thu, 18 Apr 2024 11:37:41 +0900 Subject: [PATCH 7/7] fix typo --- network/p2p/p2p.go | 1 - 1 file changed, 1 deletion(-) diff --git a/network/p2p/p2p.go b/network/p2p/p2p.go index 0923c73..1893e8c 100644 --- a/network/p2p/p2p.go +++ b/network/p2p/p2p.go @@ -93,7 +93,6 @@ func (p2p *P2P) Publish(message string) { for i := range p2p.streams { if err := p2p.streams[i].topic.Publish(p2p.ctx, msg); err != nil { log.Error("(Network) Failed to publish to topic", "topic", p2p.streams[i].name, "error", err) - } } }