package oas import ( "context" "encoding/json" "github.com/google/martian/har" "github.com/up9inc/mizu/shared/logger" "net/url" "sync" ) var ( syncOnce sync.Once instance *oasGenerator ) func GetOasGeneratorInstance() *oasGenerator { syncOnce.Do(func() { instance = newOasGenerator() logger.Log.Debug("Oas Generator Initialized") }) return instance } func (g *oasGenerator) Start() { if g.started { return } ctx, cancel := context.WithCancel(context.Background()) g.cancel = cancel g.ctx = ctx g.entriesChan = make(chan har.Entry, 100) // buffer up to 100 entries for OAS processing g.ServiceSpecs = &sync.Map{} g.started = true go instance.runGeneretor() } func (g *oasGenerator) runGeneretor() { for { select { case <-g.ctx.Done(): logger.Log.Infof("OAS Generator was canceled") return case entry, ok := <-g.entriesChan: if !ok { logger.Log.Infof("OAS Generator - entries channel closed") break } u, err := url.Parse(entry.Request.URL) if err != nil { logger.Log.Errorf("Failed to parse entry URL: %v, err: %v", entry.Request.URL, err) } val, found := g.ServiceSpecs.Load(u.Host) var gen *SpecGen if !found { gen = NewGen(u.Scheme + "://" + u.Host) g.ServiceSpecs.Store(u.Host, gen) } else { gen = val.(*SpecGen) } opId, err := gen.feedEntry(entry) if err != nil { txt, suberr := json.Marshal(entry) if suberr == nil { logger.Log.Debugf("Problematic entry: %s", txt) } logger.Log.Warningf("Failed processing entry: %s", err) continue } logger.Log.Debugf("Handled entry %s as opId: %s", entry.Request.URL, opId) // TODO: set opId back to entry? } } } func (g *oasGenerator) PushEntry(entry *har.Entry) { if !g.started { return } select { case g.entriesChan <- *entry: default: logger.Log.Warningf("OAS Generator - entry wasn't sent to channel because the channel has no buffer or there is no receiver") } } func newOasGenerator() *oasGenerator { return &oasGenerator{ started: false, ctx: nil, cancel: nil, ServiceSpecs: nil, entriesChan: nil, } } type oasGenerator struct { started bool ctx context.Context cancel context.CancelFunc ServiceSpecs *sync.Map entriesChan chan har.Entry }