1

Dependency:

<dependency>
    io.keen</groupId>
    keen-client-api-java</artifactId>
    5.2.0</
</dependency>

Bean creation:

@Bean
public KeenClient keenClient() {
    KeenClient keenClient = new JavaKeenClientBuilder().build();
    keenClient.setDefaultProject(new KeenProject(projectId, writeKey, readKey));
    keenClient.setDebugMode(debugMode);

    if (enableLogging) {
        KeenLogging.enableLogging();
    }

    return keenClient;
}

Service definition:

@Service
public class KeenAnalyticsService implements AnalyticsService {
    private static final Logger LOG = LoggerFactory.getLogger(KeenAnalyticsService.class);

    private final KeenClient keenClient;

    public static final String ID = "id";
    public static final String USER_LOGIN_EVENT = "user_login_event";

    @Autowired
    public KeenAnalyticsService(KeenClient keenClient) {
        this.keenClient = keenClient;
    }

    @Override
    public void submitUserLoginEvent(UserLoginAnalyticsEvent userLoginAnalyticsEvent) {
        Map<String, Object> event = Maps.newHashMap();
        event.put(USER_LOGIN_EVENT, userLoginAnalyticsEvent);
        addEvent(USER_LOGIN_EVENT, event);
    }

    private void addEvent(String collection, Map<String, Object> event) {
        addEvent(collection, event, Maps.newHashMap());
    }

    private void addEvent(String collection, Map<String, Object> event, Map<String, Object> keenProperties) {
        if (!event.containsKey(ID)) {
            String id = UUID.randomUUID().toString();
            LOG.info("Adding {} Keen event with ID ({})", collection, id);
            event.put(ID, id);
        } else {
            LOG.info("Adding {} Keen event with existing ID ({})", collection, event.get(ID));
        }

            try {
            keenClient.addEventAsync(keenClient.getDefaultProject(), collection, event, keenProperties, new LoggingKeenCallback());
        } catch (Throwable e) {
            LOG.warn("Unable to add event", e);
        }
    }

    private static class LoggingKeenCallback implements KeenDetailedCallback {
        @Override
        public void onSuccess() {}

        @Override
        public void onFailure(Exception e) {}

        @Override
        public void onSuccess(KeenProject project, String eventCollection, Map<String, Object> event, Map<String, Object>     keenProperties) {
            LOG.info("Successfully processed event asynchronously with ID({}) to Collection({})", event.get(ID),     eventCollection);
        }

        @Override
        public void onFailure(KeenProject project, String eventCollection, Map<String, Object> event, Map<String, Object>     keenProperties, Exception e) {
            LOG.warn("Unable to process event asynchronously with ID({}) to Collection({})", event.get(ID), eventCollection,     e);
        }
    }

}

I'm getting the following stacktrace:

Exception in thread "pool-1-thread-1" java.lang.RuntimeException: java.net.SocketException: Operation not permitted (select/    poll failed)
    at io.keen.client.java.KeenClient.handleFailure(KeenClient.java:1643)
    at io.keen.client.java.KeenClient.addEvent(KeenClient.java:171)
    at io.keen.client.java.KeenClient$1.run(KeenClient.java:243)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.SocketException: Operation not permitted (select/poll failed)
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.SocketInputStream.read(SocketInputStream.java:171)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
    at sun.security.ssl.InputRecord.read(InputRecord.java:503)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:983)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(HttpURLConnection.java:1316)
    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1291)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250)
    at io.keen.client.java.http.UrlConnectionHttpHandler.sendRequest(UrlConnectionHttpHandler.java:86)
    at io.keen.client.java.http.UrlConnectionHttpHandler.execute(UrlConnectionHttpHandler.java:30)
    at io.keen.client.java.KeenClient.publishObject(KeenClient.java:1436)
    at io.keen.client.java.KeenClient.publish(KeenClient.java:1370)
    at io.keen.client.java.KeenClient.addEvent(KeenClient.java:168)
    ... 4 more

Are there any ideas as to what might be causing the issue? The issue goes away when I add the event in sync rather than async but I'd prefer to add the event async if possible.

I'm 99% sure this is the Lambda cutting off execution to the event mid-send but I wanted to be sure. I don't recognize the stacktrace myself personally so there's only so much I can speculate from it.

Obviously I don't want to delay user login attempts any more than I have to but if I fire off the keen event asynchronously as the last thing I do before returning the login result to the user then there's bound to be some kind of timing issue related to the container closing and the keen event being sent.

Then again, Lambda might be smart enough to wait for child spawned threads to finish. Then again, it might not. It might quit when the main thread finishes executing by design.

Curious if anyone in the Keen team or the Lambda team can shed more light on this.

fIwJlxSzApHEZIl
  • 11,861
  • 6
  • 62
  • 71

0 Answers0