google-site-verification: google61fe8ba583a51912.html
Lumigo for Serverless in Java: Complete Distributed Tracing Guide

Introduction to Lumigo

Lumigo is a serverless monitoring and debugging platform that provides distributed tracing, performance monitoring, and troubleshooting capabilities for serverless applications. It automatically instruments AWS Lambda functions to provide end-to-end visibility.

Key Features

  • Automatic Tracing: Zero-code instrumentation for AWS services
  • Distributed Tracing: End-to-end request tracking across services
  • Performance Monitoring: Latency, memory usage, and cold start tracking
  • Debugging Tools: Interactive trace exploration and error analysis
  • Security Insights: Vulnerability detection and compliance monitoring

Implementation Guide

Dependencies

Add to your pom.xml:

<properties> <aws.lambda.java.version>1.2.3</aws.lambda.java.version> <lumigo.version>1.0.13</lumigo.version> <awssdk.version>2.20.56</awssdk.version> </properties> <dependencies> <!-- AWS Lambda Core --> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> <version>${aws.lambda.java.version}</version> </dependency> <!-- Lumigo Tracer --> <dependency> <groupId>io.lumigo</groupId> <artifactId>lumigo-java-tracer</artifactId> <version>${lumigo.version}</version> </dependency> <!-- AWS SDK v2 --> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>dynamodb</artifactId> <version>${awssdk.version}</version> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3</artifactId> <version>${awssdk.version}</version> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>sns</artifactId> <version>${awssdk.version}</version> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>sqs</artifactId> <version>${awssdk.version}</version> </dependency> <!-- JSON Processing --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> </dependency> <!-- Logging --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>2.0.7</version> </dependency> </dependencies>

Basic Lambda Function with Lumigo

package com.example.lumigo; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.LambdaLogger; import io.lumigo.Lumigo; import io.lumigo.models.Span; import java.util.Map; import java.util.HashMap; public class BasicLumigoFunction implements RequestHandler<Map<String, Object>, Map<String, Object>> { static { // Initialize Lumigo with your token Lumigo.init("your-lumigo-token-here"); } @Override public Map<String, Object> handleRequest(Map<String, Object> input, Context context) { LambdaLogger logger = context.getLogger(); // Start Lumigo span for this invocation Span span = Lumigo.startSpan("BasicLumigoFunction"); try { logger.log("Processing request: " + input); // Add custom attributes to the span span.addAttribute("functionName", context.getFunctionName()); span.addAttribute("awsRequestId", context.getAwsRequestId()); span.addAttribute("inputSize", input.size()); // Business logic Map<String, Object> result = processBusinessLogic(input, context); // Add response attributes span.addAttribute("processingStatus", "success"); span.addAttribute("resultSize", result.size()); return result; } catch (Exception e) { // Record exception in Lumigo span.recordException(e); span.addAttribute("processingStatus", "failed"); logger.log("Error processing request: " + e.getMessage()); throw e; } finally { // End the span Lumigo.endSpan(span); } } private Map<String, Object> processBusinessLogic(Map<String, Object> input, Context context) { Map<String, Object> result = new HashMap<>(); result.put("status", "processed"); result.put("message", "Hello from Lumigo-instrumented Lambda!"); result.put("timestamp", System.currentTimeMillis()); result.put("inputKeys", input.keySet()); // Simulate some work try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return result; } }

Advanced Lumigo Configuration

package com.example.lumigo; import io.lumigo.Lumigo; import io.lumigo.LumigoConfiguration; import io.lumigo.models.Span; public class LumigoConfigurator { public static void initializeLumigo() { LumigoConfiguration config = LumigoConfiguration.builder() .token(System.getenv("LUMIGO_TRACER_TOKEN")) .debugEnabled(Boolean.parseBoolean(System.getenv("LUMIGO_DEBUG"))) .edgeHost(System.getenv().getOrDefault("LUMIGO_EDGE", "default-edge.lumigo.io")) .timeout(Integer.parseInt(System.getenv().getOrDefault("LUMIGO_TIMEOUT", "10000"))) .maxSizeForRequest(Integer.parseInt(System.getenv().getOrDefault("LUMIGO_MAX_REQUEST_SIZE", "2048"))) .reportTimeout(Integer.parseInt(System.getenv().getOrDefault("LUMIGO_REPORT_TIMEOUT", "60000"))) .build(); Lumigo.init(config); } public static LumigoConfiguration getDefaultConfig() { return LumigoConfiguration.builder() .token("your-lumigo-token") .debugEnabled(false) .timeout(10000) .maxSizeForRequest(2048) .reportTimeout(60000) .edgeHost("default-edge.lumigo.io") .build(); } }

Serverless Application with Multiple AWS Services

package com.example.lumigo; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.LambdaLogger; import io.lumigo.Lumigo; import io.lumigo.models.Span; import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider; import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.*; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.sns.SnsClient; import software.amazon.awssdk.services.sns.model.PublishRequest; import software.amazon.awssdk.services.sqs.SqsClient; import software.amazon.awssdk.services.sqs.model.SendMessageRequest; import java.util.Map; import java.util.HashMap; import java.util.UUID; public class OrderProcessingFunction implements RequestHandler<Map<String, Object>, Map<String, Object>> { private final DynamoDbClient dynamoDb; private final S3Client s3Client; private final SnsClient snsClient; private final SqsClient sqsClient; private static final String ORDERS_TABLE = System.getenv("ORDERS_TABLE"); private static final String PROCESSING_BUCKET = System.getenv("PROCESSING_BUCKET"); private static final String NOTIFICATION_TOPIC = System.getenv("NOTIFICATION_TOPIC"); private static final String DEAD_LETTER_QUEUE = System.getenv("DEAD_LETTER_QUEUE"); static { LumigoConfigurator.initializeLumigo(); } public OrderProcessingFunction() { this.dynamoDb = DynamoDbClient.builder() .region(Region.of(System.getenv("AWS_REGION"))) .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) .build(); this.s3Client = S3Client.builder() .region(Region.of(System.getenv("AWS_REGION"))) .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) .build(); this.snsClient = SnsClient.builder() .region(Region.of(System.getenv("AWS_REGION"))) .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) .build(); this.sqsClient = SqsClient.builder() .region(Region.of(System.getenv("AWS_REGION"))) .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) .build(); } @Override public Map<String, Object> handleRequest(Map<String, Object> input, Context context) { LambdaLogger logger = context.getLogger(); Span rootSpan = Lumigo.startSpan("OrderProcessingFunction"); try { logger.log("Starting order processing: " + input); // Validate input if (!isValidOrder(input)) { throw new IllegalArgumentException("Invalid order data"); } String orderId = generateOrderId(); rootSpan.addAttribute("orderId", orderId); rootSpan.addAttribute("customerId", input.get("customerId").toString()); // Step 1: Store order in DynamoDB storeOrderInDynamoDB(input, orderId, rootSpan); // Step 2: Save order details to S3 saveOrderToS3(input, orderId, rootSpan); // Step 3: Process payment boolean paymentSuccess = processPayment(input, orderId, rootSpan); if (paymentSuccess) { // Step 4: Send success notification sendSuccessNotification(input, orderId, rootSpan); Map<String, Object> result = new HashMap<>(); result.put("status", "SUCCESS"); result.put("orderId", orderId); result.put("message", "Order processed successfully"); rootSpan.addAttribute("finalStatus", "success"); return result; } else { // Step 5: Send to dead letter queue for failed payments sendToDeadLetterQueue(input, orderId, rootSpan); Map<String, Object> result = new HashMap<>(); result.put("status", "PAYMENT_FAILED"); result.put("orderId", orderId); result.put("message", "Payment processing failed"); rootSpan.addAttribute("finalStatus", "payment_failed"); return result; } } catch (Exception e) { rootSpan.recordException(e); rootSpan.addAttribute("finalStatus", "error"); logger.log("Error in order processing: " + e.getMessage()); throw e; } finally { Lumigo.endSpan(rootSpan); } } private boolean isValidOrder(Map<String, Object> order) { return order.containsKey("customerId") && order.containsKey("items") && order.containsKey("totalAmount"); } private String generateOrderId() { return "ORD-" + UUID.randomUUID().toString().substring(0, 8).toUpperCase(); } private void storeOrderInDynamoDB(Map<String, Object> order, String orderId, Span parentSpan) { Span span = Lumigo.startSpan("DynamoDB-StoreOrder", parentSpan); try { Map<String, AttributeValue> item = new HashMap<>(); item.put("orderId", AttributeValue.builder().s(orderId).build()); item.put("customerId", AttributeValue.builder().s(order.get("customerId").toString()).build()); item.put("totalAmount", AttributeValue.builder().n(order.get("totalAmount").toString()).build()); item.put("createdAt", AttributeValue.builder().n(String.valueOf(System.currentTimeMillis())).build()); item.put("status", AttributeValue.builder().s("PROCESSING").build()); if (order.containsKey("items")) { item.put("items", AttributeValue.builder().s(order.get("items").toString()).build()); } PutItemRequest request = PutItemRequest.builder() .tableName(ORDERS_TABLE) .item(item) .build(); dynamoDb.putItem(request); span.addAttribute("dynamodb.table", ORDERS_TABLE); span.addAttribute("dynamodb.operation", "PutItem"); span.addAttribute("orderId", orderId); } catch (Exception e) { span.recordException(e); throw e; } finally { Lumigo.endSpan(span); } } private void saveOrderToS3(Map<String, Object> order, String orderId, Span parentSpan) { Span span = Lumigo.startSpan("S3-SaveOrder", parentSpan); try { String key = "orders/" + orderId + ".json"; String orderJson = convertToJson(order); PutObjectRequest request = PutObjectRequest.builder() .bucket(PROCESSING_BUCKET) .key(key) .contentType("application/json") .build(); s3Client.putObject(request, software.amazon.awssdk.core.sync.RequestBody.fromBytes(orderJson.getBytes())); span.addAttribute("s3.bucket", PROCESSING_BUCKET); span.addAttribute("s3.key", key); span.addAttribute("s3.operation", "PutObject"); } catch (Exception e) { span.recordException(e); throw e; } finally { Lumigo.endSpan(span); } } private boolean processPayment(Map<String, Object> order, String orderId, Span parentSpan) { Span span = Lumigo.startSpan("ProcessPayment", parentSpan); try { // Simulate payment processing double amount = Double.parseDouble(order.get("totalAmount").toString()); span.addAttribute("payment.amount", amount); span.addAttribute("payment.currency", "USD"); // Simulate random failures for demo (10% failure rate) if (Math.random() < 0.1) { span.addAttribute("payment.status", "failed"); span.addAttribute("payment.failureReason", "Insufficient funds"); return false; } // Simulate processing time Thread.sleep(200 + (long)(Math.random() * 300)); span.addAttribute("payment.status", "success"); span.addAttribute("payment.gateway", "mock-gateway"); return true; } catch (InterruptedException e) { Thread.currentThread().interrupt(); span.recordException(e); span.addAttribute("payment.status", "interrupted"); return false; } catch (Exception e) { span.recordException(e); span.addAttribute("payment.status", "error"); return false; } finally { Lumigo.endSpan(span); } } private void sendSuccessNotification(Map<String, Object> order, String orderId, Span parentSpan) { Span span = Lumigo.startSpan("SNS-SendNotification", parentSpan); try { String message = String.format( "Order %s processed successfully for customer %s. Amount: %s", orderId, order.get("customerId"), order.get("totalAmount") ); PublishRequest request = PublishRequest.builder() .topicArn(NOTIFICATION_TOPIC) .message(message) .subject("Order Processing Complete") .build(); snsClient.publish(request); span.addAttribute("sns.topic", NOTIFICATION_TOPIC); span.addAttribute("sns.operation", "Publish"); span.addAttribute("notification.type", "success"); } catch (Exception e) { span.recordException(e); // Don't throw - notification failure shouldn't fail the whole process } finally { Lumigo.endSpan(span); } } private void sendToDeadLetterQueue(Map<String, Object> order, String orderId, Span parentSpan) { Span span = Lumigo.startSpan("SQS-SendToDLQ", parentSpan); try { Map<String, Object> dlqMessage = new HashMap<>(); dlqMessage.put("orderId", orderId); dlqMessage.put("originalOrder", order); dlqMessage.put("failureReason", "payment_failed"); dlqMessage.put("timestamp", System.currentTimeMillis()); SendMessageRequest request = SendMessageRequest.builder() .queueUrl(DEAD_LETTER_QUEUE) .messageBody(convertToJson(dlqMessage)) .build(); sqsClient.sendMessage(request); span.addAttribute("sqs.queue", DEAD_LETTER_QUEUE); span.addAttribute("sqs.operation", "SendMessage"); span.addAttribute("dlq.reason", "payment_failed"); } catch (Exception e) { span.recordException(e); // Log but don't throw - DLQ failure is serious but shouldn't break main flow } finally { Lumigo.endSpan(span); } } private String convertToJson(Map<String, Object> data) { try { // Simple JSON conversion - use Jackson in production StringBuilder json = new StringBuilder("{"); boolean first = true; for (Map.Entry<String, Object> entry : data.entrySet()) { if (!first) json.append(","); json.append("\"").append(entry.getKey()).append("\":"); if (entry.getValue() instanceof String) { json.append("\"").append(entry.getValue()).append("\""); } else { json.append(entry.getValue()); } first = false; } json.append("}"); return json.toString(); } catch (Exception e) { return "{\"error\": \"JSON conversion failed\"}"; } } }

Custom Span Creation for Business Logic

package com.example.lumigo; import io.lumigo.Lumigo; import io.lumigo.models.Span; import java.util.concurrent.TimeUnit; public class BusinessSpanManager { public static <T> T executeWithSpan(String operationName, SpanableOperation<T> operation) { return executeWithSpan(operationName, null, operation); } public static <T> T executeWithSpan(String operationName, Span parentSpan, SpanableOperation<T> operation) { Span span = Lumigo.startSpan(operationName, parentSpan); try { T result = operation.execute(); span.addAttribute("operation.status", "success"); return result; } catch (Exception e) { span.recordException(e); span.addAttribute("operation.status", "failed"); throw e; } finally { Lumigo.endSpan(span); } } public static Span startBusinessSpan(String domain, String operation) { Span span = Lumigo.startSpan(domain + "." + operation); span.addAttribute("business.domain", domain); span.addAttribute("business.operation", operation); span.addAttribute("business.timestamp", System.currentTimeMillis()); return span; } public static void addBusinessContext(Span span, String key, Object value) { if (span != null && value != null) { span.addAttribute("business.context." + key, value.toString()); } } public static void recordBusinessMetric(Span span, String metricName, double value) { if (span != null) { span.addAttribute("business.metric." + metricName, value); } } @FunctionalInterface public interface SpanableOperation<T> { T execute(); } } // Usage example class OrderService { public Order processOrder(Order order) { return BusinessSpanManager.executeWithSpan("OrderService.processOrder", () -> { BusinessSpanManager.addBusinessContext( Lumigo.getCurrentSpan(), "orderId", order.getId() ); // Business logic here validateOrder(order); calculateTax(order); applyDiscounts(order); BusinessSpanManager.recordBusinessMetric( Lumigo.getCurrentSpan(), "orderAmount", order.getTotalAmount() ); return order; }); } private void validateOrder(Order order) { BusinessSpanManager.executeWithSpan("OrderService.validateOrder", () -> { // Validation logic return null; }); } private void calculateTax(Order order) { // Tax calculation with span } private void applyDiscounts(Order order) { // Discount application with span } }

Async Lambda Function with Lumigo

package com.example.lumigo; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.LambdaLogger; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; import io.lumigo.Lumigo; import io.lumigo.models.Span; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.Map; import java.util.HashMap; public class AsyncLumigoFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { private final ExecutorService executorService; static { LumigoConfigurator.initializeLumigo(); } public AsyncLumigoFunction() { this.executorService = Executors.newFixedThreadPool(10); } @Override public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { LambdaLogger logger = context.getLogger(); Span rootSpan = Lumigo.startSpan("AsyncLumigoFunction"); try { logger.log("Processing async request: " + input.getBody()); // Extract trace context for async operations Map<String, String> traceContext = extractTraceContext(input); rootSpan.addAttribute("http.method", input.getHttpMethod()); rootSpan.addAttribute("http.path", input.getPath()); // Process asynchronously CompletableFuture<String> asyncResult = processAsync(input.getBody(), traceContext); // Wait for completion (with timeout) String result = asyncResult.get(30, java.util.concurrent.TimeUnit.SECONDS); APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent(); response.setStatusCode(200); response.setBody(result); rootSpan.addAttribute("async.completed", true); return response; } catch (Exception e) { rootSpan.recordException(e); rootSpan.addAttribute("async.completed", false); APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent(); response.setStatusCode(500); response.setBody("{\"error\": \"" + e.getMessage() + "\"}"); return response; } finally { Lumigo.endSpan(rootSpan); } } private CompletableFuture<String> processAsync(String input, Map<String, String> traceContext) { return CompletableFuture.supplyAsync(() -> { // Create a new span for the async operation Span asyncSpan = Lumigo.startSpan("AsyncProcessing"); try { // Add trace context to maintain distributed tracing if (traceContext != null) { traceContext.forEach(asyncSpan::addAttribute); } // Simulate async processing Thread.sleep(1000); // Business logic String result = "Processed: " + input.toUpperCase(); asyncSpan.addAttribute("processing.result", "success"); asyncSpan.addAttribute("processing.inputLength", input.length()); return result; } catch (InterruptedException e) { Thread.currentThread().interrupt(); asyncSpan.recordException(e); asyncSpan.addAttribute("processing.result", "interrupted"); throw new RuntimeException("Processing interrupted", e); } catch (Exception e) { asyncSpan.recordException(e); asyncSpan.addAttribute("processing.result", "failed"); throw e; } finally { Lumigo.endSpan(asyncSpan); } }, executorService); } private Map<String, String> extractTraceContext(APIGatewayProxyRequestEvent input) { Map<String, String> traceContext = new HashMap<>(); // Extract headers that might contain trace information if (input.getHeaders() != null) { String traceId = input.getHeaders().get("X-Amzn-Trace-Id"); if (traceId != null) { traceContext.put("xray.traceId", traceId); } // Extract other relevant headers input.getHeaders().forEach((key, value) -> { if (key.toLowerCase().startsWith("x-")) { traceContext.put("header." + key, value); } }); } return traceContext; } @Override protected void finalize() throws Throwable { executorService.shutdown(); super.finalize(); } }

Error Handling and Custom Exceptions

package com.example.lumigo; import io.lumigo.Lumigo; import io.lumigo.models.Span; public class LumigoErrorHandler { public static void recordBusinessException(String errorCode, String message, Map<String, Object> context) { Span currentSpan = Lumigo.getCurrentSpan(); if (currentSpan != null) { currentSpan.addAttribute("error.code", errorCode); currentSpan.addAttribute("error.message", message); currentSpan.addAttribute("error.type", "business"); if (context != null) { context.forEach((key, value) -> currentSpan.addAttribute("error.context." + key, value.toString()) ); } } } public static void recordTechnicalException(Exception e, String component, Map<String, Object> technicalContext) { Span currentSpan = Lumigo.getCurrentSpan(); if (currentSpan != null) { currentSpan.recordException(e); currentSpan.addAttribute("error.component", component); currentSpan.addAttribute("error.type", "technical"); if (technicalContext != null) { technicalContext.forEach((key, value) -> currentSpan.addAttribute("technical.context." + key, value != null ? value.toString() : "null") ); } } } public static class BusinessException extends RuntimeException { private final String errorCode; private final Map<String, Object> context; public BusinessException(String errorCode, String message) { this(errorCode, message, null); } public BusinessException(String errorCode, String message, Map<String, Object> context) { super(message); this.errorCode = errorCode; this.context = context; // Automatically record in Lumigo recordBusinessException(errorCode, message, context); } public String getErrorCode() { return errorCode; } public Map<String, Object> getContext() { return context; } } } // Usage example class PaymentService { public void processPayment(PaymentRequest request) { try { if (request.getAmount() <= 0) { throw new LumigoErrorHandler.BusinessException( "INVALID_AMOUNT", "Payment amount must be positive", Map.of("amount", request.getAmount(), "currency", request.getCurrency()) ); } // Payment processing logic if (!isPaymentMethodValid(request.getPaymentMethod())) { throw new LumigoErrorHandler.BusinessException( "INVALID_PAYMENT_METHOD", "Unsupported payment method", Map.of("paymentMethod", request.getPaymentMethod()) ); } } catch (TechnicalException e) { LumigoErrorHandler.recordTechnicalException(e, "PaymentGateway", Map.of("gateway", "stripe", "requestId", request.getId())); throw e; } } private boolean isPaymentMethodValid(String paymentMethod) { // Validation logic return true; } }

SAM Template for Deployment

AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Parameters: LumigoTracerToken: Type: String Description: "Lumigo tracer token" NoEcho: true Globals: Function: Timeout: 30 MemorySize: 512 Runtime: java11 Environment: Variables: LUMIGO_TRACER_TOKEN: !Ref LumigoTracerToken LUMIGO_DEBUG: "false" Resources: BasicLumigoFunction: Type: AWS::Serverless::Function Properties: CodeUri: target/lumigo-demo-1.0.0.jar Handler: com.example.lumigo.BasicLumigoFunction::handleRequest Policies: - AWSLambdaBasicExecutionRole Tracing: Active OrderProcessingFunction: Type: AWS::Serverless::Function Properties: CodeUri: target/lumigo-demo-1.0.0.jar Handler: com.example.lumigo.OrderProcessingFunction::handleRequest Environment: Variables: ORDERS_TABLE: !Ref OrdersTable PROCESSING_BUCKET: !Ref ProcessingBucket NOTIFICATION_TOPIC: !Ref NotificationTopic DEAD_LETTER_QUEUE: !Ref DeadLetterQueue Policies: - AWSLambdaBasicExecutionRole - DynamoDBCrudPolicy: TableName: !Ref OrdersTable - S3CrudPolicy: BucketName: !Ref ProcessingBucket - SNSPublishMessagePolicy: TopicName: !Ref NotificationTopic - SQSSendMessagePolicy: QueueName: !Ref DeadLetterQueue Tracing: Active Events: ApiEvent: Type: Api Properties: Path: /orders Method: post OrdersTable: Type: AWS::DynamoDB::Table Properties: TableName: orders AttributeDefinitions: - AttributeName: orderId AttributeType: S KeySchema: - AttributeName: orderId KeyType: HASH BillingMode: PAY_PER_REQUEST ProcessingBucket: Type: AWS::S3::Bucket Properties: BucketName: !Sub "${AWS::StackName}-processing-${AWS::AccountId}" NotificationTopic: Type: AWS::SNS::Topic Properties: TopicName: !Sub "${AWS::StackName}-notifications" DeadLetterQueue: Type: AWS::SQS::Queue Properties: QueueName: !Sub "${AWS::StackName}-dlq" Outputs: BasicLumigoFunctionArn: Description: "Basic Lumigo Function ARN" Value: !GetAtt BasicLumigoFunction.Arn OrderProcessingFunctionArn: Description: "Order Processing Function ARN" Value: !GetAtt OrderProcessingFunction.Arn ApiEndpoint: Description: "API Gateway Endpoint" Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/orders/"

Build Configuration (Maven)

<!-- pom.xml --> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <source>11</source> <target>11</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.4.1</version> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.1.0</version> <configuration> <mainClass>com.example.lumigo.TestRunner</mainClass> </configuration> </plugin> </plugins> </build>

Testing with Lumigo

package com.example.lumigo; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.LambdaLogger; import io.lumigo.Lumigo; import io.lumigo.models.Span; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.HashMap; import java.util.Map; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.*; class OrderProcessingFunctionTest { @Mock private Context mockContext; @Mock private LambdaLogger mockLogger; private OrderProcessingFunction function; @BeforeEach void setUp() { MockitoAnnotations.openMocks(this); when(mockContext.getLogger()).thenReturn(mockLogger); when(mockContext.getFunctionName()).thenReturn("TestFunction"); when(mockContext.getAwsRequestId()).thenReturn("test-request-id"); // Initialize Lumigo with test token Lumigo.init("test-token"); function = new OrderProcessingFunction(); } @Test void testValidOrderProcessing() { // Given Map<String, Object> input = new HashMap<>(); input.put("customerId", "cust-123"); input.put("items", "[{\"id\": \"item1\", \"quantity\": 2}]"); input.put("totalAmount", "100.50"); // When Map<String, Object> result = function.handleRequest(input, mockContext); // Then assertNotNull(result); assertEquals("SUCCESS", result.get("status")); assertNotNull(result.get("orderId")); verify(mockLogger, atLeastOnce()).log(anyString()); } @Test void testInvalidOrder() { // Given Map<String, Object> input = new HashMap<>(); input.put("customerId", "cust-123"); // Missing required fields // When & Then assertThrows(IllegalArgumentException.class, () -> { function.handleRequest(input, mockContext); }); } @Test void testBusinessSpanManager() { // Given String expectedResult = "test-result"; // When String result = BusinessSpanManager.executeWithSpan("TestOperation", () -> { Span currentSpan = Lumigo.getCurrentSpan(); assertNotNull(currentSpan); currentSpan.addAttribute("test.attribute", "value"); return expectedResult; }); // Then assertEquals(expectedResult, result); } } // Local testing runner class TestRunner { public static void main(String[] args) { // Initialize Lumigo for local testing Lumigo.init("local-test-token"); // Create test context Context context = new Context() { public String getAwsRequestId() { return "local-test-id"; } public String getLogGroupName() { return "/aws/lambda/local-test"; } public String getLogStreamName() { return "2023/01/01/[$LATEST]test"; } public String getFunctionName() { return "LocalTestFunction"; } public String getFunctionVersion() { return "$LATEST"; } public String getInvokedFunctionArn() { return "arn:aws:lambda:us-east-1:123456789012:function:LocalTestFunction"; } public com.amazonaws.services.lambda.runtime.CognitoIdentity getIdentity() { return null; } public com.amazonaws.services.lambda.runtime.ClientContext getClientContext() { return null; } public int getRemainingTimeInMillis() { return 30000; } public int getMemoryLimitInMB() { return 512; } public LambdaLogger getLogger() { return System.out::println; } }; // Test the function OrderProcessingFunction function = new OrderProcessingFunction(); Map<String, Object> input = Map.of( "customerId", "test-customer", "items", "[{\"id\": \"test-item\", \"quantity\": 1}]", "totalAmount", "50.00" ); try { Map<String, Object> result = function.handleRequest(input, context); System.out.println("Test completed successfully: " + result); } catch (Exception e) { System.err.println("Test failed: " + e.getMessage()); e.printStackTrace(); } } }

Best Practices

1. Environment Configuration

public class LumigoEnvironment { public static final String LUMIGO_TOKEN = System.getenv("LUMIGO_TRACER_TOKEN"); public static final boolean LUMIGO_DEBUG = Boolean.parseBoolean(System.getenv("LUMIGO_DEBUG")); public static final String LUMIGO_EDGE = System.getenv().getOrDefault("LUMIGO_EDGE", "default-edge.lumigo.io"); public static void validateConfiguration() { if (LUMIGO_TOKEN == null || LUMIGO_TOKEN.trim().isEmpty()) { throw new IllegalStateException("LUMIGO_TRACER_TOKEN environment variable is required"); } } }

2. Span Naming Conventions

public class SpanNamingConventions { // Format: Domain.Operation public static final String ORDER_PROCESSING = "Order.Process"; public static final String PAYMENT_PROCESSING = "Payment.Process"; public static final String NOTIFICATION_SENDING = "Notification.Send"; // AWS Service operations public static String dynamoDbOperation(String operation, String table) { return "DynamoDB." + operation + "." + table; } public static String s3Operation(String operation, String bucket) { return "S3." + operation + "." + bucket; } }

3. Cold Start Optimization

public class ColdStartOptimizer { private static boolean initialized = false; static { initializeLumigo(); warmUpDependencies(); } private static void initializeLumigo() { if (!initialized) { LumigoConfigurator.initializeLumigo(); initialized = true; } } private static void warmUpDependencies() { // Pre-initialize AWS clients and other dependencies try { Class.forName("software.amazon.awssdk.services.dynamodb.DynamoDbClient"); Class.forName("software.amazon.awssdk.services.s3.S3Client"); } catch (ClassNotFoundException e) { // Ignore in production } } }

Conclusion

This comprehensive Lumigo implementation for Java serverless applications provides:

  • Automatic instrumentation for AWS Lambda functions
  • Distributed tracing across multiple AWS services
  • Custom span creation for business logic monitoring
  • Error handling with detailed context
  • Async operation support with proper context propagation
  • Testing utilities for local development
  • Best practices for production deployment

Key benefits include reduced debugging time, performance optimization insights, and comprehensive observability across your serverless architecture. The implementation follows AWS and Lumigo best practices while providing flexibility for custom instrumentation needs.

Remember to:

  • Keep your Lumigo token secure using environment variables
  • Follow span naming conventions for consistency
  • Instrument both synchronous and asynchronous operations
  • Add meaningful context to spans for better debugging
  • Test locally before deploying to production

Complete C Programming Guide + Compilers Collection


1. C srand() Function – Understanding Seed Initialization

https://macronepal.com/understanding-the-c-srand-function
Explains how srand() initializes the pseudo-random number generator in C by setting a seed value. Using the same seed produces the same sequence, while time(NULL) gives different results each run.


2. C rand() Function Mechanics and Limitations

https://macronepal.com/c-rand-function-mechanics-and-limitations
Explains how rand() generates pseudo-random numbers between 0 and RAND_MAX, its deterministic nature, and limitations for security use cases.


3. C log() Function

https://macronepal.com/c-log-function-2
Covers natural logarithm calculation using <math.h> and its applications.


4. Mastering Date and Time in C

https://macronepal.com/mastering-date-and-time-in-c
Explains <time.h> functions like time(), clock(), difftime(), and struct tm.


5. Mastering time_t Type in C

https://macronepal.com/mastering-the-c-time_t-type-for-time-management
Explains time representation as seconds since Unix epoch and conversion functions.


6. C exp() Function

https://macronepal.com/c-exp-function-mechanics-and-implementation
Explains exponential function exp(x) and its scientific applications.


7. C log() Function (Alternate Guide)

https://macronepal.com/c-log-function
Comparison of log() and log10() with usage examples.


8. C log10() Function

https://macronepal.com/mastering-the-log10-function-in-c
Explains base-10 logarithm for engineering and scientific applications.


9. C tan() Function

https://macronepal.com/understanding-the-c-tan-function
Explains tangent function and radian-based calculations.


10. Random Numbers in C (Secure vs Predictable)

https://macronepal.com/mastering-c-random-numbers-for-secure-and-predictable-applications
Explains difference between rand() and secure randomness methods.


11. Free Online C Compiler

https://macronepal.com/free-online-c-code-compiler-2
Browser-based compiler for testing C programs instantly.


C Functions, Arguments, Parameters & Flow

Mastering Functions in C – Complete Guide

https://macronepal.com/c/mastering-functions-in-c-a-complete-guide/
Covers function structure, modular programming, and real-world usage.


Function Arguments in C

https://macronepal.com/c-function-arguments/
Explains how arguments are passed and used in function calls.


Function Parameters in C

https://macronepal.com/c-function-parameters/
Explains defining inputs for functions and matching them with arguments.


Function Declarations in C

https://macronepal.com/c-function-declarations-syntax-rules-and-best-practices/
Covers prototypes, syntax rules, and best practices.


Function Calls in C

https://macronepal.com/understanding-function-calls-in-c-syntax-mechanics-and-best-practices/
Explains execution flow and parameter handling during function calls.


Void Functions in C

https://macronepal.com/understanding-void-functions-in-c-syntax-patterns-and-best-practices/
Explains functions that do not return values.


Return Values in C

https://macronepal.com/c-return-values-mechanics-types-and-best-practices/
Explains different return types and how functions return results.


Pass-by-Value in C

https://macronepal.com/aws/understanding-pass-by-value-in-c-mechanics-implications-and-best-practices/
Explains how copies of variables are passed into functions.


Pass-by-Reference in C

https://macronepal.com/c/understanding-pass-by-reference-in-c-pointers-semantics-and-safe-practices/
Explains using pointers to modify original variables.


C strstr() Function

https://macronepal.com/aws/c-strstr-function/
Explains substring search inside strings in C.


C Preprocessor & Macros

https://macronepal.com/mastering-c-variadic-macros-for-flexible-debugging/
https://macronepal.com/mastering-the-stdc-macro-in-c/
https://macronepal.com/c-time-macro-mechanics-and-usage/
https://macronepal.com/understanding-the-c-date-macro/
https://macronepal.com/c-file-type/
https://macronepal.com/mastering-c-line-macro-for-debugging-and-diagnostics/
https://macronepal.com/mastering-predefined-macros-in-c/
https://macronepal.com/c-error-directive-mechanics-and-usage/
https://macronepal.com/understanding-the-c-pragma-directive/
https://macronepal.com/c-include-directive/


C Structures, Memory, Scope & Linkage

https://macronepal.com/mastering-structures-in-c/
https://macronepal.com/c-structure-declaration-mechanics-and-usage/
https://macronepal.com/c-structure-initialization-mechanics-and-best-practices/
https://macronepal.com/mastering-c-structure-member-access-for-reliable-data-handling/
https://macronepal.com/c-nested-structures/
https://macronepal.com/mastering-arrays-of-structures-in-c/
https://macronepal.com/c-structure-pointers-mechanics-and-implementation/
https://macronepal.com/understanding-c-structure-parameter-passing-mechanics/
https://macronepal.com/mastering-c-returning-structures-for-efficient-data-flow/
https://macronepal.com/c-self-referential-structures/
https://macronepal.com/mastering-structure-alignment-in-c/
https://macronepal.com/c-structure-padding-mechanics-and-optimization/
https://macronepal.com/understanding-c-flexible-array-members-mechanics-and-usage/
https://macronepal.com/mastering-c-anonymous-structures-for-flattened-data-layouts/
https://macronepal.com/c-unions/
https://macronepal.com/mastering-c-name-mangling-and-symbol-decoration/
https://macronepal.com/c-no-linkage-mechanics-and-scope-isolation/
https://macronepal.com/understanding-c-internal-linkage-mechanics-and-architecture/


C Scope, Storage Classes & Typedef

https://macronepal.com/mastering-function-prototype-scope-in-c/
https://macronepal.com/c-function-scope-mechanics-and-visibility/
https://macronepal.com/understanding-c-file-scope-mechanics-and-architecture/
https://macronepal.com/mastering-c-scope-rules-for-predictable-name-resolution/
https://macronepal.com/c-scope-rules/
https://macronepal.com/mastering-c-register-storage-class-for-historical-context-and-modern-alternatives/
https://macronepal.com/mastering-_thread_local-in-c/
https://macronepal.com/c-extern-storage-class-mechanics-and-usage/
https://macronepal.com/understanding-the-c-static-storage-class-mechanics-and-usage/
https://macronepal.com/c-auto-storage-class/
https://macronepal.com/c-typedef-with-pointers/


Extra Articles

https://macronepal.com/13757-2/
https://macronepal.com/13748-2/
https://macronepal.com/13747-2/
https://macronepal.com/13746-2/
https://macronepal.com/13745-2/
https://macronepal.com/13708-2/
https://macronepal.com/13707-2/
https://macronepal.com/13702-2/


Online Compilers

https://macronepal.com/free-html-online-code-compiler/
https://macronepal.com/free-online-python-code-compiler/
https://macronepal.com/free-online-python2-code-compiler/
https://macronepal.com/free-online-java-code-compiler/
https://macronepal.com/free-online-javascript-code-compiler/
https://macronepal.com/free-online-node-js-code-compiler/
https://macronepal.com/free-online-c-code-compiler/
https://macronepal.com/free-online-c-code-compiler-2/
https://macronepal.com/free-online-c-code-compiler-3/
https://macronepal.com/free-online-php-code-compiler/
https://macronepal.com/free-online-ruby-code-compiler/
https://macronepal.com/free-online-perl-code-compiler/
https://macronepal.com/free-online-lua-code-compiler/
https://macronepal.com/free-online-tcl-code-compiler/
https://macronepal.com/free-online-groovy-code-compiler/
https://macronepal.com/free-online-j-shell-code-compiler/
https://macronepal.com/free-online-haskell-code-compiler/
https://macronepal.com/free-online-scala-code-compiler/
https://macronepal.com/free-online-common-lisp-code-compiler/
https://macronepal.com/free-online-d-code-compiler/
https://macronepal.com/free-online-ada-code-compiler/
https://macronepal.com/free-erlang-code-compiler/
https://macronepal.com/free-online-assembly-code-compiler/

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper