Skip to content

Commit

Permalink
updated python azure function to use manual instrumentation
Browse files Browse the repository at this point in the history
  • Loading branch information
dmitchsplunk committed Dec 17, 2024
1 parent 7b7b4d4 commit fd10ad5
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 50 deletions.
2 changes: 1 addition & 1 deletion instrumentation/go/azure-functions/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ __blobstorage__
__queuestorage__
__azurite_db*__.json

# binary
# binary
handler
69 changes: 25 additions & 44 deletions instrumentation/python/azure-functions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,9 @@ If you just want to build and deploy the example, feel free to skip this section
The application used for this example is a simple Hello World application.

We added a file named [splunk_opentelemetry.py](./splunk_opentelemetry.py) to include a helper function
that initializes OpenTelemetry tracing and metrics:
that initializes OpenTelemetry for traces, logs, and metrics:

```python
from splunk_otel.tracing import start_tracing
from splunk_otel.metrics import start_metrics

def init_opentelemetry():

if 'OTEL_SERVICE_NAME' not in os.environ:
Expand All @@ -50,9 +47,25 @@ def init_opentelemetry():
if 'OTEL_RESOURCE_ATTRIBUTES' not in os.environ:
raise Exception('The OTEL_RESOURCE_ATTRIBUTES environment variable must be set')

start_tracing()
start_metrics()

traceProvider = TracerProvider()
processor = BatchSpanProcessor(OTLPSpanExporter())
traceProvider.add_span_processor(processor)
trace.set_tracer_provider(traceProvider)

reader = PeriodicExportingMetricReader(OTLPMetricExporter())
meterProvider = MeterProvider(metric_readers=[reader])
metrics.set_meter_provider(meterProvider)

_logs.set_logger_provider(
LoggerProvider()
)
logging.getLogger().addHandler(
LoggingHandler(
logger_provider=_logs.get_logger_provider().add_log_record_processor(
BatchLogRecordProcessor(OTLPLogExporter())
)
)
)
```

We also updated the [function_app.py](./function_app.py) file to call our helper function to initialize
Expand Down Expand Up @@ -99,12 +112,13 @@ def azure_function_python_opentelemetry_example(req: func.HttpRequest) -> func.H
)
```

These code changes required the `splunk-opentelemetry[all]` and
`opentelemetry-instrumentation-logging` packages to be installed, which we can see
These code changes required several OpenTelemetry packages to be installed, which we can see
in the [requirements.txt](./requirements.txt) file:

````
splunk-opentelemetry[all]==1.21.0
opentelemetry-api
opentelemetry-sdk
opentelemetry-exporter-otlp-proto-http
# add this package to ensure trace context is added to logs
opentelemetry-instrumentation-logging
Expand All @@ -119,7 +133,7 @@ For this example, we'll send metrics, traces, and logs to a collector running on
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "python",
"OTEL_SERVICE_NAME": "azure_function_python_opentelemetry_example",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://<Collector IP Address>:4317",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://<Collector IP Address>:4318",
"OTEL_RESOURCE_ATTRIBUTES": "deployment.environment=test",
"OTEL_PYTHON_LOG_CORRELATION": "true"
}
Expand All @@ -140,30 +154,6 @@ configuration instead for [local.settings.json](./local.settings.json):
}
````

The [host.json](./host.json) file was also updated to set the `telemetryMode` to `OpenTelemetry`. This
enables OpenTelemetry output from the host where the function runs:

````
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
},
"telemetryMode": "OpenTelemetry",
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[4.*, 5.0.0)"
}
````

Note: while the above setting should be optional, during testing it was observed that
application traces don't get captured either if this setting is not included.

## Build and Deploy

Open the following project using Visual Studio Code:
Expand Down Expand Up @@ -228,15 +218,6 @@ appearing in Splunk Observability Cloud:

Note that the bottom-right of the trace includes a button that links to the related log entries.

### View Metrics in Splunk Observability Cloud

The Splunk distribution of OpenTelemetry Python automatically captures runtime metrics,
such as `process.runtime.cpython.memory`:

![Metrics](./images/metrics.png)

Note that the bottom-right of the trace includes a button that links to the related log entries.

### Add Trace Context to Logs

In general, logs generated by an Azure function get sent to Application Insights.
Expand Down
4 changes: 3 additions & 1 deletion instrumentation/python/azure-functions/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

azure-functions

splunk-opentelemetry[all]==1.21.0
opentelemetry-api
opentelemetry-sdk
opentelemetry-exporter-otlp-proto-http

# add this package to ensure trace context is added to logs
opentelemetry-instrumentation-logging
34 changes: 30 additions & 4 deletions instrumentation/python/azure-functions/splunk_opentelemetry.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import os
from splunk_otel.tracing import start_tracing
from splunk_otel.metrics import start_metrics
import logging
from opentelemetry import trace, _logs, metrics
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader

def init_opentelemetry():

Expand All @@ -13,5 +22,22 @@ def init_opentelemetry():
if 'OTEL_RESOURCE_ATTRIBUTES' not in os.environ:
raise Exception('The OTEL_RESOURCE_ATTRIBUTES environment variable must be set')

start_tracing()
start_metrics()
traceProvider = TracerProvider()
processor = BatchSpanProcessor(OTLPSpanExporter())
traceProvider.add_span_processor(processor)
trace.set_tracer_provider(traceProvider)

reader = PeriodicExportingMetricReader(OTLPMetricExporter())
meterProvider = MeterProvider(metric_readers=[reader])
metrics.set_meter_provider(meterProvider)

_logs.set_logger_provider(
LoggerProvider()
)
logging.getLogger().addHandler(
LoggingHandler(
logger_provider=_logs.get_logger_provider().add_log_record_processor(
BatchLogRecordProcessor(OTLPLogExporter())
)
)
)

0 comments on commit fd10ad5

Please sign in to comment.