modernice / goes

goes is an event-sourcing framework for Go.
https://goes.modernice.dev
Apache License 2.0
134 stars 12 forks source link

MongoDB Query Analyzer #160

Open bounoable opened 1 year ago

bounoable commented 1 year ago

I want to be able to debug MongoDB queries that are executed by projection jobs.

Something like this:

package example

func example() {
  queries := make(chan mongo.ExecutedQuery)
  go func(){
    for q := range queries {
      log.Printf("Query: %s", q.Query)
      log.Printf("Runtime: %s", q.Runtime)
    }
  }()

  store := mongo.NewEventStore(..., mongo.MonitorQueries(queries))
  events, errs, err := store.Query(context.TODO(), query.New(...))
}

To easily identify which part of an app caused a query, maybe implement "query descriptions":

package example

func example() {
  queries := make(chan mongo.ExecutedQuery)
  go func(){
    for q := range queries {
      if query.Description(q.Query) == "example" {
        log.Printf("Query: %s", q.Query)
        log.Printf("Runtime: %s", q.Runtime)
      }

      // or
      if query.Expand(q.Query).Description() == "example" {
        log.Printf("Query: %s", q.Query)
        log.Printf("Runtime: %s", q.Runtime)
      }
    }
  }()

  q := query.New(...)
  q.Describe("example")

  store := mongo.NewEventStore(..., mongo.MonitorQueries(queries))
  events, errs, err := store.Query(context.TODO(), q)
}

Or maybe event implement full query metadata support:

package example

func example() {
  queries := make(chan mongo.ExecutedQuery)
  go func(){
    for q := range queries {
      if query.MetadataOf[map[string]string](q.Query)["description"] == "example" {
        log.Printf("Query: %s", q.Query)
        log.Printf("Runtime: %s", q.Runtime)
      }

      // or
      if query.Expand(q.Query).Metadata().(map[string]string)["description"] == "example" {
        log.Printf("Query: %s", q.Query)
        log.Printf("Runtime: %s", q.Runtime)
      }
    }
  }()

  q := query.New(query.Metadata(map[string]string{
    "description": "example",
  }))

  store := mongo.NewEventStore(..., mongo.MonitorQueries(queries))
  events, errs, err := store.Query(context.TODO(), q)
}

Metadata could support arbitrary types:

package example

func example() {
  queries := make(chan mongo.ExecutedQuery)
  go func(){
    for q := range queries {
      if query.MetadataOf[string](q.Query) == "example" {
        log.Printf("Query: %s", q.Query)
        log.Printf("Runtime: %s", q.Runtime)
      }

      if query.Expand(q.Query).Metadata().(string) == "example" {
        log.Printf("Query: %s", q.Query)
        log.Printf("Runtime: %s", q.Runtime)
      }
    }
  }()

  q := query.New(query.Metadata("example"))

  store := mongo.NewEventStore(..., mongo.MonitorQueries(queries))
  events, errs, err := store.Query(context.TODO(), q)
}