package meowlib import ( "bytes" "encoding/json" "fmt" "net/http" "os" "time" "github.com/rs/zerolog" ) type LokiWriter struct { url string labels map[string]string httpClient *http.Client } type LokiPayload struct { Streams []LokiStream `json:"streams"` } type LokiStream struct { Stream map[string]string `json:"stream"` Values [][]string `json:"values"` } func NewLokiWriter(url string, labels map[string]string) *LokiWriter { return &LokiWriter{ url: url, labels: labels, httpClient: &http.Client{}, } } func (w *LokiWriter) Write(p []byte) (n int, err error) { // Use zerolog to parse the log level var event map[string]interface{} if err := json.Unmarshal(p, &event); err != nil { return 0, fmt.Errorf("failed to unmarshal log event: %w", err) } level := "" if l, ok := event["level"].(string); ok { level = l } message := "" if m, ok := event["message"].(string); ok { message = m } // Add log level to labels labels := make(map[string]string) for k, v := range w.labels { labels[k] = v } labels["level"] = level // Format the timestamp in nanoseconds timestamp := fmt.Sprintf("%d000000", time.Now().UnixNano()/int64(time.Millisecond)) stream := LokiStream{ Stream: labels, Values: [][]string{ {timestamp, message}, }, } payload := LokiPayload{ Streams: []LokiStream{stream}, } payloadBytes, err := json.Marshal(payload) if err != nil { return 0, fmt.Errorf("failed to marshal payload: %w", err) } fmt.Printf("Sending payload to Loki: %s\n", string(payloadBytes)) req, err := http.NewRequest("POST", w.url, bytes.NewReader(payloadBytes)) if err != nil { return 0, fmt.Errorf("failed to create HTTP request: %w", err) } req.Header.Set("Content-Type", "application/json") resp, err := w.httpClient.Do(req) if err != nil { return 0, fmt.Errorf("failed to send log to Loki: %w", err) } defer resp.Body.Close() fmt.Printf("Loki response status: %d\n", resp.StatusCode) if resp.StatusCode != http.StatusNoContent { return 0, fmt.Errorf("received non-204 response from Loki: %d", resp.StatusCode) } return len(p), nil } func main() { lokiURL := "http://your-loki-url/loki/api/v1/push" labels := map[string]string{ "app": "your_app_name", // Add more labels as needed } lokiWriter := NewLokiWriter(lokiURL, labels) consoleWriter := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339} multiWriter := zerolog.MultiLevelWriter(consoleWriter, lokiWriter) logger := zerolog.New(multiWriter).With().Timestamp().Logger() // Configure the logger in the sublibrary sublibrary.AddLogger(logger) logger.Info().Msg("Main library log message") sublibrary.SublibraryFunction() }