Prasad Pande
Prasad Pande

Reputation: 508

AWS Lambda that parse CloudWatch log Stream

I am writing a AWS Lambda that will process log stream from CloudWatch. I am implementing it in Java. I am struggling with couple of issues:

  1. How to decode and decompressed the logs that are received. In Python following code works:
import json
import base64
import zlib

def stream_gzip_decompress(stream):
    dec = zlib.decompressobj(32 + zlib.MAX_WBITS)  # offset 32 to skip the header
    foo=''
    for chunk in stream:
        rv = dec.decompress(chunk)
        if rv:
            foo += rv
    return foo

def lambda_handler(event, context):
    # Decode and decompress the AWS Log stream to extract json object
    stream=json.dumps(event['awslogs']['data'])
    payload=json.loads(stream_gzip_decompress(stream.decode('base64')))
    print(payload)

How to implement similar functionality in Java?

  1. Also when I try to add external jar org.json for parsing input JSON data. I am getting following error although I tried most of the things that are given on stackoverflow

Error:

{ "errorMessage": "Error loading class UpdateCurrentNotificationStatus: org/json/JSONException",
"errorType": "class java.lang.NoClassDefFoundError" }

Following is the sample code that I am writing:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.json.JSONException;
import org.json.JSONObject;

import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
import com.amazonaws.services.lambda.runtime.Context; 

public class UpdateCurrentNotificationStatus implements RequestStreamHandler {
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context)
            throws IOException {
        int letter;
        while((letter = inputStream.read()) != -1)
        {
            //outputStream.write(Character.toUpperCase(letter));
            JSONObject json = new JSONObject(letter);
            try {
              String stream = json.getString("awslogs");
              System.out.println(stream);
          } catch (JSONException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
        }
    }
}

Can somebody help me with this?

Thank You,

Prasad

Upvotes: 5

Views: 3464

Answers (1)

Max
Max

Reputation: 1292

What you need to do is to accept CloudWatchLogsEvent as input param.

    public class Testing implements RequestHandler<CloudWatchLogsEvent, String> {


        public String handleRequest(CloudWatchLogsEvent request, Context context){
            context.getLogger().log(request.toString());
            String timeStamp = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").format(Calendar.getInstance().getTime());
            context.getLogger().log("Invocation started: " + timeStamp);

            context.getLogger().log(request.toString());

            timeStamp = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").format(Calendar.getInstance().getTime());
            context.getLogger().log("Invocation completed: " + timeStamp);
            return "completed";
        }
}

Remember this will print the encoded base 64 string which is gzipped as well. Which you'll have to decode and unzip. There are example available on web on how to do that so I'll not dig into that. One eg is here Decode Base64 encoded ZIP archive (GZIP).

Upvotes: 4

Related Questions