Skip to content

Commit

Permalink
chore: bump otel deps + setup CI (unit + smoke tests) (#19)
Browse files Browse the repository at this point in the history
* chore: bump deps

* update: smoke tests

* ci: run unit test

* fix: ci

* ci: bump checkout action

* ci: run smoke tests

* fix: setup BATS
  • Loading branch information
wrn14897 committed Feb 16, 2024
1 parent 8f41d4b commit 8eed7d1
Show file tree
Hide file tree
Showing 29 changed files with 878 additions and 415 deletions.
61 changes: 61 additions & 0 deletions .github/workflows/smoke.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Smoke
on:
push:
branches: [main]
pull_request:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
main:
timeout-minutes: 8
runs-on: ubuntu-20.04
steps:
- name: Setup BATS
uses: mig4/setup-bats@v1
with:
bats-version: 1.10.0
- name: Check out repository
uses: actions/checkout@v4
- name: Set up python
id: setup-python
uses: actions/setup-python@v5
with:
python-version: '3.10'
#----------------------------------------------
# ----- install & configure poetry -----
#----------------------------------------------
- name: Install Poetry
uses: snok/install-poetry@v1
with:
virtualenvs-create: true
virtualenvs-in-project: true
installer-parallel: true
#----------------------------------------------
# load cached venv if cache exists
#----------------------------------------------
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
path: .venv
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
#----------------------------------------------
# install dependencies if cache does not exist
#----------------------------------------------
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: poetry install --no-interaction --no-root
#----------------------------------------------
# install your root project, if required
#----------------------------------------------
- name: Install project
run: poetry install --no-interaction
#----------------------------------------------
# run test suite
#----------------------------------------------
- name: Build
run: make build
- name: Run smoke tests
run: make smoke-sdk
57 changes: 57 additions & 0 deletions .github/workflows/unit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Unit
on:
push:
branches: [main]
pull_request:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
main:
timeout-minutes: 8
runs-on: ubuntu-20.04
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Set up python
id: setup-python
uses: actions/setup-python@v5
with:
python-version: '3.10'
#----------------------------------------------
# ----- install & configure poetry -----
#----------------------------------------------
- name: Install Poetry
uses: snok/install-poetry@v1
with:
virtualenvs-create: true
virtualenvs-in-project: true
installer-parallel: true
#----------------------------------------------
# load cached venv if cache exists
#----------------------------------------------
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
path: .venv
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
#----------------------------------------------
# install dependencies if cache does not exist
#----------------------------------------------
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: poetry install --no-interaction --no-root
#----------------------------------------------
# install your root project, if required
#----------------------------------------------
- name: Install project
run: poetry install --no-interaction
#----------------------------------------------
# run test suite
#----------------------------------------------
- name: Build
run: make build
- name: Run unit tests
run: make test
2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Check out the [Hello-World Readme](hello-world/README.md) for setting this up!

If you'd like to use Docker for running these examples, there is a `docker-compose.yml` we use for smoke-tests [that may be helpful.](../smoke-tests/docker-compose.yml)

We have the HYPERDX_API_ENDPOINT set to an OpenTelemetry Collector. This can be modified as needed or deleted entirely to use the default HyperDX API Endpoint.
We have the HONEYCOMB_API_ENDPOINT set to an OpenTelemetry Collector. This can be modified as needed or deleted entirely to use the default Honeycomb API Endpoint.

Because each example uses the same port, either comment out the other apps in the docker-compose file, or specify the app and protocol to run:

Expand Down
49 changes: 49 additions & 0 deletions examples/hello-world-django/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# hello-world

This simple Django app returns "Hello World". This app uses the `configure_opentelemetry` method from `honeycomb.opentelemetry` to set up OpenTelemetry to export data to Honeycomb through configuration options set in the app's code. It is also possible to set configuration options through the `opentelemetry_instrument` command (see the instructions for automatic instrumenetation [here](https://docs.honeycomb.io/getting-data-in/opentelemetry/python-distro/#automatic-instrumentation)).

## Prerequisites

You'll need [Poetry](https://python-poetry.org/) installed to run the example. Poetry automatically creates a virtual environment to run the example in so you don't need to manage one yourself.

## Running the example

Install application dependencies:

```bash
poetry install
```

Run the application:

```bash
poetry run python manage.py runserver
```

Then navigate to http://127.0.0.1:8000 as shown in the command output and you should see `Hello, world`.

## Distro Instrumentation Example

This app uses configuration configures the OpenTelemetry SDK programmatically in [manage.py](./manage.py).
Alternatively, you can use environment variables as parameters like below:

```python
configure_opentelemetry(
HoneycombOptions(
debug=True,
apikey=os.getenv("HYPERDX_API_KEY"),
service_name="hello-world-django"
)
)
```

Note: With `debug` set to `True`, spans will also be printed to stdout.

To send to Honeycomb, set your API Key:

```bash
HYPERDX_API_KEY="your-api-key" poetry run python manage.py runserver
```

You can configure exporter protocol with this flag:
`OTEL_EXPORTER_OTLP_PROTOCOL=grpc` or `OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf`
Empty file.
Empty file.
16 changes: 16 additions & 0 deletions examples/hello-world-django/hello_world/asgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
ASGI config for hello_world project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
"""

import os

from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hello_world.settings')

application = get_asgi_application()
123 changes: 123 additions & 0 deletions examples/hello-world-django/hello_world/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
"""
Django settings for hello_world project.
Generated by 'django-admin startproject' using Django 5.0.1.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.0/ref/settings/
"""

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-c8cw65!*ys%e%w*$ow-%fi3&0k-zt51+c25pv_c&9zk#ba3e^i'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'hello_world.urls'

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

WSGI_APPLICATION = 'hello_world.wsgi.application'


# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}


# Password validation
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]


# Internationalization
# https://docs.djangoproject.com/en/5.0/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/

STATIC_URL = 'static/'

# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
23 changes: 23 additions & 0 deletions examples/hello-world-django/hello_world/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""
URL configuration for hello_world project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/5.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path('admin/', admin.site.urls),
path("", include("pages.urls")),
]
16 changes: 16 additions & 0 deletions examples/hello-world-django/hello_world/wsgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
WSGI config for hello_world project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hello_world.settings')

application = get_wsgi_application()

0 comments on commit 8eed7d1

Please sign in to comment.