Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
Empty file added uptrace/.env
Empty file.
1 change: 1 addition & 0 deletions uptrace/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*__pycache__
51 changes: 51 additions & 0 deletions uptrace/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
ARG base=python:3.10.11-bullseye


FROM ${base} AS poetry
ARG POETRY_VERSION=1.4.0

ENV POETRY_VERSION=${POETRY_VERSION}

RUN apt-get update && \
apt-get -y install build-essential \
curl && \
curl -sSL https://install.python-poetry.org | python


###

FROM ${base} AS builder

ENV FLASK_APP=app.py
ENV PATH=/root/.local/bin:$PATH
ENV POETRY_VIRTUALENVS_CREATE=false
ENV PIP_DISABLE_PIP_VERSION_CHECK=on

WORKDIR /usr/src/app

COPY --from=poetry /root/.local /root/.local

COPY pyproject.toml .
COPY poetry.lock .


RUN apt-get update && \
apt-get -y install build-essential && \
poetry install -vv -n --only=main --no-root

###

FROM ${base}

WORKDIR /usr/src/app

ENV PYTHONUNBUFFERED=1
ENV PATH=/root/.local/bin:$PATH

EXPOSE 8000/tcp
CMD ["flask", "run", "--host", "0.0.0.0"]


COPY --from=poetry /root/.local /root/.local
COPY --from=builder /usr/local /usr/local
COPY . /usr/src/app
49 changes: 49 additions & 0 deletions uptrace/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Uptrace Docker demo

## Getting started

This example demonstrates how to quickly start Uptrace using Docker. To run Uptrace permanently, you
can also use a DEB/RPM [package](https://uptrace.dev/get/install.html#packages) or a pre-compiled
[binary](https://uptrace.dev/get/install.html#binaries).

**Step 1**. Download the example using Git:

```shell
git clone https://github.com/uptrace/uptrace.git
cd uptrace/example/docker
```

**Step 2**. Start the services using Docker:

```shell
docker-compose pull
docker-compose up -d
```

**Step 3**. Make sure Uptrace is running:

```shell
docker-compose logs uptrace
```

**Step 4**. Open Uptrace UI at [http://localhost:14318](http://localhost:14318)

Uptrace will monitor itself using [uptrace-go](https://github.com/uptrace/uptrace-go) OpenTelemetry
distro. To get some test data, just reload the UI few times. It usually takes about 30 seconds for
the data to appear.

To configure OpenTelemetry for your programming language, see
[documentation](https://uptrace.dev/get/get-started.html).

## Alerting

This example uses MailHog to test email notifications. Open
[http://localhost:8025](http://localhost:8025) to view available email notifications.

See [Alerting and Notifications](https://uptrace.dev/get/alerting.html) for more details.

## OpenTelemetry Collector

This example also comes with a pre-configured OpenTelemetry Collector to monitor
[host metrics](https://uptrace.dev/opentelemetry/collector-host-metrics.html) and
[PostgreSQL](https://uptrace.dev/opentelemetry/postgresql-monitoring.html).
39 changes: 39 additions & 0 deletions uptrace/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import demo
import os
import celery

import opentelemetry
import opentelemetry.exporter.otlp.proto.grpc.metric_exporter
import opentelemetry.exporter.otlp.proto.grpc.trace_exporter
import opentelemetry.instrumentation.wsgi
import opentelemetry.sdk.metrics
import opentelemetry.sdk.trace
import opentelemetry.sdk.trace.export
import opentelemetry.semconv.trace
import pkg_resources


tracer = opentelemetry.sdk.trace.TracerProvider()
tracer.add_span_processor(
opentelemetry.sdk.trace.export.BatchSpanProcessor(
opentelemetry.exporter.otlp.proto.grpc.trace_exporter.OTLPSpanExporter(),
),
)
opentelemetry.trace.set_tracer_provider(tracer)

meter = opentelemetry.sdk.metrics.MeterProvider([
opentelemetry.sdk.metrics.export.PeriodicExportingMetricReader(
opentelemetry.exporter.otlp.proto.grpc.metric_exporter.OTLPMetricExporter()
)
])
opentelemetry.metrics.set_meter_provider(meter)

for entry_point in pkg_resources.iter_entry_points('opentelemetry_instrumentor'):
Instrumentor = entry_point.load()
Instrumentor().instrument()

app = demo.create_app()

# app.register_blueprint(demo.endpoints.app)
celery_app = demo.celery_init_app(app)

54 changes: 54 additions & 0 deletions uptrace/config/otel-collector.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# REF: https://opentelemetry.io/docs/collector/configuration/

receivers:
otlp:
protocols:
grpc:
http:

processors:
batch:
send_batch_size: 10000
timeout: 10s
cumulativetodelta:
resourcedetection:
detectors:
- env
- system

exporters:
otlp:
endpoint: uptrace:14317
headers:
uptrace-dsn: '${env:UPTRACE_DSN}'
tls:
insecure: true
logging:
loglevel: info

service:
pipelines:
traces:
receivers:
- otlp
processors:
- batch
exporters:
- otlp
- logging
metrics:
receivers:
- otlp
processors:
- batch
exporters:
- otlp
- logging
logs:
receivers:
- otlp
processors:
- batch
exporters:
- otlp
- logging
30 changes: 30 additions & 0 deletions uptrace/config/uptrace.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-----BEGIN CERTIFICATE-----
MIIFHzCCAwegAwIBAgIUBaw6sa4CxZG0HoeTXxvkfYQU0uYwDQYJKoZIhvcNAQEL
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIzMDUyODA2NDMxN1oXDTMzMDUy
NTA2NDMxN1owFDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF
AAOCAg8AMIICCgKCAgEApxMHiQhDg6q5v23qPsDCDqPZKSiJIOtsOhrwvfro8d19
RnUO+bSXYgwtTrNa5HquTaNCc7/ERyT68RuCa0RJfZNy9rgUXBpH6ODaQ/x8fPgy
Lv7IqSr3Egb77jWPu3zxotNXVj+7vmhSgx76TXoJjryhU46N6rw90c5FjjBdkhwC
NopWH+B8rnrZCAl2VOd5Y6GxphUPgn2j/K/NOKesjnLw75eIpQtTnBxhgD9Lovj2
4ffK4XNYqEoeqHhvkizcBgV7LATCKnpy9H0Ry2hC6IljOtCnY+4T/m4EJuPFZGhM
dcBFLgC89uv/qUMWJRB0J3lwR8g9Bs6ktFnpxtiwdwzqBquuceiBpK9uNI2gLzfJ
fNr7rooLhtG0iR7rn+50KD5yvWijhq2sOkodEgzlCjThbGY2d95Vee480T6zbHtq
lL1cPTPHVP9saTN2NpvsMx5iKmEmYkm3cK8rsfVQYlnLtNST9WQexLo/h3aC5irK
JNRKE16Rz9EvJCNR0xu8dk6w0IogXTW0bJj6WV3BxY7IwtO8vI8vmUIeG7oMmDx3
CYJh2zRsEkFt+zcwVJSbuc8Tw9aMCCiqP79hnQXyWdXDWmd39D200nawzyt+rp71
xV3QEgSx9m5a2iRfF8zhQEUhkW3Z7ISmzdPAvCTQ3hOTd50GJkDj7bElXCWTVLEC
AwEAAaNpMGcwHQYDVR0OBBYEFG244f2Mah9YBWgP7YuybLFtLyb3MB8GA1UdIwQY
MBaAFG244f2Mah9YBWgP7YuybLFtLyb3MA8GA1UdEwEB/wQFMAMBAf8wFAYDVR0R
BA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBCwUAA4ICAQCeiGKKXL7P+N7YkIC9
6um0KcJLVzdYEVFd4o2n8JnW5qzVSKCI/bZfSEGIBXWI5vOgV7BO+BztNABYtaCt
VNnlAitAqf8BOq1jBn2yWuZzB9lVROSksVvO0HiFChpRo8K8cNa3XNzIEvGmKaYf
ldW90i/Z4uS+Yi2LfEBuL1XgUxumUXXDcWiC/MItbp93SgW1lT2wLGUCXSLWPWNL
f8w2jzJLs98B1G0d6nhx5EmYiCdjfx1RTo/yE/D+g6GkRGrUQeb3tQlg9o0mXB2G
K+PcAO9Op4GC/iNalLETbHkIZQ9ZAXQ7THfX/3weElJhz6GiEn4Brwb3EP5DEULy
9Iv44kCBjB/s7r383USmZYkxJdX9nG6UTCuOzFKGvjOkXaKSOdjw86awWrNnlvcG
o7fddpoFOq+HWiBprPsqjImptSRM2qPVbiEnx+KFigItk36tSdSidG/16or/5KyX
4BN0vkDpg8j/vEBqX7C1TlkXrWWYR1lRzNtFpi16VvV2ht/LdHpPgUTmhVRoG50L
fXY7wP5t0B55cjBC4du7Q3ULXKTOGZCEX3NxHbkp2gCrARSdMYQF5UDbU7n2L7h2
QPY5U4eZ46uG/Xe340Z2aorJ+PydpDgZ5v/IMK2ZkdbuiJq51C63crO1r/xPDrE7
gYUrQNr4ZHigXDoiv6qyMHacLA==
-----END CERTIFICATE-----
52 changes: 52 additions & 0 deletions uptrace/config/uptrace.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
e149zm2ClhuXXoIvEt6AhLoq2FwY
-----END PRIVATE KEY-----
24 changes: 24 additions & 0 deletions uptrace/config/uptrace.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# REF: https://uptrace.dev/get/config.html

ch:
addr: clickhouse:9000
user: ${CLICKHOUSE_USER}
password: ${CLICKHOUSE_PASSWORD}
database: ${CLICKHOUSE_DB}

pg:
addr: postgres:5432
user: ${POSTGRES_USER}
password: ${POSTGRES_PASSWORD}
database: ${POSTGRES_DB}

projects:
- id: 1
name: SWAG
token: ${UPTRACE_PROJECT_TOKEN}

auth:
users:
- name: Anonymous
email: uptrace@localhost
password: uptrace
14 changes: 14 additions & 0 deletions uptrace/config/uwsgi.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[uwsgi]
module = app:app
master = true
die-on-term = true
post-buffering = true
reload-mercy = 30
worker-reload-mercy = 15
need-app = true
strict = true
hook-master-start = unix_signal:15 gracefully_kill_them_all
hook-master-start = unix_signal:2 gracefully_kill_them_all
hook-master-start = unix_signal:3 gracefully_kill_them_all
disable-write-exception = true
cache2 = name=inmemory,maxitems=500,bitmap=1
34 changes: 34 additions & 0 deletions uptrace/demo/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from flask import Flask
from celery import Celery, Task, signals
from flask_mongoengine import MongoEngine
from opentelemetry.instrumentation.pymongo import PymongoInstrumentor
from opentelemetry.instrumentation.celery import CeleryInstrumentor


db = MongoEngine()

def create_app() -> Flask:
app = Flask(__name__)
app.config.from_object('demo.settings.Config')
app.config.from_prefixed_env()
celery_init_app(app)
db.init_app(app)

from . import endpoints

app.register_blueprint(endpoints.app)

return app


def celery_init_app(app: Flask) -> Celery:
class FlaskTask(Task):
def __call__(self, *args: object, **kwargs: object) -> object:
with app.app_context():
return self.run(*args, **kwargs)

celery_app = Celery(app.name, task_cls=FlaskTask)
celery_app.config_from_object(app.config["CELERY"])
celery_app.set_default()
app.extensions["celery"] = celery_app
return celery_app
Loading