Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NH-69805: lambda layer init commit #97

Merged
merged 11 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions .github/workflows/build_publish_lambda_layer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Copyright (c) 2023 SolarWinds, LLC.
# All rights reserved.

name: Build and publish ruby lambda layer

on:
workflow_dispatch:

jobs:
# create one arm64 ec2 instance on aws as our runner
start_arm64_runner:
outputs:
matrix: ${{ steps.launch.outputs.matrix }} # this will be a json object mapping identifiers to labels and instance ids
runs-on: ubuntu-latest
steps:
- uses: getsentry/action-github-app-token@v2
id: github-token
with:
app_id: ${{ vars.APPLICATION_ID }}
private_key: ${{ secrets.APPLICATION_PRIVATE_KEY }}

- uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.CI_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.CI_SECRET_ACCESS_KEY }}
aws-region: us-east-1

- id: launch
uses: solarwindscloud/ec2-runner-action@main
with:
action: launch
matrix: | # one identifier per line
ubuntu:22.04
github-token: ${{ steps.github-token.outputs.token }}
runner-user: github
runner-directory: /gh
instance-type: t4g.medium
ami-name: gha-arm64-ubuntu22-.*
ami-owner: "858939916050"
subnet-id: subnet-0fd499f8a50e41807
security-group-ids: sg-0fd8d8cd6effda4a5
tags: |
Name=xuan-cao-ec2-runner

# build layer on arm64 and amd64, then upload to artifacts
build_layer:
needs:
- start_arm64_runner
runs-on: ${{ matrix.arch == 'arm64' && fromJSON(needs.start_arm64_runner.outputs.matrix)[matrix.image].label || 'ubuntu-latest' }}
strategy:
fail-fast: false
matrix:
arch:
- x86_64
- arm64
steps:
- uses: actions/checkout@v3
- uses: aws-actions/setup-sam@v2

# Build inside Docker containers
# There is only two ruby runtime for aws lambda ruby 3.2 and 2.7
# Since the 2.7 is not supported by otel, then we don't use it
- name: build lambda layer
run: |
cd lambda/
sam build -u -t template.yml -e BUNDLE_RUBYGEMS__PKG__GITHUB__COM=$GITHUB_RUBY_TOKEN
./zip_layer.sh -n ruby-layer-${{ matrix.arch }}
env:
GITHUB_RUBY_TOKEN: ${{ secrets.GITHUB_RUBY_TOKEN }}

- name: Upload to artifact
uses: actions/upload-artifact@v3
name: Save assembled layer to build
with:
name: ruby-layer-${{ matrix.arch }}.zip
path: lambda

# extract the built layer from artifacts, then publish it based on region
publish_layer:
needs:
- build_layer
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
aws_region:
- ap-northeast-1
- ap-northeast-2
- ap-south-1
- ap-southeast-1
- ap-southeast-2
- ca-central-1
- eu-central-1
- eu-north-1
- eu-west-1
- eu-west-2
- eu-west-3
- sa-east-1
- us-east-1
- us-east-2
- us-west-1
- us-west-2
arch:
- x86_64
- arm64
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_LAMBDA_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_LAMBDA_ACCESS_KEY_KEY }}
aws-region: ${{ matrix.aws_region }}

- name: extract layer zip from artifacts
uses: actions/download-artifact@v3
with:
name: ruby-layer-${{ matrix.arch }}.zip
path: lambda

- name: publish lambda layer
run: |
cd lambda/
aws lambda publish-layer-version \
--layer-name solarwinds-ruby-layer \
--license-info "Apache 2.0" \
--compatible-architectures ${{ matrix.arch }} \
--compatible-runtimes ruby3.2 \
--zip-file ruby-layer-${{ matrix.arch }}.zip \
--query 'LayerVersionArn' \
--output text

terminate_arm64_runner:
if: ${{ always() }}
needs:
- start_arm64_runner
- build_layer
- publish_layer
runs-on: ubuntu-latest
steps:
- uses: getsentry/action-github-app-token@v2
id: github-token
with:
app_id: ${{ vars.APPLICATION_ID }}
private_key: ${{ secrets.APPLICATION_PRIVATE_KEY }}

- uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.CI_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.CI_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- uses: solarwindscloud/ec2-runner-action@main
with:
action: terminate
github-token: ${{ steps.github-token.outputs.token }}
matrix: ${{ needs.start_arm64_runner.outputs.matrix }} # passing a matrix will terminate all runners, not just one
4 changes: 2 additions & 2 deletions .github/workflows/verify_install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
app_id: ${{ vars.APPLICATION_ID }}
private_key: ${{ secrets.APPLICATION_PRIVATE_KEY }}

- uses: aws-actions/configure-aws-credentials@v2
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.CI_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.CI_SECRET_ACCESS_KEY }}
Expand Down Expand Up @@ -133,7 +133,7 @@ jobs:
app_id: ${{ vars.APPLICATION_ID }}
private_key: ${{ secrets.APPLICATION_PRIVATE_KEY }}

- uses: aws-actions/configure-aws-credentials@v2
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.CI_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.CI_SECRET_ACCESS_KEY }}
Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,7 @@ rubocop_result.txt
git_push.sh

# act.secrets
act.secrets
act.secrets

# lambda layer
lambda/.aws-sam/*
2 changes: 1 addition & 1 deletion ext/oboe_metal/extconf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
case system_arch
when 'x86_64'
swo_arch = 'x86_64'
when 'aarch64'
when 'aarch64' || 'arm64'
swo_arch = 'aarch64'
end

Expand Down
31 changes: 31 additions & 0 deletions lambda/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# SolarWinds Lambda Ruby Layer

## Building Lambda Ruby Layer With OpenTelemetry Ruby Dependencies

Build
```bash
sam build -u -t template.yml
```

Make sure the layer structure like below with your zip
```
ruby
└── gems
└── 3.2.0
├── build_info
├── doc
├── extensions
├── gems
├── plugins
└── specifications
```

Zip the file for uploading to ruby lambda layer

```bash
cd .aws-sam/build/OTelLayer/
zip -qr ../../../<your_layer_name>.zip ruby/
cd -
# or run following script
zip_ruby_layer.sh -n <your_layer_name>
```
10 changes: 10 additions & 0 deletions lambda/layer/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
source 'https://rubygems.org'

gem 'solarwinds_apm'

source 'https://rubygems.pkg.github.com/solarwinds' do
gem 'opentelemetry-metrics-api', '0.0.1'
gem 'opentelemetry-metrics-sdk', '0.0.1'
gem 'opentelemetry-exporter-otlp', '0.26.1'
gem 'opentelemetry-instrumentation-aws_lambda', '0.0.1'
end
12 changes: 12 additions & 0 deletions lambda/layer/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

build-OTelLayer:
mkdir -p ruby
mkdir -p $(ARTIFACTS_DIR)/ruby/gems/3.2.0
mkdir -p $(ARTIFACTS_DIR)/ruby/lib/
bundle config set --global silence_root_warning 1
bundle config set --local path 'ruby'
bundle install
cp -r ruby/ruby/3.2.0/* $(ARTIFACTS_DIR)/ruby/gems/3.2.0
cp otel-handler $(ARTIFACTS_DIR)/otel-handler
cheempz marked this conversation as resolved.
Show resolved Hide resolved
cp wrapper.rb $(ARTIFACTS_DIR)/ruby/lib/
rm -rf $(ARTIFACTS_DIR)/ruby/gems/3.2.0/cache
22 changes: 22 additions & 0 deletions lambda/layer/otel-handler
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/sh

export ORIG_HANDLER=$_HANDLER;
export _HANDLER="wrapper.otel_wrapper";

if [ -z "${OTEL_SERVICE_NAME}" ]; then
export OTEL_SERVICE_NAME="$AWS_LAMBDA_FUNCTION_NAME";
fi

# disable HTTP NET by default - otherwise, lambda runtime gets instrumented yielding noise
if [ -z "${OTEL_RUBY_INSTRUMENTATION_NET_HTTP_ENABLED}" ]; then
export OTEL_RUBY_INSTRUMENTATION_NET_HTTP_ENABLED=false;
fi

export LAMBDA_RESOURCE_ATTRIBUTES="cloud.region=$AWS_REGION,cloud.provider=aws,faas.name=$AWS_LAMBDA_FUNCTION_NAME,faas.version=$AWS_LAMBDA_FUNCTION_VERSION";
if [ -z "${OTEL_RESOURCE_ATTRIBUTES}" ]; then
export OTEL_RESOURCE_ATTRIBUTES="$LAMBDA_RESOURCE_ATTRIBUTES";
else
export OTEL_RESOURCE_ATTRIBUTES="$LAMBDA_RESOURCE_ATTRIBUTES,$OTEL_RESOURCE_ATTRIBUTES";
fi

exec "$@"
10 changes: 10 additions & 0 deletions lambda/layer/wrapper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require 'solarwinds_apm'
require 'opentelemetry/instrumentation/aws_lambda'

::OpenTelemetry::Instrumentation.registry.register('OpenTelemetry::Instrumentation::AwsLambda')
::OpenTelemetry::Instrumentation.registry.install(['OpenTelemetry::Instrumentation::AwsLambda'])

def otel_wrapper(event:, context:)
otel_wrapper = OpenTelemetry::Instrumentation::AwsLambda::Handler.new()
Fixed Show fixed Hide fixed
otel_wrapper.call_wrapped(event: event, context: context)
end
19 changes: 19 additions & 0 deletions lambda/template.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: OpenTelemetry Ruby Lambda layer for Ruby
Parameters:
LayerName:
Type: String
Description: Lambda layer name to be published
Default: opentelemetry-ruby
Resources:
OTelLayer:
Type: AWS::Serverless::LayerVersion
Properties:
LayerName: !Ref LayerName
Description: Opentelemetry Ruby layer
ContentUri: ./layer
CompatibleRuntimes:
- ruby3.2
Metadata:
BuildMethod: makefile
40 changes: 40 additions & 0 deletions lambda/zip_layer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/sh

set -e
set -u

echo_usage() {
echo "usage: Build Lambda layer/application by SAM"
echo " -n <specify layer name>"
}


main() {
echo "running..."
layerName="opentelemetry-ruby-layer"

while getopts "n:h" opt; do
case "${opt}" in
h)
echo_usage
exit 0
;;
n)
layerName="${OPTARG}"
;;
\?)
exit 1
;;
:)
echo "Option -${OPTARG} requires an argument" >&2
exit 1
;;
esac
done

cd .aws-sam/build/OTelLayer/
zip -qr ../../../"$layerName".zip ruby/
cd -
}

main "$@"