add logging service for service-wide logging
This commit is contained in:
		
							parent
							
								
									5fa4371b33
								
							
						
					
					
						commit
						0508a4867e
					
				|  | @ -0,0 +1,74 @@ | |||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/bdlm/log" | ||||
| 	"github.com/satori/go.uuid" | ||||
| 	"github.com/streadway/amqp" | ||||
| 
 | ||||
| 	srv "dev.sum7.eu/genofire/microservices-collection/logging" | ||||
| ) | ||||
| 
 | ||||
| const ServiceName = "eu.sum7.log-cmd" | ||||
| 
 | ||||
| var ServiceID = uuid.Must(uuid.NewV4()) | ||||
| 
 | ||||
| func main() { | ||||
| 	log.SetFormatter(&log.TextFormatter{ | ||||
| 		DisableTimestamp: true, | ||||
| 	}) | ||||
| 
 | ||||
| 	logLevel, err := strconv.ParseUint(os.Args[1], 10, 32) | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Failed to parse LogLevel: %s", err) | ||||
| 	} | ||||
| 	logMessage := srv.LogMessage{ | ||||
| 		ServiceName: ServiceName, | ||||
| 		ServiceID:   ServiceID, | ||||
| 		Time:        time.Now(), | ||||
| 		Level:       uint32(logLevel), | ||||
| 		Message:     strings.Join(os.Args[2:], " "), | ||||
| 	} | ||||
| 	body, err := json.Marshal(logMessage) | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Failed to parse LogLevel: %s", err) | ||||
| 	} | ||||
| 
 | ||||
| 	conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/") | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Failed to connect to RabbitMQ: %s", err) | ||||
| 	} | ||||
| 	defer conn.Close() | ||||
| 
 | ||||
| 	ch, err := conn.Channel() | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Failed to open a channel: %s", err) | ||||
| 	} | ||||
| 	defer ch.Close() | ||||
| 
 | ||||
| 	if err = srv.ExchangeDeclare(ch); err != nil { | ||||
| 		log.Fatalf("Failed to declare an exchange: %s", err) | ||||
| 	} | ||||
| 
 | ||||
| 	err = ch.Publish( | ||||
| 		srv.EXCHANGE, | ||||
| 		fmt.Sprintf("%d.%s", logLevel, ServiceName), | ||||
| 		false, | ||||
| 		false, | ||||
| 		amqp.Publishing{ | ||||
| 			ContentType:  "application/json", | ||||
| 			DeliveryMode: amqp.Persistent, | ||||
| 			Body:         body, | ||||
| 		}) | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Failed to publish log message: %s", err) | ||||
| 	} | ||||
| 
 | ||||
| 	log.Printf(" [x] Sent %s", body) | ||||
| } | ||||
|  | @ -0,0 +1,128 @@ | |||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"os/signal" | ||||
| 	"syscall" | ||||
| 
 | ||||
| 	"github.com/bdlm/log" | ||||
| 	"github.com/bdlm/std/logger" | ||||
| 	"github.com/streadway/amqp" | ||||
| 
 | ||||
| 	"dev.sum7.eu/genofire/microservices-collection/lib" | ||||
| 	srv "dev.sum7.eu/genofire/microservices-collection/logging" | ||||
| ) | ||||
| 
 | ||||
| var logRecieved = false | ||||
| 
 | ||||
| func main() { | ||||
| 	flag.BoolVar(&logRecieved, "recieved", logRecieved, "show recieved log on console") | ||||
| 	flag.Parse() | ||||
| 	lib.LogUpdateConfig() | ||||
| 
 | ||||
| 	conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/") | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Failed to connect to RabbitMQ: %s", err) | ||||
| 	} | ||||
| 	defer conn.Close() | ||||
| 
 | ||||
| 	ch, err := conn.Channel() | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Failed to open a channel: %s", err) | ||||
| 	} | ||||
| 	defer ch.Close() | ||||
| 
 | ||||
| 	if err = srv.ExchangeDeclare(ch); err != nil { | ||||
| 		log.Fatalf("Failed to declare an exchange: %s", err) | ||||
| 	} | ||||
| 
 | ||||
| 	q, err := ch.QueueDeclare( | ||||
| 		"",    // name
 | ||||
| 		false, // durable
 | ||||
| 		false, // delete when usused
 | ||||
| 		true,  // exclusive
 | ||||
| 		false, // no-wait
 | ||||
| 		nil,   // arguments
 | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Failed to declare a queue: %s", err) | ||||
| 	} | ||||
| 
 | ||||
| 	err = ch.QueueBind( | ||||
| 		q.Name,       // queue name
 | ||||
| 		"",           // routing key
 | ||||
| 		srv.EXCHANGE, // exchange
 | ||||
| 		false, | ||||
| 		nil) | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Failed to bind a queue: %s", err) | ||||
| 	} | ||||
| 
 | ||||
| 	msgs, err := ch.Consume( | ||||
| 		q.Name, // queue
 | ||||
| 		"",     // consumer
 | ||||
| 		true,   // auto-ack
 | ||||
| 		false,  // exclusive
 | ||||
| 		false,  // no-local
 | ||||
| 		false,  // no-wait
 | ||||
| 		nil,    // args
 | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Failed to register a consumer: %s", err) | ||||
| 	} | ||||
| 
 | ||||
| 	loggerRecieved := log.New() | ||||
| 	loggerRecieved.SetLevel(logger.Trace) | ||||
| 
 | ||||
| 	go func() { | ||||
| 		for d := range msgs { | ||||
| 			var logMessage *srv.LogMessage | ||||
| 			if err := json.Unmarshal([]byte(d.Body), &logMessage); err != nil { | ||||
| 				log.Fatal(err) | ||||
| 			} | ||||
| 			//TODO write to Database (to get last values for web client)
 | ||||
| 
 | ||||
| 			// output to console
 | ||||
| 			if !logRecieved { | ||||
| 				continue | ||||
| 			} | ||||
| 			e := &log.Entry{ | ||||
| 				Logger: loggerRecieved, | ||||
| 				Time:   logMessage.Time, | ||||
| 				Data:   logMessage.Data, | ||||
| 			} | ||||
| 			e = e.WithFields(map[string]interface{}{ | ||||
| 				"service_name": logMessage.ServiceName, | ||||
| 				"service_id":   logMessage.ServiceID, | ||||
| 				"log_level":    logMessage.Level, | ||||
| 			}) | ||||
| 			lvl := logger.Level(uint32(logMessage.Level)) | ||||
| 			if lvl >= logger.Trace { | ||||
| 				e.Debug(fmt.Sprintf("[trace] %s", logMessage.Message)) | ||||
| 			} else if lvl >= logger.Debug { | ||||
| 				e.Debug(logMessage.Message) | ||||
| 			} else if lvl >= logger.Info { | ||||
| 				e.Info(logMessage.Message) | ||||
| 			} else if lvl >= logger.Warn { | ||||
| 				e.Warn(logMessage.Message) | ||||
| 			} else if lvl >= logger.Error { | ||||
| 				e.Error(logMessage.Message) | ||||
| 			} else if lvl >= logger.Panic { | ||||
| 				e.Error(fmt.Sprintf("[panic] %s", logMessage.Message)) | ||||
| 			} else if lvl >= logger.Fatal { | ||||
| 				e.Error(fmt.Sprintf("[fatal] %s", logMessage.Message)) | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
| 
 | ||||
| 	log.Debug("started") | ||||
| 
 | ||||
| 	// Wait for INT/TERM
 | ||||
| 	sigs := make(chan os.Signal, 1) | ||||
| 	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) | ||||
| 	sig := <-sigs | ||||
| 	log.WithField("recieved", sig).Info("stopped") | ||||
| } | ||||
|  | @ -0,0 +1,43 @@ | |||
| package logging | ||||
| 
 | ||||
| import ( | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/bdlm/log" | ||||
| 	"github.com/satori/go.uuid" | ||||
| 	"github.com/streadway/amqp" | ||||
| ) | ||||
| 
 | ||||
| const EXCHANGE = "sum7.logging" | ||||
| 
 | ||||
| func ExchangeDeclare(ch *amqp.Channel) error { | ||||
| 	return ch.ExchangeDeclare( | ||||
| 		EXCHANGE, | ||||
| 		"direct", | ||||
| 		true, | ||||
| 		false, | ||||
| 		false, | ||||
| 		false, | ||||
| 		nil, | ||||
| 	) | ||||
| } | ||||
| 
 | ||||
| type LogMessage struct { | ||||
| 	ServiceName string                 `json:"sname"` | ||||
| 	ServiceID   uuid.UUID              `json:"sid"` | ||||
| 	Time        time.Time              `json:"time"` | ||||
| 	Level       uint32                 `json:"level"` | ||||
| 	Message     string                 `json:"message"` | ||||
| 	Data        map[string]interface{} `json:"data"` | ||||
| } | ||||
| 
 | ||||
| func LogMessageFromEntry(sname string, sid uuid.UUID, e *log.Entry) *LogMessage { | ||||
| 	return &LogMessage{ | ||||
| 		ServiceName: sname, | ||||
| 		ServiceID:   sid, | ||||
| 		Time:        e.Time, | ||||
| 		Level:       uint32(e.Level), | ||||
| 		Message:     e.Message, | ||||
| 		Data:        e.Data, | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue