diff --git a/.gitignore b/.gitignore index 3e925e6..cfb4d29 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Logs .DS_Store logs +.idea *.log npm-debug.log* yarn-debug.log* diff --git a/cmd/adapter/main.go b/cmd/adapter/main.go index 43ad48d..518a419 100644 --- a/cmd/adapter/main.go +++ b/cmd/adapter/main.go @@ -11,6 +11,7 @@ import ( "sync" "time" + "github.com/beckn-one/beckn-onix/pkg/model" "gopkg.in/yaml.v2" "github.com/beckn-one/beckn-onix/core/module" @@ -52,7 +53,7 @@ var runFunc = run func main() { // Define and parse command-line flags. - flag.StringVar(&configPath, "config", "../../config/onix/adapter.yaml", "Path to the configuration file") + flag.StringVar(&configPath, "config", "config/onix/adapter.yaml", "Path to the configuration file") flag.Parse() // Use custom log for initial setup messages. @@ -153,6 +154,9 @@ func run(ctx context.Context, configPath string) error { return fmt.Errorf("failed to initialize logger: %w", err) } + //to add the parent_id in the context value so it get passed to the logs + ctx = addParentIdCtx(ctx, cfg) + // Initialize plugin manager. log.Infof(ctx, "Initializing plugin manager") mgr, closer, err := newManagerFunc(ctx, cfg.PluginManager) @@ -220,3 +224,35 @@ func shutdown(ctx context.Context, httpServer *http.Server, wg *sync.WaitGroup, } }() } + +func addParentIdCtx(ctx context.Context, config *Config) context.Context { + var parentID string + var podName string + + if p := os.Getenv("POD_NAME"); p != "" { + log.Infof(ctx, "Adding POD name: %s", p) + podName = p + } else { + log.Info(ctx, "POD_NAME environment variable not set falling back to hostname") + if hostname, err := os.Hostname(); err == nil { + log.Infof(ctx, "Setting POD name as hostname: %s", hostname) + podName = hostname + } else { + log.Info(ctx, "failed to get POD name") + } + } + + for _, m := range config.Modules { + if m.Handler.Role != "" && m.Handler.SubscriberID != "" { + parentID = string(m.Handler.Role) + ":" + m.Handler.SubscriberID + ":" + podName + break + } + } + + if parentID != "" { + ctx = context.WithValue(ctx, model.ContextKeyParentID, parentID) + } else { + log.Warnf(ctx, "Failed to find parent ID in config please add the role and subscriber_id in the handler config ") + } + return ctx +} diff --git a/pkg/log/log_test.go b/pkg/log/log_test.go index 30245ba..334788b 100644 --- a/pkg/log/log_test.go +++ b/pkg/log/log_test.go @@ -20,6 +20,11 @@ import ( type ctxKey any var requestID ctxKey = "requestID" +var transaction_id ctxKey = "transactionID" +var message_id ctxKey = "messageID" +var subscriber_id ctxKey = "subscriberID" +var module_id ctxKey = "moduleID" +var parent_id ctxKey = "parentID" const testLogFilePath = "./test_logs/test.log" @@ -69,6 +74,7 @@ func setupLogger(t *testing.T, l level) string { model.ContextKeyMsgID, model.ContextKeySubscriberID, model.ContextKeyModuleID, + model.ContextKeyParentID, }, } @@ -103,16 +109,25 @@ func parseLogLine(t *testing.T, line string) map[string]interface{} { func TestDebug(t *testing.T) { t.Helper() logPath := setupLogger(t, DebugLevel) - ctx := context.WithValue(context.Background(), model.ContextKeySubscriberID, "12345") + ctx := context.WithValue(context.Background(), model.ContextKeySubscriberID, "subscriber-id-12345") + ctx = context.WithValue(ctx, model.ContextKeyTxnID, "trx-id-12345") + ctx = context.WithValue(ctx, model.ContextKeyMsgID, "message-id-12345") + ctx = context.WithValue(ctx, model.ContextKeyModuleID, "module-id-12345") + ctx = context.WithValue(ctx, model.ContextKeyParentID, "parent-id-12345") + Debug(ctx, "Debug message") lines := readLogFile(t, logPath) if len(lines) == 0 { t.Fatal("No logs were written.") } expected := map[string]interface{}{ - "level": "debug", - "subscriber_id": "12345", - "message": "Debug message", + "level": "debug", + "transaction_id": "trx-id-12345", + "message_id": "message-id-12345", + "subscriber_id": "subscriber-id-12345", + "module_id": "module-id-12345", + "parent_id": "parent-id-12345", + "message": "Debug message", } var found bool @@ -135,16 +150,24 @@ func TestDebug(t *testing.T) { func TestInfo(t *testing.T) { logPath := setupLogger(t, InfoLevel) - ctx := context.WithValue(context.Background(), model.ContextKeySubscriberID, "12345") + ctx := context.WithValue(context.Background(), model.ContextKeySubscriberID, "subscriber-id-12345") + ctx = context.WithValue(ctx, model.ContextKeyTxnID, "trx-id-12345") + ctx = context.WithValue(ctx, model.ContextKeyMsgID, "message-id-12345") + ctx = context.WithValue(ctx, model.ContextKeyModuleID, "module-id-12345") + ctx = context.WithValue(ctx, model.ContextKeyParentID, "parent-id-12345") Info(ctx, "Info message") lines := readLogFile(t, logPath) if len(lines) == 0 { t.Fatal("No logs were written.") } expected := map[string]interface{}{ - "level": "info", - "subscriber_id": "12345", - "message": "Info message", + "level": "info", + "transaction_id": "trx-id-12345", + "message_id": "message-id-12345", + "subscriber_id": "subscriber-id-12345", + "module_id": "module-id-12345", + "parent_id": "parent-id-12345", + "message": "Info message", } var found bool @@ -227,6 +250,12 @@ func TestError(t *testing.T) { func TestRequest(t *testing.T) { logPath := setupLogger(t, InfoLevel) ctx := context.WithValue(context.Background(), requestID, "abc-123") + ctx = context.WithValue(context.Background(), transaction_id, "transaction-id-123-") + ctx = context.WithValue(context.Background(), message_id, "message-id-123") + ctx = context.WithValue(context.Background(), subscriber_id, "subscriber-id-123") + ctx = context.WithValue(context.Background(), module_id, "module-id-123") + ctx = context.WithValue(context.Background(), parent_id, "parent-id-123") + req, _ := http.NewRequest("POST", "/api/test", bytes.NewBuffer([]byte(`{"key":"value"}`))) req.RemoteAddr = "127.0.0.1:8080" Request(ctx, req, []byte(`{"key":"value"}`)) diff --git a/pkg/model/error_test.go b/pkg/model/error_test.go index 1ac952e..6cf69fc 100644 --- a/pkg/model/error_test.go +++ b/pkg/model/error_test.go @@ -208,6 +208,7 @@ func TestParseContextKey_ValidKeys(t *testing.T) { {"message_id", ContextKeyMsgID}, {"subscriber_id", ContextKeySubscriberID}, {"module_id", ContextKeyModuleID}, + {"parent_id", ContextKeyParentID}, } for _, tt := range tests { diff --git a/pkg/model/model.go b/pkg/model/model.go index 8adc569..1cd08cc 100644 --- a/pkg/model/model.go +++ b/pkg/model/model.go @@ -53,6 +53,9 @@ const ( // ContextKeyModuleID is the context key for storing and retrieving the model ID from a request context. ContextKeyModuleID ContextKey = "module_id" + + // ContextKeyParentID is the context key for storing and retrieving the parent ID from a request context + ContextKeyParentID ContextKey = "parent_id" ) var contextKeys = map[string]ContextKey{ @@ -60,6 +63,7 @@ var contextKeys = map[string]ContextKey{ "message_id": ContextKeyMsgID, "subscriber_id": ContextKeySubscriberID, "module_id": ContextKeyModuleID, + "parent_id": ContextKeyParentID, } // ParseContextKey converts a string into a valid ContextKey. @@ -100,6 +104,8 @@ const ( RoleGateway Role = "gateway" // RoleRegistery represents the Registry that maintains network participant details. RoleRegistery Role = "registery" + // RoleCDS represents the CDS for that network + RoleCDS Role = "cds" ) var validRoles = map[Role]bool{ @@ -107,6 +113,7 @@ var validRoles = map[Role]bool{ RoleBPP: true, RoleGateway: true, RoleRegistery: true, + RoleCDS: true, } // UnmarshalYAML implements custom YAML unmarshalling for Role to ensure only valid values are accepted. @@ -184,4 +191,4 @@ type Message struct { // Response represents the main response structure. type Response struct { Message Message `json:"message"` -} \ No newline at end of file +} diff --git a/pkg/plugin/implementation/reqpreprocessor/cmd/plugin.go b/pkg/plugin/implementation/reqpreprocessor/cmd/plugin.go index e02d477..494d6d1 100644 --- a/pkg/plugin/implementation/reqpreprocessor/cmd/plugin.go +++ b/pkg/plugin/implementation/reqpreprocessor/cmd/plugin.go @@ -5,6 +5,7 @@ import ( "net/http" "strings" + "github.com/beckn-one/beckn-onix/pkg/model" "github.com/beckn-one/beckn-onix/pkg/plugin/implementation/reqpreprocessor" ) @@ -18,6 +19,11 @@ func (p provider) New(ctx context.Context, c map[string]string) (func(http.Handl if contextKeys, ok := c["contextKeys"]; ok { config.ContextKeys = strings.Split(contextKeys, ",") } + + if v := ctx.Value(model.ContextKeyParentID); v != nil { + config.ParentID = v.(string) + } + return reqpreprocessor.NewPreProcessor(config) } diff --git a/pkg/plugin/implementation/reqpreprocessor/cmd/plugin_test.go b/pkg/plugin/implementation/reqpreprocessor/cmd/plugin_test.go index cb5c7e6..2df83e0 100644 --- a/pkg/plugin/implementation/reqpreprocessor/cmd/plugin_test.go +++ b/pkg/plugin/implementation/reqpreprocessor/cmd/plugin_test.go @@ -7,6 +7,7 @@ import ( "strings" "testing" + "github.com/beckn-one/beckn-onix/pkg/model" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -92,7 +93,9 @@ func TestProviderNew(t *testing.T) { }` p := provider{} - middleware, err := p.New(context.Background(), tc.config) + ctx := context.Background() + ctx = context.WithValue(ctx, model.ContextKeyParentID, "bap:bap-1:instanceID") + middleware, err := p.New(ctx, tc.config) if tc.expectedError { assert.Error(t, err) return diff --git a/pkg/plugin/implementation/reqpreprocessor/reqpreprocessor.go b/pkg/plugin/implementation/reqpreprocessor/reqpreprocessor.go index 12e6581..fa32898 100644 --- a/pkg/plugin/implementation/reqpreprocessor/reqpreprocessor.go +++ b/pkg/plugin/implementation/reqpreprocessor/reqpreprocessor.go @@ -17,6 +17,7 @@ import ( type Config struct { Role string ContextKeys []string + ParentID string } const contextKey = "context" @@ -58,6 +59,11 @@ func NewPreProcessor(cfg *Config) (func(http.Handler) http.Handler, error) { log.Debugf(ctx, "adding subscriberId to request:%s, %v", model.ContextKeySubscriberID, subID) ctx = context.WithValue(ctx, model.ContextKeySubscriberID, subID) } + + if cfg.ParentID != "" { + log.Debugf(ctx, "adding parentID to request:%s, %v", model.ContextKeyParentID, cfg.ParentID) + ctx = context.WithValue(ctx, model.ContextKeyParentID, cfg.ParentID) + } for _, key := range cfg.ContextKeys { ctxKey, _ := model.ParseContextKey(key) if v, ok := reqContext[key]; ok { diff --git a/pkg/plugin/implementation/reqpreprocessor/reqpreprocessor_test.go b/pkg/plugin/implementation/reqpreprocessor/reqpreprocessor_test.go index 97a147a..1e9f0c1 100644 --- a/pkg/plugin/implementation/reqpreprocessor/reqpreprocessor_test.go +++ b/pkg/plugin/implementation/reqpreprocessor/reqpreprocessor_test.go @@ -22,7 +22,8 @@ func TestNewPreProcessorSuccessCases(t *testing.T) { { name: "BAP role with valid context", config: &Config{ - Role: "bap", + Role: "bap", + ParentID: "bap:bap-123", }, requestBody: map[string]interface{}{ "context": map[string]interface{}{ @@ -38,7 +39,8 @@ func TestNewPreProcessorSuccessCases(t *testing.T) { { name: "BPP role with valid context", config: &Config{ - Role: "bpp", + Role: "bpp", + ParentID: "bap:bap-123", }, requestBody: map[string]interface{}{ "context": map[string]interface{}{