func Main()

in main.go [81:206]


func Main() error {
	frontendBuildDir := filepath.FromSlash(*frontendDir)
	indexFilePath := filepath.Join(frontendBuildDir, "index.html")
	faviconFilePath := filepath.Join(frontendBuildDir, "favicon.ico")
	staticDirPath := filepath.Join(frontendBuildDir, "static")
	imagesDirPath := filepath.Join(frontendBuildDir, "images")

	var backendURLs []*url.URL
	if *backendAddrs == "" {
		*backendAddrs = os.Getenv("OPBEANS_SERVICES")
	}
	if *backendAddrs != "" {
		for _, field := range strings.Split(*backendAddrs, ",") {
			field = strings.TrimSpace(field)
			if u, err := url.Parse(field); err == nil && u.Scheme != "" {
				backendURLs = append(backendURLs, u)
				continue
			}
			// Not an absolute URL, so should be a host or host/port pair.
			hostport := field
			if _, _, err := net.SplitHostPort(hostport); err != nil {
				// A bare host was specified; assume the same port
				// that we're listening on.
				_, port, err := net.SplitHostPort(*listenAddr)
				if err != nil {
					port = "3000"
				}
				hostport = net.JoinHostPort(hostport, port)
			}
			backendURLs = append(backendURLs, &url.URL{Scheme: "http", Host: hostport})
		}
	}

	// Read index.html, replace <head> with <head><script>...
	// that injects the dynamic page load properties for RUM.
	indexFileBytes, err := ioutil.ReadFile(indexFilePath)
	if err != nil {
		return err
	}
	indexFileContent := strings.Replace(string(indexFileBytes), "<head>", `<head>
<script type="text/javascript">
  window.rumConfig = {
    pageLoadTraceId: {{.TraceContext.Trace}},
    pageLoadSpanId: {{.EnsureParent}},
    pageLoadSampled: {{.Sampled}},
  }
</script>`, 1)
	indexTemplate, err := template.New(indexTemplateName).Parse(indexFileContent)
	if err != nil {
		return err
	}

	db, err := newDatabase()
	if err != nil {
		return err
	}
	defer db.Close()

	cacheStore, err := newCache()
	if err != nil {
		return err
	}

	r := gin.New()
	r.Use(cache.Cache(&cacheStore))
	r.Use(apmgin.Middleware(r))
	r.Use(logrusMiddleware)

	pprof.Register(r)
	r.Static("/static", staticDirPath)
	r.Static("/images", imagesDirPath)
	r.StaticFile("/favicon.ico", faviconFilePath)
	r.SetHTMLTemplate(indexTemplate)
	r.GET("/", handleIndex)
	r.GET("/oopsie", handleOopsie)
	r.GET("/rum-config.js", handleRUMConfig)
	r.Use(func(c *gin.Context) {
		// Paths used by the frontend for state.
		for _, prefix := range []string{
			"/dashboard",
			"/products",
			"/customers",
			"/orders",
		} {
			if strings.HasPrefix(c.Request.URL.Path, prefix) {
				tx := apm.TransactionFromContext(c.Request.Context())
				if tx != nil {
					tx.Name = c.Request.Method + " " + prefix
				}
				handleIndex(c)
				return
			}
		}
		c.Next()
	})

	// Create API routes. We install middleware for /api which probabilistically
	// proxies these requests to another opbeans service to demonstrate distributed
	// tracing, and test agent compatibility.
	proxyProbability := 0.5
	if value := os.Getenv("OPBEANS_DT_PROBABILITY"); value != "" {
		f, err := strconv.ParseFloat(value, 64)
		if err != nil {
			return errors.Wrapf(err, "failed to parse OPBEANS_DT_PROBABILITY")
		}
		if f < 0.0 || f > 1.0 {
			return errors.Errorf("invalid OPBEANS_DT_PROBABILITY value %s: out of range [0,1.0]", value)
		}
		proxyProbability = f
	}
	rand.Seed(time.Now().UnixNano())
	maybeProxy := func(c *gin.Context) {
		if len(backendURLs) > 0 && rand.Float64() < proxyProbability {
			u := backendURLs[rand.Intn(len(backendURLs))]
			logrus.WithFields(apmlogrus.TraceContext(c.Request.Context())).Infof("proxying API request to %s", u)
			httputil.NewSingleHostReverseProxy(u).ServeHTTP(c.Writer, c.Request)
			c.Abort()
			return
		}
		c.Next()
	}
	apiGroup := r.Group("/api", maybeProxy)
	addAPIHandlers(apiGroup, db)

	return r.Run(*listenAddr)
}