Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
4642823
Refactor, reorganize and cleanup for AWS prep
pglombardo Feb 14, 2020
d090049
AWS Lambda Agent, Layer, Span & handler method
pglombardo Feb 25, 2020
4e5e1ed
Functional Lambda Tracing and Infra linking
pglombardo Feb 27, 2020
a53e74b
Bug fixes for test suite issues
pglombardo Feb 27, 2020
f0d336e
Bug fixes for test suite issues: second batch
pglombardo Feb 27, 2020
df6f73f
Restructured tag collection
pglombardo Mar 3, 2020
cc3dd0a
Update suds and grpcio tests. Unify spans in span.py
pglombardo Mar 3, 2020
2b641ea
Remove debug remnants
pglombardo Mar 3, 2020
63c4dd6
Update/fix cassandra tests
pglombardo Mar 3, 2020
1e7f775
Check if agent supports extra_headers before proceeding
pglombardo Mar 5, 2020
ddd45ce
Centralize all lambda instrumentation
pglombardo Mar 10, 2020
130e931
New Lambda test suite
pglombardo Mar 10, 2020
6d27d42
New and improved lambda handler and handler parsing
pglombardo Mar 10, 2020
e3c5f92
Fix trailing slash bug reported by Justyn
pglombardo Mar 10, 2020
a2f9ae4
Refinement and additions for the test suite
pglombardo Mar 10, 2020
d7189a4
Linter love
pglombardo Mar 10, 2020
46df777
Allow get/set of agent & tracer for tests
pglombardo Mar 10, 2020
a28c1ae
Updated build script
pglombardo Mar 10, 2020
2c824ad
Restore agent and tracer after each test; lint fixes
pglombardo Mar 10, 2020
cdd15b0
Enable script for all regions
pglombardo Mar 13, 2020
26888d0
Better script name
pglombardo Mar 13, 2020
e70ae15
Trigger support & tests
pglombardo Mar 17, 2020
e214ceb
Move Lambda inst into it's own package
pglombardo Mar 17, 2020
d583626
Code documentation
pglombardo Mar 18, 2020
61d80ce
Update import path
pglombardo Mar 18, 2020
372672d
Keep 2.7 compatible: no type hints
pglombardo Mar 18, 2020
06be7e8
Py 2.7 compatible decompression
pglombardo Mar 18, 2020
58abc62
Fix Python 3.5 compatibility
pglombardo Mar 19, 2020
4e0571e
Remove comment
pglombardo Mar 19, 2020
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
97 changes: 97 additions & 0 deletions bin/lambda_build_publish_layer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#!/usr/bin/env python

import os
import json
import shutil
import time
import distutils.spawn
from subprocess import call, check_output

# Disable aws CLI pagination
os.environ["AWS_PAGER"] = ""

# Check requirements first
for cmd in ["pip", "zip"]:
if distutils.spawn.find_executable(cmd) is None:
print("Can't find required tool: %s" % cmd)
exit(1)

# Determine where this script is running from
this_file_path = os.path.dirname(os.path.realpath(__file__))

# Change directory to the base of the Python sensor repository
os.chdir(this_file_path + "/../")

cwd = os.getcwd()
print("===> Working directory is: %s" % cwd)

# For development, respect or set PYTHONPATH to this repository
local_env = os.environ.copy()
if "PYTHONPATH" not in os.environ:
local_env["PYTHONPATH"] = os.getcwd()

build_directory = os.getcwd() + '/build/lambda/python'

if os.path.isdir(build_directory):
print("===> Cleaning build pre-existing directory: %s" % build_directory)
shutil.rmtree(build_directory)

print("===> Creating new build directory: %s" % build_directory)
os.makedirs(build_directory, exist_ok=True)

print("===> Installing Instana and dependencies into build directory")
call(["pip", "install", "-q", "-U", "-t", os.getcwd() + '/build/lambda/python', "instana"], env=local_env)

print("===> Manually copying in local dev code")
shutil.rmtree(build_directory + "/instana")
shutil.copytree(os.getcwd() + '/instana', build_directory + "/instana")

print("===> Creating Lambda ZIP file")
timestamp = time.strftime("%Y-%m-%d_%H:%M:%S")
zip_filename = "instana-py-layer-%s.zip" % timestamp

os.chdir(os.getcwd() + "/build/lambda/")
call(["zip", "-q", "-r", zip_filename, "./python", "-x", "*.pyc", "./python/pip*", "./python/setuptools*", "./python/wheel*"])

fq_zip_filename = os.getcwd() + '/%s' % zip_filename
aws_zip_filename = "fileb://%s" % fq_zip_filename
print("Zipfile should be at: ", fq_zip_filename)

regions = ['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']

# regions = ['us-west-1']

# LAYER_NAME = "instana-py-test"
LAYER_NAME = "instana-python"

published = dict()

for region in regions:
print("===> Uploading layer to AWS %s " % region)
response = check_output(["aws", "--region", region, "lambda", "publish-layer-version",
"--description",
"Provides Instana tracing and monitoring of AWS Lambda functions built with Python",
"--license-info", "MIT", "--output", "json",
"--layer-name", LAYER_NAME, "--zip-file", aws_zip_filename,
"--compatible-runtimes", "python2.7", "python3.6", "python3.7", "python3.8"])

json_data = json.loads(response)
version = json_data['Version']
print("===> Uploaded version is %s" % version)

print("===> Making layer public...")
response = check_output(["aws", "--region", region, "lambda", "add-layer-version-permission",
"--layer-name", LAYER_NAME, "--version-number", str(version),
"--statement-id", "public-permission-all-accounts",
"--principal", "*",
"--action", "lambda:GetLayerVersion",
"--output", "text"])

published[region] = json_data['LayerVersionArn']


print("===> Published list:")
for key in published.keys():
print("%s\t%s" % (key, published[key]))
34 changes: 27 additions & 7 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,37 @@ services:
- ./bin:/nodejs-collector-bin
# command: ["/nodejs-collector-bin/wait-for-it.sh", "-s", "-t", "120", "zookeeper:2181", "--", "start-kafka.sh"]

mysql:
image: mysql:8.0.1
cassandra:
image: cassandra:3.11.5
ports:
- 9042:9042


couchbase:
image: couchbase
ports:
- 8091-8094:8091-8094
- 11210:11210

mariadb:
image: mariadb
ports:
- 3306:3306
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
MYSQL_DATABASE: 'circle_test'
MYSQL_USER: 'root'
MYSQL_PASSWORD: ''
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
MYSQL_ROOT_PASSWORD: ''
MYSQL_DATABASE: circle_test
MYSQL_USER: root
MYSQL_PASSWORD:
MYSQL_ROOT_HOST: '0.0.0.0'
MYSQL_ROOT_HOST: '%'
volumes:
- ./tests/config/database/mysql/conf.d:/etc/mysql/conf.d

mongodb:
image: 'mongo:3.4.1'
ports:
- '27017:27017'

postgres:
image: postgres:10.5
ports:
Expand All @@ -68,3 +85,6 @@ services:
ports:
- 5671:5671
- 5672:5672

#volumes:
# mysql-data:
56 changes: 55 additions & 1 deletion instana/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@

import os
import sys
from threading import Timer
import importlib
import pkg_resources
from threading import Timer

__author__ = 'Instana Inc.'
__copyright__ = 'Copyright 2020 Instana Inc.'
Expand All @@ -45,6 +46,57 @@ def load(_):
if "INSTANA_DEBUG" in os.environ:
print("Instana: activated via AUTOWRAPT_BOOTSTRAP")

if "INSTANA_ENDPOINT_URL" in os.environ:
print("load: detected lambda environment")


def get_lambda_handler_or_default():
"""
For instrumenting AWS Lambda, users specify their original lambda handler in the LAMBDA_HANDLER environment
variable. This function searches for and parses that environment variable or returns the defaults.

The default handler value for AWS Lambda is 'lambda_function.lambda_handler' which
equates to the function "lambda_handler in a file named "lambda_function.py" or in Python
terms "from lambda_function import lambda_handler"
"""
handler_module = "lambda_function"
handler_function = "lambda_handler"

try:
handler = os.environ.get("LAMBDA_HANDLER", False)

if handler:
parts = handler.split(".")
handler_function = parts.pop()
handler_module = ".".join(parts)
except:
pass

return handler_module, handler_function


def lambda_handler(event, context):
"""
Entry point for AWS Lambda monitoring.

This function will trigger the initialization of Instana monitoring and then call
the original user specified lambda handler function.
"""
module_name, function_name = get_lambda_handler_or_default()

try:
# Import the module specified in module_name
handler_module = importlib.import_module(module_name)
except ImportError:
print("Couldn't determine and locate default module handler: %s.%s", module_name, function_name)
else:
# Now get the function and execute it
if hasattr(handler_module, function_name):
handler_function = getattr(handler_module, function_name)
return handler_function(event, context)
else:
print("Couldn't determine and locate default function handler: %s.%s", module_name, function_name)


def boot_agent():
"""Initialize the Instana agent and conditionally load auto-instrumentation."""
Expand All @@ -56,6 +108,8 @@ def boot_agent():
# Instrumentation
if "INSTANA_DISABLE_AUTO_INSTR" not in os.environ:
# Import & initialize instrumentation
from .instrumentation.aws import lambda_inst

if sys.version_info >= (3, 5, 3):
from .instrumentation import asyncio
from .instrumentation.aiohttp import client
Expand Down
Loading