You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							123 lines
						
					
					
						
							3.0 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							123 lines
						
					
					
						
							3.0 KiB
						
					
					
				
								package main
							 | 
						|
								
							 | 
						|
								import (
							 | 
						|
									"context"
							 | 
						|
									"fmt"
							 | 
						|
									"log"
							 | 
						|
									"os"
							 | 
						|
									"os/signal"
							 | 
						|
									"syscall"
							 | 
						|
									"time"
							 | 
						|
								
							 | 
						|
									"github.com/segmentio/kafka-go"
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								func main() {
							 | 
						|
									// Configuration
							 | 
						|
									brokerAddress := "localhost:9093" // Kafka gateway port (not SeaweedMQ broker port 17777)
							 | 
						|
									topicName := "_raw_messages"      // Topic with "_" prefix - should skip schema validation
							 | 
						|
									groupID := "raw-message-consumer"
							 | 
						|
								
							 | 
						|
									fmt.Printf("Consuming messages from topic '%s' on broker '%s'\n", topicName, brokerAddress)
							 | 
						|
								
							 | 
						|
									// Create a new reader
							 | 
						|
									reader := kafka.NewReader(kafka.ReaderConfig{
							 | 
						|
										Brokers: []string{brokerAddress},
							 | 
						|
										Topic:   topicName,
							 | 
						|
										GroupID: groupID,
							 | 
						|
										// Start reading from the beginning for testing
							 | 
						|
										StartOffset: kafka.FirstOffset,
							 | 
						|
										// Configure for quick consumption
							 | 
						|
										MinBytes: 1,
							 | 
						|
										MaxBytes: 10e6, // 10MB
							 | 
						|
									})
							 | 
						|
									defer reader.Close()
							 | 
						|
								
							 | 
						|
									// Set up signal handling for graceful shutdown
							 | 
						|
									ctx, cancel := context.WithCancel(context.Background())
							 | 
						|
									defer cancel()
							 | 
						|
								
							 | 
						|
									sigChan := make(chan os.Signal, 1)
							 | 
						|
									signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
							 | 
						|
								
							 | 
						|
									go func() {
							 | 
						|
										<-sigChan
							 | 
						|
										fmt.Println("\nReceived shutdown signal, stopping consumer...")
							 | 
						|
										cancel()
							 | 
						|
									}()
							 | 
						|
								
							 | 
						|
									fmt.Println("Starting to consume messages (Press Ctrl+C to stop)...")
							 | 
						|
									fmt.Println("=" + fmt.Sprintf("%60s", "="))
							 | 
						|
								
							 | 
						|
									messageCount := 0
							 | 
						|
								
							 | 
						|
									for {
							 | 
						|
										select {
							 | 
						|
										case <-ctx.Done():
							 | 
						|
											fmt.Printf("\nStopped consuming. Total messages processed: %d\n", messageCount)
							 | 
						|
											return
							 | 
						|
										default:
							 | 
						|
											// Set a timeout for reading messages
							 | 
						|
											msgCtx, msgCancel := context.WithTimeout(ctx, 5*time.Second)
							 | 
						|
								
							 | 
						|
											message, err := reader.ReadMessage(msgCtx)
							 | 
						|
											msgCancel()
							 | 
						|
								
							 | 
						|
											if err != nil {
							 | 
						|
												if err == context.DeadlineExceeded {
							 | 
						|
													fmt.Print(".")
							 | 
						|
													continue
							 | 
						|
												}
							 | 
						|
												log.Printf("Error reading message: %v", err)
							 | 
						|
												continue
							 | 
						|
											}
							 | 
						|
								
							 | 
						|
											messageCount++
							 | 
						|
								
							 | 
						|
											// Display message details
							 | 
						|
											fmt.Printf("\nMessage #%d:\n", messageCount)
							 | 
						|
											fmt.Printf("   Partition: %d, Offset: %d\n", message.Partition, message.Offset)
							 | 
						|
											fmt.Printf("   Key: %s\n", string(message.Key))
							 | 
						|
											fmt.Printf("   Value: %s\n", string(message.Value))
							 | 
						|
											fmt.Printf("   Timestamp: %s\n", message.Time.Format(time.RFC3339))
							 | 
						|
								
							 | 
						|
											// Display headers if present
							 | 
						|
											if len(message.Headers) > 0 {
							 | 
						|
												fmt.Printf("   Headers:\n")
							 | 
						|
												for _, header := range message.Headers {
							 | 
						|
													fmt.Printf("     %s: %s\n", header.Key, string(header.Value))
							 | 
						|
												}
							 | 
						|
											}
							 | 
						|
								
							 | 
						|
											// Try to detect content type
							 | 
						|
											contentType := detectContentType(message.Value)
							 | 
						|
											fmt.Printf("   Content Type: %s\n", contentType)
							 | 
						|
								
							 | 
						|
											fmt.Printf("   Raw Size: %d bytes\n", len(message.Value))
							 | 
						|
											fmt.Println("   " + fmt.Sprintf("%50s", "-"))
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// detectContentType tries to determine the content type of the message
							 | 
						|
								func detectContentType(data []byte) string {
							 | 
						|
									if len(data) == 0 {
							 | 
						|
										return "empty"
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Check if it looks like JSON
							 | 
						|
									trimmed := string(data)
							 | 
						|
									if (trimmed[0] == '{' && trimmed[len(trimmed)-1] == '}') ||
							 | 
						|
										(trimmed[0] == '[' && trimmed[len(trimmed)-1] == ']') {
							 | 
						|
										return "JSON"
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Check if it's printable text
							 | 
						|
									for _, b := range data {
							 | 
						|
										if b < 32 && b != 9 && b != 10 && b != 13 { // Allow tab, LF, CR
							 | 
						|
											return "binary"
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									return "text"
							 | 
						|
								}
							 |