brefphp / extra-php-extensions

Community-maintained extra PHP extensions usable in AWS Lambda with the Bref PHP runtimes.
https://bref.sh/docs/environment/php.html#extra-extensions
213 stars 109 forks source link

NewRelic: include newrelic-daemon executable as Lambda Extension #213

Closed starred-gijs closed 2 years ago

starred-gijs commented 3 years ago

I have been playing around with this idea, and I created a Lambda Layer and using the Lambda Extension API and the newrelic-daemon executable. Its a very basic implementation, and there is indeed the occasional connection issue with cold starts, as the docs mention already

2021-04-08 11:22:17.607 +0000 (14 14) warning: daemon connect(fd=5 host=127.0.0.1, port=31339) returned -1 errno=ECONNREFUSED. Failed to connect to the newrelic-daemon. Please make sure that there is a properly configured newrelic-daemon running. For additional assistance, please see: https://newrelic.com/docs/php/newrelic-daemon-startup-modes

But for us this has been working really well, so I was wondering if the community could benefit from including the newrelic-daemon in this newrelic layer (and optionally use it)

We would need 2 additional files in the layer extensions/bin/newrelic-daemon extensions/newrelic.sh

where newrelic.sh is a bash script registering the Lambda Extension API and starting the daemon, based on this example

#!/bin/bash
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0

set -euo pipefail

OWN_FILENAME="$(basename $0)"
LAMBDA_EXTENSION_NAME="$OWN_FILENAME" # (external) extension name has to match the filename
TMPFILE=/tmp/$OWN_FILENAME

# Graceful Shutdown
_term() {
  echo "[${LAMBDA_EXTENSION_NAME}] Received SIGTERM"
  # forward SIGTERM to child procs and exit
  kill -TERM "$PID" 2>/dev/null
  echo "[${LAMBDA_EXTENSION_NAME}] Exiting"
  exit 0
}

forward_sigterm_and_wait() {
  trap _term SIGTERM
  wait "$PID"
  trap - SIGTERM
}

# Registration
HEADERS="$(mktemp)"
echo "[${LAMBDA_EXTENSION_NAME}] Registering at http://${AWS_LAMBDA_RUNTIME_API}/2020-01-01/extension/register"
curl -sS -LD "$HEADERS" -XPOST "http://${AWS_LAMBDA_RUNTIME_API}/2020-01-01/extension/register" --header "Lambda-Extension-Name: ${LAMBDA_EXTENSION_NAME}" -d "{ \"events\": [\"INVOKE\", \"SHUTDOWN\"]}" > $TMPFILE

RESPONSE=$(<$TMPFILE)
HEADINFO=$(<$HEADERS)
# Extract Extension ID from response headers
EXTENSION_ID=$(grep -Fi Lambda-Extension-Identifier "$HEADERS" | tr -d '[:space:]' | cut -d: -f2)

# Start NewRelic Daemon and accept all connections
/opt/extensions/bin/newrelic-daemon --address=0.0.0.0:31339 --logfile=/proc/self/fd/2

# Event processing
while true
do
  # Get an event. The HTTP request will block until one is received
  curl -sS -L -XGET "http://${AWS_LAMBDA_RUNTIME_API}/2020-01-01/extension/event/next" --header "Lambda-Extension-Identifier: ${EXTENSION_ID}" > $TMPFILE &
  PID=$!
  forward_sigterm_and_wait

  EVENT_DATA=$(<$TMPFILE)
  if [[ $EVENT_DATA == *"SHUTDOWN"* ]]; then
    echo "[extension: ${LAMBDA_EXTENSION_NAME}] Received SHUTDOWN event. Exiting."  1>&2;
    exit 0 # Exit if we receive a SHUTDOWN event
  fi

done

But than modified to only register if some environment var is set. Im also not a bash expert, I copied the example from amazon as starting point

Im curious to find out what you think about this, please share your thoughts!

starred-gijs commented 2 years ago

Closing due the occasional connection issue with cold starts is not worth the trouble.