<commit_before>// Copyright (C) 2015 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

package main

import (
	"fmt"

	"github.com/syncthing/syncthing/lib/events"
)

// The verbose logging service subscribes to events and prints these in
// verbose format to the console using INFO level.
type verboseService struct {
	stop    chan struct{} // signals time to stop
	started chan struct{} // signals startup complete
}

func newVerboseService() *verboseService {
	return &verboseService{
		stop:    make(chan struct{}),
		started: make(chan struct{}),
	}
}

// Serve runs the verbose logging service.
func (s *verboseService) Serve() {
	sub := events.Default.Subscribe(events.AllEvents)
	defer events.Default.Unsubscribe(sub)

	select {
	case <-s.started:
		// The started channel has already been closed; do nothing.
	default:
		// This is the first time around. Indicate that we're ready to start
		// processing events.
		close(s.started)
	}

	for {
		select {
		case ev := <-sub.C():
			formatted := s.formatEvent(ev)
			if formatted != "" {
				l.Verboseln(formatted)
			}
		case <-s.stop:
			return
		}
	}
}

// Stop stops the verbose logging service.
func (s *verboseService) Stop() {
	close(s.stop)
}

// WaitForStart returns once the verbose logging service is ready to receive
// events, or immediately if it's already running.
func (s *verboseService) WaitForStart() {
	<-s.started
}

func (s *verboseService) formatEvent(ev events.Event) string {
	switch ev.Type {
	case events.DownloadProgress, events.LocalIndexUpdated:
		// Skip
		return ""

	case events.Starting:
		return fmt.Sprintf("Starting up (%s)", ev.Data.(map[string]string)["home"])

	case events.StartupComplete:
		return "Startup complete"

	case events.DeviceDiscovered:
		data := ev.Data.(map[string]interface{})
		return fmt.Sprintf("Discovered device %v at %v", data["device"], data["addrs"])

	case events.DeviceConnected:
		data := ev.Data.(map[string]string)
		return fmt.Sprintf("Connected to device %v at %v (type %s)", data["id"], data["addr"], data["type"])

	case events.DeviceDisconnected:
		data := ev.Data.(map[string]string)
		return fmt.Sprintf("Disconnected from device %v", data["id"])

	case events.StateChanged:
		data := ev.Data.(map[string]interface{})
		return fmt.Sprintf("Folder %q is now %v", data["folder"], data["to"])

	case events.LocalChangeDetected:
		data := ev.Data.(map[string]string)
		return fmt.Sprintf("Local change detected in folder %q: %s %s %s", data["folder"], data["action"], data["type"], data["path"])

	case events.RemoteChangeDetected:
		data := ev.Data.(map[string]string)
		return fmt.Sprintf("Remote change detected in folder %q: %s %s %s", data["folder"], data["action"], data["type"], data["path"])

	case events.RemoteIndexUpdated:
		data := ev.Data.(map[string]interface{})
		return fmt.Sprintf("Device %v sent an index update for %q with %d items", data["device"], data["folder"], data["items"])

	case events.DeviceRejected:
		data := ev.Data.(map[string]interface{})
		return fmt.Sprintf("Rejected connection from device %v at %v", data["device"], data["address"])

	case events.FolderRejected:
		data := ev.Data.(map[string]string)
		return fmt.Sprintf("Rejected unshared folder %q from device %v", data["folder"], data["device"])

	case events.ItemStarted:<commit_msg>cmd/syncthing: Correct type assertion in verboseService (fixes #5270) (#5272)<commit_after>// Copyright (C) 2015 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

package main

import (
	"fmt"

	"github.com/syncthing/syncthing/lib/events"
)

// The verbose logging service subscribes to events and prints these in
// verbose format to the console using INFO level.
type verboseService struct {
	stop    chan struct{} // signals time to stop
	started chan struct{} // signals startup complete
}

func newVerboseService() *verboseService {
	return &verboseService{
		stop:    make(chan struct{}),
		started: make(chan struct{}),
	}
}

// Serve runs the verbose logging service.
func (s *verboseService) Serve() {
	sub := events.Default.Subscribe(events.AllEvents)
	defer events.Default.Unsubscribe(sub)

	select {
	case <-s.started:
		// The started channel has already been closed; do nothing.
	default:
		// This is the first time around. Indicate that we're ready to start
		// processing events.
		close(s.started)
	}

	for {
		select {
		case ev := <-sub.C():
			formatted := s.formatEvent(ev)
			if formatted != "" {
				l.Verboseln(formatted)
			}
		case <-s.stop:
			return
		}
	}
}

// Stop stops the verbose logging service.
func (s *verboseService) Stop() {
	close(s.stop)
}

// WaitForStart returns once the verbose logging service is ready to receive
// events, or immediately if it's already running.
func (s *verboseService) WaitForStart() {
	<-s.started
}

func (s *verboseService) formatEvent(ev events.Event) string {
	switch ev.Type {
	case events.DownloadProgress, events.LocalIndexUpdated:
		// Skip
		return ""

	case events.Starting:
		return fmt.Sprintf("Starting up (%s)", ev.Data.(map[string]string)["home"])

	case events.StartupComplete:
		return "Startup complete"

	case events.DeviceDiscovered:
		data := ev.Data.(map[string]interface{})
		return fmt.Sprintf("Discovered device %v at %v", data["device"], data["addrs"])

	case events.DeviceConnected:
		data := ev.Data.(map[string]string)
		return fmt.Sprintf("Connected to device %v at %v (type %s)", data["id"], data["addr"], data["type"])

	case events.DeviceDisconnected:
		data := ev.Data.(map[string]string)
		return fmt.Sprintf("Disconnected from device %v", data["id"])

	case events.StateChanged:
		data := ev.Data.(map[string]interface{})
		return fmt.Sprintf("Folder %q is now %v", data["folder"], data["to"])

	case events.LocalChangeDetected:
		data := ev.Data.(map[string]string)
		return fmt.Sprintf("Local change detected in folder %q: %s %s %s", data["folder"], data["action"], data["type"], data["path"])

	case events.RemoteChangeDetected:
		data := ev.Data.(map[string]string)
		return fmt.Sprintf("Remote change detected in folder %q: %s %s %s", data["folder"], data["action"], data["type"], data["path"])

	case events.RemoteIndexUpdated:
		data := ev.Data.(map[string]interface{})
		return fmt.Sprintf("Device %v sent an index update for %q with %d items", data["device"], data["folder"], data["items"])

	case events.DeviceRejected:
		data := ev.Data.(map[string]string)
		return fmt.Sprintf("Rejected connection from device %v at %v", data["device"], data["address"])

	case events.FolderRejected:
		data := ev.Data.(map[string]string)
		return fmt.Sprintf("Rejected unshared folder %q from device %v", data["folder"], data["device"])

	case events.ItemStarted:
{'fraction_non_alphanumeric': 0.14507182477599204, 'fraction_numerical': 0.0034134547006115772, 'mean_word_length': 4.335356600910471, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7367552', 'n_tokens_mistral': 2339, 'n_tokens_neox': 2133, 'n_words': 689}