func (hc Controller) Logs(c *gin.Context) {
	ctx := c.Request.Context()
	org := c.Param("org")
	appName := c.Param("app")
	stageID := c.Param("stage_id")
	log := tracelog.Logger(ctx)
	log.Info("get cluster client")
	cluster, err := kubernetes.GetCluster(ctx)
	if err != nil {
		response.Error(c, apierror.InternalError(err))
		return
	}
	log.Info("validate organization", "name", org)
	exists, err := organizations.Exists(ctx, cluster, org)
	if err != nil {
		response.Error(c, apierror.InternalError(err))
		return
	}
	if !exists {
		response.Error(c, apierror.OrgIsNotKnown(org))
		return
	}
	if appName != "" {
		log.Info("retrieve application", "name", appName, "org", org)
		app, err := application.Lookup(ctx, cluster, org, appName)
		if err != nil {
			response.Error(c, apierror.InternalError(err))
			return
		}
		if app == nil {
			response.Error(c, apierror.AppIsNotKnown(appName))
			return
		}
		if app.Workload == nil {
			response.Error(c, apierror.NewAPIError("No logs available for application without workload", "", http.StatusBadRequest))
			return
		}
	}
	if appName == "" && stageID == "" {
		response.Error(c, apierror.BadRequest(errors.New("You need to specify either the stage id or the app")))
		return
	}
	log.Info("process query")
	followStr := c.Query("follow")
	log.Info("upgrade to web socket")
	var upgrader = websocket.Upgrader{}
	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		response.Error(c, apierror.InternalError(err))
		return
	}
	follow := followStr == "true"
	log.Info("streaming mode", "follow", follow)
	log.Info("streaming begin")
	err = hc.streamPodLogs(ctx, conn, org, appName, stageID, cluster, follow)
	if err != nil {
		log.V(1).Error(err, "error occurred after upgrading the websockets connection")
		return
	}
	log.Info("streaming completed")
}
Logs handles the API endpoints GET /namespaces/:org/applications/:app/logs
and                            GET /namespaces/:org/staging/:stage_id/logs
It arranges for the logs of the specified application to be
streamed over a websocket. Dependent on the endpoint this may be
either regular logs, or the app's staging logs.
package application
import (
	"context"
	"encoding/json"
	"net/http"
	"sync"
	"time"
	"github.com/epinio/epinio/helpers/kubernetes"
	"github.com/epinio/epinio/helpers/kubernetes/tailer"
	"github.com/epinio/epinio/helpers/tracelog"
	"github.com/epinio/epinio/internal/api/v1/response"
	"github.com/epinio/epinio/internal/application"
	"github.com/epinio/epinio/internal/organizations"
	apierror "github.com/epinio/epinio/pkg/api/core/v1/errors"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"github.com/pkg/errors"
)