<commit_before>package main

import (
	"fmt"
	"github.com/ActiveState/log"
	"github.com/gorilla/mux"
	"github.com/gorilla/websocket"
	"net/http"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		// Ignore origin checks (won't work with wscat)
		return true
	},
}

// XXX: pass this as a log context (gorilla) object
func getWsConnId(r *http.Request, ws *websocket.Conn) string {
	return fmt.Sprintf("ws:/%v %v (subprotocol %+v)",
		r.URL.Path, ws.RemoteAddr(), ws.Subprotocol())
}

func tailHandler(w http.ResponseWriter, r *http.Request) {
	ws, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		if _, ok := err.(websocket.HandshakeError); !ok {
			log.Infof("Handshake error: %v", err)
		} else {
			log.Infof("Unknown websocket error: %v", err)
		}
		return
	}

	args, err := ParseArguments(r)
	if err != nil {
		http.Error(
			w, fmt.Sprintf("Invalid arguments; %v", err), 400)
		return
	}

	tailHandlerWs(r, ws, args)
}

func tailHandlerWs(
	r *http.Request, ws *websocket.Conn, args *Arguments) {
	log.Infof("WS init - %v", getWsConnId(r, ws))
	defer log.Infof("WS done - %v", getWsConnId(r, ws))

	stream := &WebSocketStream{ws}

	// First authorize with the CC by fetching something
	_, err := recentLogs(args.Token, args.GUID, 1)
	if err != nil {
		stream.Fatalf("%v", err)
		return
	}

	// Recent history requested?
	if args.Num > 0 {
		recentLogs, err := recentLogs(args.Token, args.GUID, args.Num)
		if err != nil {
			stream.Fatalf("%v", err)
			return
		}
		for _, line := range recentLogs {
			// TODO: make CC return raw log data from apptail as-is
			// without mangling.
			stream.Send(line)
		}
	}

	drain, err := NewAppLogDrain(args.GUID)
	if err != nil {
		stream.Fatalf("Unable to create drain: %v", err)
		return
	}
	ch, err := drain.Start()
	if err != nil {
		stream.Fatalf("Unable to start drain: %v", err)
	}

	err = stream.Forward(ch)
	if err != nil {
		log.Infof("%v", err)
		drain.Stop(err)
	}

	// We expect drain.Wait to not block at this point.
	if err := drain.Wait(); err != nil {
		if _, ok := err.(WebSocketStreamError); !ok {
			log.Warnf("Error from app log drain server: %v", err)
		}
	}
}

func serve() error {
	addr := fmt.Sprintf(":%d", PORT)
	r := mux.NewRouter()
	r.HandleFunc("/v2/apps/{guid}/tail", tailHandler)
	// r.HandleFunc("/v2/apps/{guid}/recent", recentHandler)
	http.Handle("/", r)
	return http.ListenAndServe(addr, nil)<commit_msg>add API to fetch recent logs (no tailing)<commit_after>package main

import (
	"fmt"
	"github.com/ActiveState/log"
	"github.com/gorilla/mux"
	"github.com/gorilla/websocket"
	"net/http"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		// Ignore origin checks (won't work with wscat)
		return true
	},
}

// XXX: pass this as a log context (gorilla) object
func getWsConnId(r *http.Request, ws *websocket.Conn) string {
	return fmt.Sprintf("ws:/%v %v (subprotocol %+v)",
		r.URL.Path, ws.RemoteAddr(), ws.Subprotocol())
}

func recentHandler(w http.ResponseWriter, r *http.Request) {
	log.Infof("%v", r)
	args, err := ParseArguments(r)
	if err != nil {
		http.Error(
			w, fmt.Sprintf("Invalid arguments; %v", err), 400)
		return
	}

	recentLogs, err := recentLogs(args.Token, args.GUID, args.Num)
	if err != nil {
		http.Error(
			w, fmt.Sprintf("%v", err), 500)
		return
	}
	for _, line := range recentLogs {
		w.Write([]byte(line))
	}

}

func tailHandler(w http.ResponseWriter, r *http.Request) {
	ws, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		if _, ok := err.(websocket.HandshakeError); !ok {
			log.Infof("Handshake error: %v", err)
		} else {
			log.Infof("Unknown websocket error: %v", err)
		}
		return
	}

	args, err := ParseArguments(r)
	if err != nil {
		http.Error(
			w, fmt.Sprintf("Invalid arguments; %v", err), 400)
		return
	}

	tailHandlerWs(r, ws, args)
}

func tailHandlerWs(
	r *http.Request, ws *websocket.Conn, args *Arguments) {
	log.Infof("WS init - %v", getWsConnId(r, ws))
	defer log.Infof("WS done - %v", getWsConnId(r, ws))

	stream := &WebSocketStream{ws}

	if args.Num <= 0 {
		// First authorize with the CC by fetching something
		_, err := recentLogs(args.Token, args.GUID, 1)
		if err != nil {
			stream.Fatalf("%v", err)
			return
		}
	} else {
		// Recent history requested?
		recentLogs, err := recentLogs(args.Token, args.GUID, args.Num)
		if err != nil {
			stream.Fatalf("%v", err)
			return
		}
		for _, line := range recentLogs {
			stream.Send(line)
		}
	}

	drain, err := NewAppLogDrain(args.GUID)
	if err != nil {
		stream.Fatalf("Unable to create drain: %v", err)
		return
	}
	ch, err := drain.Start()
	if err != nil {
		stream.Fatalf("Unable to start drain: %v", err)
	}

	err = stream.Forward(ch)
	if err != nil {
		log.Infof("%v", err)
		drain.Stop(err)
	}

	// We expect drain.Wait to not block at this point.
	if err := drain.Wait(); err != nil {
		if _, ok := err.(WebSocketStreamError); !ok {
			log.Warnf("Error from app log drain server: %v", err)
		}
	}
}

func serve() error {
	addr := fmt.Sprintf(":%d", PORT)
	r := mux.NewRouter()
	r.HandleFunc("/v2/apps/{guid}/recent", recentHandler)
	r.HandleFunc("/v2/apps/{guid}/tail", tailHandler)

	http.Handle("/", r)
	return http.ListenAndServe(addr, nil)
{'fraction_non_alphanumeric': 0.16481864311219696, 'fraction_numerical': 0.00676564555534674, 'mean_word_length': 3.5526090675791275, 'pattern_counts': {'":': 2, '<': 4, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1275825', 'n_tokens_mistral': 2177, 'n_tokens_neox': 2005, 'n_words': 525}