package main import ( "bytes" "encoding/json" "errors" "fmt" "github.com/gorilla/handlers" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promhttp" "io" "log" "net/http" "os" "strconv" ) func getenv(key, fallback string) string { value := os.Getenv(key) if len(value) == 0 { return fallback } return value } type Comment struct { Comment string `json:"comment"` } type EngineError struct { Message string `json:"message"` AdditionalInfo string `json:"additionalInfo"` } var comments_engine_endpoint string var ( httpHits = promauto.NewCounterVec(prometheus.CounterOpts{ Name: "comments_interactor_http_hits_total", Help: "The total number of hits on a given route", }, []string{"route", "method"}) commentsReceived = promauto.NewCounter(prometheus.CounterOpts{ Name: "comments_interactor_comments_received_total", Help: "The total number of comments received (successfully posted or not)", }) commentsPosted = promauto.NewCounter(prometheus.CounterOpts{ Name: "comments_interactor_comments_posted_total", Help: "The total number of comments posted (successfully posted)", }) ) func sendComment(w http.ResponseWriter, r *http.Request) { commentsReceived.Inc() if err := r.ParseForm(); err != nil { fmt.Fprintf(w, "

error

ParseForm() err: %v

", err) return } var comment Comment comment.Comment = r.FormValue("comment") if comment.Comment == "" { fmt.Fprintf(w, "

error

Empty comment or malformed

") return } obj, err := json.Marshal(comment) if err != nil { fmt.Fprintf(w, "

error

Empty comment or malformed

") return } _, err = http.Post("http://"+comments_engine_endpoint+"/comment", "application/json", bytes.NewReader(obj)) if err == nil { fmt.Fprintf(w, "

Success !

Comment posted

") commentsPosted.Inc() } else { fmt.Fprintf(w, "

Error

Error while trying to send a comment: %s", err) } } func showDashboard(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "

Latest comments

") io.WriteString(w, "

") resp, err := http.Get("http://" + comments_engine_endpoint + "/latest") if err != nil { log.Printf("Could not HTTP get on CommentsEngine: %s", err) io.WriteString(w, fmt.Sprintf("Error contacting the backend, %s", err)) } else { defer resp.Body.Close() body, err := io.ReadAll(resp.Body) var comments []string err = json.Unmarshal(body, &comments) if err != nil { var engineError EngineError err = json.Unmarshal(body, &engineError) if err != nil { log.Printf("CommentsEngine returned unexpected value: %s", err) io.WriteString(w, fmt.Sprintf("CommentsEngine returned badly formated values, %s", err)) } else { io.WriteString(w, fmt.Sprintf("CommentsEngine returned an error: %s
Additional info: %s", engineError.Message, engineError.AdditionalInfo)) } } else { for i, comment := range comments { io.WriteString(w, "

comment "+strconv.Itoa(i)+"

"+comment+"

") } } } io.WriteString(w, "

") io.WriteString(w, "

Send comment

") io.WriteString(w, "

") } func getRoot(w http.ResponseWriter, r *http.Request) { httpHits.With(prometheus.Labels{"route": "/", "method": r.Method}).Inc() io.WriteString(w, "CommentsInteractor") if r.Method == http.MethodPost { sendComment(w, r) } showDashboard(w, r) io.WriteString(w, "") } func sendError(w http.ResponseWriter, err error, additionalInfo string) { w.WriteHeader(http.StatusInternalServerError) resp := make(map[string]string) resp["message"] = fmt.Sprint(err) resp["additionalInfo"] = additionalInfo jsonResp, err := json.Marshal(resp) if err != nil { log.Fatalf("Error happened in JSON marshal. Err: %s", err) } w.Write(jsonResp) } func main() { http.HandleFunc("/", getRoot) prometheus.Unregister(prometheus.NewGoCollector()) http.Handle("/metrics", promhttp.Handler()) listeningHostPort := getenv("HOST", "127.0.0.1") + ":" + getenv("PORT", "9000") comments_engine_endpoint = getenv("COMMENTS_ENGINE_ENDPOINT", "127.0.0.1:8000") fmt.Printf("Starting the server on %s\n", listeningHostPort) err := http.ListenAndServe(listeningHostPort, handlers.LoggingHandler(os.Stdout, http.DefaultServeMux)) if errors.Is(err, http.ErrServerClosed) { fmt.Printf("server closed\n") } else if err != nil { fmt.Printf("error starting server: %s\n", err) os.Exit(1) } }