<commit_before>package apptail

import (
	"encoding/json"
	"github.com/ActiveState/log"
	"github.com/ActiveState/zmqpubsub"
	"logyard"
	"logyard/clients/sieve"
	"time"
)

type App struct {
	GUID  string `json:"guid"`
	Space string `json:"space_guid"`
	Name  string `json:"name"`
}

type TimelineEvent struct {
	App App `json:"app"`
}

// Make relevant cloud events available in application logs. Heroku style.
func MonitorCloudEvents(nodeid string) {
	sub := logyard.Broker.Subscribe("event.timeline")
	defer sub.Stop()

	pub := logyard.Broker.NewPublisherMust()
	defer pub.Stop()

	log.Info("Listening for app relevant cloud events...")
	for msg := range sub.Ch {
		var event sieve.Event

		err := json.Unmarshal([]byte(msg.Value), &event)
		if err != nil {
			log.Fatal(err) // not expected at all
		}

		// Re-parse the event json record into a TimelineEvent structure.
		var t TimelineEvent
		if data, err := json.Marshal(event.Info); err != nil {
			log.Fatal(err)
		} else {
			err = json.Unmarshal(data, &t)
			if err != nil {
				log.Fatalf("Invalid timeline event: %v", err)
			}
		}

		// TODO: add an instance_index properly to the timeline event
		index := -1 // FIXME: find the instance index; use -1 only for non-app instances (eg: staging)

		source := "stackato." + event.Process

		PublishAppLog(pub, t, index, source, nodeid, &event)
	}
	log.Warn("Finished listening for app relevant cloud events.")

	err := sub.Wait()
	if err != nil {
		log.Fatal(err)
	}
}

func PublishAppLog(
	pub *zmqpubsub.Publisher,
	t TimelineEvent,
	index int, source string, nodeid string, event *sieve.Event) {

	err := (&AppLogMessage{
		Text:          event.Desc,
		LogFilename:   "",
		UnixTime:      event.UnixTime,
		HumanTime:     time.Unix(event.UnixTime, 0).Format("2006-01-02T15:04:05-07:00"), // heroku-format
		Source:        source,
		InstanceIndex: index,
		AppGUID:       t.App.GUID,
		AppName:       t.App.Name,
		AppSpace:      t.App.Space,
		NodeID:        nodeid,
	}).Publish(pub, true)

	if err != nil {
		log.Fatal(err)
	}
}<commit_msg>Bug #101139 - use instance_index<commit_after>package apptail

import (
	"encoding/json"
	"github.com/ActiveState/log"
	"github.com/ActiveState/zmqpubsub"
	"logyard"
	"logyard/clients/sieve"
	"time"
)

type App struct {
	GUID  string `json:"guid"`
	Space string `json:"space_guid"`
	Name  string `json:"name"`
}

type TimelineEvent struct {
	App           App `json:"app"`
	InstanceIndex int `json:"instance_index"`
}

// Make relevant cloud events available in application logs. Heroku style.
func MonitorCloudEvents(nodeid string) {
	sub := logyard.Broker.Subscribe("event.timeline")
	defer sub.Stop()

	pub := logyard.Broker.NewPublisherMust()
	defer pub.Stop()

	log.Info("Listening for app relevant cloud events...")
	for msg := range sub.Ch {
		var event sieve.Event

		err := json.Unmarshal([]byte(msg.Value), &event)
		if err != nil {
			log.Fatal(err) // not expected at all
		}

		// Re-parse the event json record into a TimelineEvent structure.
		var t TimelineEvent
		if data, err := json.Marshal(event.Info); err != nil {
			log.Fatal(err)
		} else {
			err = json.Unmarshal(data, &t)
			if err != nil {
				log.Fatalf("Invalid timeline event: %v", err)
			}
		}

		source := "stackato." + event.Process

		PublishAppLog(pub, t, source, nodeid, &event)
	}
	log.Warn("Finished listening for app relevant cloud events.")

	err := sub.Wait()
	if err != nil {
		log.Fatal(err)
	}
}

func PublishAppLog(
	pub *zmqpubsub.Publisher,
	t TimelineEvent,
	source string, nodeid string, event *sieve.Event) {

	err := (&AppLogMessage{
		Text:          event.Desc,
		LogFilename:   "",
		UnixTime:      event.UnixTime,
		HumanTime:     time.Unix(event.UnixTime, 0).Format("2006-01-02T15:04:05-07:00"), // heroku-format
		Source:        source,
		InstanceIndex: t.InstanceIndex,
		AppGUID:       t.App.GUID,
		AppName:       t.App.Name,
		AppSpace:      t.App.Space,
		NodeID:        nodeid,
	}).Publish(pub, true)

	if err != nil {
		log.Fatal(err)
	}
}
{'fraction_non_alphanumeric': 0.1380429355966051, 'fraction_numerical': 0.011482775836245632, 'mean_word_length': 3.294748124330118, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '1499561', 'n_tokens_mistral': 1547, 'n_tokens_neox': 1410, 'n_words': 363}