From 7e26addd804f903cc063c8ecdd5b00a603bd2fb8 Mon Sep 17 00:00:00 2001 From: Ramiro Paz Date: Tue, 10 Mar 2026 16:36:57 -0300 Subject: [PATCH] improvement --- quickfix/file_log.go | 117 ++++++++++++++++++++++++++++++++++++++ quickfix/fileutil.go | 56 ++++++++++++++++++ src/client/fix/manager.go | 10 +++- 3 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 quickfix/file_log.go create mode 100644 quickfix/fileutil.go diff --git a/quickfix/file_log.go b/quickfix/file_log.go new file mode 100644 index 0000000..3ef5599 --- /dev/null +++ b/quickfix/file_log.go @@ -0,0 +1,117 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + +package quickfix + +import ( + "fmt" + "log" + "os" + "path" + + "quantex.com/qfixdpl/quickfix/config" +) + +type fileLog struct { + eventLogger *log.Logger + messageLogger *log.Logger +} + +func (l fileLog) OnIncoming(msg []byte) { + l.messageLogger.Print(string(msg)) +} + +func (l fileLog) OnOutgoing(msg []byte) { + l.messageLogger.Print(string(msg)) +} + +func (l fileLog) OnEvent(msg string) { + l.eventLogger.Print(msg) +} + +func (l fileLog) OnEventf(format string, v ...interface{}) { + l.eventLogger.Printf(format, v...) +} + +type fileLogFactory struct { + globalLogPath string + sessionLogPaths map[SessionID]string +} + +// NewFileLogFactory creates an instance of LogFactory that writes messages and events to file. +// The location of global and session log files is configured via FileLogPath. +func NewFileLogFactory(settings *Settings) (LogFactory, error) { + logFactory := fileLogFactory{} + + var err error + if logFactory.globalLogPath, err = settings.GlobalSettings().Setting(config.FileLogPath); err != nil { + return logFactory, err + } + + logFactory.sessionLogPaths = make(map[SessionID]string) + + for sid, sessionSettings := range settings.SessionSettings() { + logPath, err := sessionSettings.Setting(config.FileLogPath) + if err != nil { + return logFactory, err + } + logFactory.sessionLogPaths[sid] = logPath + } + + return logFactory, nil +} + +func newFileLog(prefix string, logPath string) (fileLog, error) { + l := fileLog{} + + eventLogName := path.Join(logPath, prefix+".event.current.log") + messageLogName := path.Join(logPath, prefix+".messages.current.log") + + if err := os.MkdirAll(logPath, os.ModePerm); err != nil { + return l, err + } + + fileFlags := os.O_RDWR | os.O_CREATE | os.O_APPEND + eventFile, err := os.OpenFile(eventLogName, fileFlags, os.ModePerm) + if err != nil { + return l, err + } + + messageFile, err := os.OpenFile(messageLogName, fileFlags, os.ModePerm) + if err != nil { + return l, err + } + + logFlag := log.Ldate | log.Ltime | log.Lmicroseconds | log.LUTC + l.eventLogger = log.New(eventFile, "", logFlag) + l.messageLogger = log.New(messageFile, "", logFlag) + + return l, nil +} + +func (f fileLogFactory) Create() (Log, error) { + return newFileLog("GLOBAL", f.globalLogPath) +} + +func (f fileLogFactory) CreateSessionLog(sessionID SessionID) (Log, error) { + logPath, ok := f.sessionLogPaths[sessionID] + + if !ok { + return nil, fmt.Errorf("logger not defined for %v", sessionID) + } + + prefix := sessionIDFilenamePrefix(sessionID) + return newFileLog(prefix, logPath) +} diff --git a/quickfix/fileutil.go b/quickfix/fileutil.go new file mode 100644 index 0000000..73bc4a6 --- /dev/null +++ b/quickfix/fileutil.go @@ -0,0 +1,56 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + +package quickfix + +import ( + "fmt" + "os" + "strings" +) + +func sessionIDFilenamePrefix(s SessionID) string { + sender := []string{s.SenderCompID} + if s.SenderSubID != "" { + sender = append(sender, s.SenderSubID) + } + if s.SenderLocationID != "" { + sender = append(sender, s.SenderLocationID) + } + + target := []string{s.TargetCompID} + if s.TargetSubID != "" { + target = append(target, s.TargetSubID) + } + if s.TargetLocationID != "" { + target = append(target, s.TargetLocationID) + } + + fname := []string{s.BeginString, strings.Join(sender, "_"), strings.Join(target, "_")} + if s.Qualifier != "" { + fname = append(fname, s.Qualifier) + } + return strings.Join(fname, "-") +} + +// openOrCreateFile opens a file for reading and writing, creating it if necessary. +func openOrCreateFile(fname string, perm os.FileMode) (f *os.File, err error) { + if f, err = os.OpenFile(fname, os.O_RDWR, perm); err != nil { + if f, err = os.OpenFile(fname, os.O_RDWR|os.O_CREATE, perm); err != nil { + return nil, fmt.Errorf("error opening or creating file: %s: %s", fname, err.Error()) + } + } + return f, nil +} diff --git a/src/client/fix/manager.go b/src/client/fix/manager.go index 6bd70fa..d0db6c4 100644 --- a/src/client/fix/manager.go +++ b/src/client/fix/manager.go @@ -7,6 +7,7 @@ import ( "sync" "time" + "github.com/rs/zerolog/log" "github.com/shopspring/decimal" "quantex.com/qfixdpl/quickfix" @@ -14,6 +15,7 @@ import ( "quantex.com/qfixdpl/quickfix/gen/field" "quantex.com/qfixdpl/quickfix/gen/fix50sp2/quote" "quantex.com/qfixdpl/src/app" + "quantex.com/qfixdpl/src/common/tracerr" "quantex.com/qfixdpl/src/domain" ) @@ -55,7 +57,13 @@ func (m *Manager) Start() error { } storeFactory := quickfix.NewMemoryStoreFactory() - logFactory := quickfix.NewNullLogFactory() + logFactory, err := quickfix.NewFileLogFactory(settings) + if err != nil { + err = tracerr.Errorf("error creating file log factory: %s", err) + log.Error().Msg(err.Error()) + + return err + } initiator, err := quickfix.NewInitiator(fixApp, storeFactory, settings, logFactory) if err != nil {