This article demonstrates how to stream logs from a Java application running on a local Mac directly into Azure Event Hub using the Azure SDK for Java.

Prerequisites

  • Java 17+
  • Maven
  • Azure Event Hub Namespace, Event Hub, and SAS Key
  • Azure CLI configured and logged in
  • Internet access to download dependencies

Project Structure





java-eventhub-logger/
├── pom.xml
├── src
│   └── main
│       ├── java
│       │   ├── DemoAppLogger.java
│       │   └── EHLogTailStreamer.java
│       └── resources
│           └── logback.xml
└── logs
    └── app.log

pom.xml





<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>java-eventhub-logger</artifactId>
  <version>1.0.0</version>

  <properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
  </properties>

  <dependencies>
    <!-- Azure Event Hubs SDK -->
    <dependency>
      <groupId>com.azure</groupId>
      <artifactId>azure-messaging-eventhubs</artifactId>
      <version>5.17.0</version>
    </dependency>

    <!-- SLF4J Logging -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-simple</artifactId>
      <version>2.0.13</version>
    </dependency>

    <!-- Apache Commons IO for tailing logs -->
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.15.1</version>
    </dependency>
  </dependencies>
</project>

DemoAppLogger.java

This is a demo Java app that generates the logs to the app.log file.

import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.TimeUnit;

public class DemoAppLogger {
    public static void main(String[] args) throws IOException, InterruptedException {
        FileWriter writer = new FileWriter("logs/app.log", true);
        Random random = new Random();
        String[] levels = {"INFO", "DEBUG", "WARN", "ERROR"};

        while (true) {
            String level = levels[random.nextInt(levels.length)];
            String log = String.format("%s - [%s] This is a simulated %s message\n",
                    java.time.LocalDateTime.now(), level, level.toLowerCase());
            writer.write(log);
            writer.flush();
            TimeUnit.SECONDS.sleep(2);
        }
    }
}

EHLogTailStreamer.java





import com.azure.messaging.eventhubs.EventData;
import com.azure.messaging.eventhubs.EventHubProducerClient;
import com.azure.messaging.eventhubs.EventHubClientBuilder;
import org.apache.commons.io.input.Tailer;
import org.apache.commons.io.input.TailerListenerAdapter;

import java.util.Collections;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class EHLogTailStreamer {

    private static final String CONNECTION_STRING = "Endpoint=sb://<eendpoint>/;SharedAccessKeyName=<actual key name>;SharedAccessKey=<access key>;EntityPath=<event-hub-name>";
    private static final String LOG_FILE_PATH = "logs/app.log";

    public static void main(String[] args) {
        EventHubProducerClient producer = new EventHubClientBuilder()
                .connectionString(CONNECTION_STRING)
                .buildProducerClient();

        TailerListenerAdapter listener = new TailerListenerAdapter() {
            @Override
            public void handle(String line) {
                try {
                    System.out.println("Sending log: " + line);
                    producer.send(Collections.singletonList(new EventData(line)));
                } catch (Exception e) {
                    System.err.println("Failed to send log: " + e.getMessage());
                }
            }
        };

        Tailer tailer = new Tailer(new java.io.File(LOG_FILE_PATH), listener, 2000, true);
        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.submit(tailer::run);

        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            producer.close();
            executor.shutdown();
        }));
    }
}

logback.xml





<configuration>
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>logs/app.log</file>
    <append>true</append>
    <encoder>
      <pattern>%date [%thread] %-5level %logger - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="INFO">
    <appender-ref ref="FILE" />
  </root>
</configuration>

Run the App

1. Generate Logs





mvn compile exec:java -Dexec.mainClass="DemoAppLogger"




mvn compile exec:java -Dexec.mainClass="DemoAppLogger"

[INFO] Scanning for projects...
[INFO] 
[INFO] ------------------< com.example:java-eventhub-logger >------------------
[INFO] Building java-eventhub-logger 1.0.0
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- resources:3.3.1:resources (default-resources) @ java-eventhub-logger ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource from src/main/resources to target/classes
[INFO] 
[INFO] --- compiler:3.13.0:compile (default-compile) @ java-eventhub-logger ---
[INFO] Nothing to compile - all classes are up to date.
[INFO] 
[INFO] --- exec:3.5.1:java (default-cli) @ java-eventhub-logger ---

2. Stream to Event Hub





mvn compile exec:java -Dexec.mainClass="EHLogTailStreamer"
mvn compile exec:java -Dexec.mainClass="EHLogTailStreamer"

[INFO] Scanning for projects...
[INFO] 
[INFO] ------------------< com.example:java-eventhub-logger >------------------
[INFO] Building java-eventhub-logger 1.0.0
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- resources:3.3.1:resources (default-resources) @ java-eventhub-logger ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource from src/main/resources to target/classes
[INFO] 
[INFO] --- compiler:3.13.0:compile (default-compile) @ java-eventhub-logger ---
[INFO] Nothing to compile - all classes are up to date.
[INFO] 
[INFO] --- exec:3.5.1:java (default-cli) @ java-eventhub-logger ---
[EHLogTailStreamer.main()] INFO com.azure.messaging.eventhubs.EventHubClientBuilder - {"az.sdk.message":"Emitting a single connection.","connectionId":"MF_9e944c_1751012373534"}
[EHLogTailStreamer.main()] INFO com.azure.messaging.eventhubs.implementation.EventHubConnectionProcessor - {"az.sdk.message":"Setting next AMQP channel.","entityPath":"rranjan-event"}
Sending log: 2025-06-27T13:49:35.374570 - [ERROR] This is a simulated error message
Sending log: 2025-06-27T13:49:37.380537 - [INFO] This is a simulated info message
Sending log: 2025-06-27T13:49:39.385760 - [ERROR] This is a simulated error message
Sending log: 2025-06-27T13:49:41.389575 - [INFO] This is a simulated info message

Validate in Azure

Log in to the Azure portal and validate the same in Event Hub under both Metrics and Data Explorer.

Using Azure Portal

  1. Navigate to your Event Hub Namespace.
  2. Click on your Event Hub (e.g., rranjan-event).
  3. Go to Metrics to visualize throughput.
  4. Enable Capture to route logs to Blob or Data Lake.
  5. Use Diagnostic settings to archive or pipe to Log Analytics.

In this guide, we walked through building a lightweight Java application that logs messages to a file using SLF4J + Logback and streams those logs to Azure Event Hub in near real-time using the Azure SDK. With end-to-end validation in the Azure Portal(can also be done via Azure CLI), this approach is well-suited for custom observability pipelines, audit logging, or streaming telemetry use cases.

Whether you’re building a large-scale distributed system or just need a reliable logging relay, this pattern is easy to extend with batching, retry policies, and error-handling enhancements.

#AzureEventHub #JavaLogging #Observability #LogStreaming #AzureSDK #DevOps #CloudLogging 

The code will be uploaded to my GitHub.

Reach out on LinkedIn for any questions or


Discover more from Tech Insights & Blogs by Rahul Ranjan

Subscribe to get the latest posts sent to your email.

Leave a comment

Trending