From fd8d92a64483d79b48a1a7c63594f0183a1c67e7 Mon Sep 17 00:00:00 2001 From: Irene Stanely Date: Tue, 28 Jan 2025 12:08:34 -0600 Subject: [PATCH 1/8] adding application insights distro without collector --- python/.env_sample | 12 ++++++++++++ python/common/configurator/config_reader.py | 6 ++++++ python/requirements.txt | 5 ++++- python/sk_financial_analyst/README.md | 2 +- .../deployment/durable_function/function_app.py | 7 +++++++ .../deployment/durable_function/requirements.txt | 8 ++++++++ .../executors/aml/aml_batch_executor.py | 9 ++++++++- .../sk_financial_analyst/executors/aml/aml_env.yaml | 12 ++++++++---- .../executors/single_item_executor.py | 4 ++-- python/sk_financial_analyst/routes/routes.py | 9 +++++---- 10 files changed, 61 insertions(+), 13 deletions(-) diff --git a/python/.env_sample b/python/.env_sample index c1c11ad..25d3205 100644 --- a/python/.env_sample +++ b/python/.env_sample @@ -8,3 +8,15 @@ AML_RESOURCE_GROUP_NAME= AML_WORKSPACE_NAME= SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS_SENSITIVE=true +OTEL_SERVICE_NAME="sk-financial-analyst-local" +OTEL_LOGS_EXPORTER="otlp" +OTEL_TRACES_EXPORTER="otlp" +OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED="true" +OTEL_EXPORTER_OTLP_PROTOCOL="grpc" +OTEL_EXPORTER_OTLP_INSECURE="true" +OTEL_LOG_LEVEL="INFO" +OTEL_RESOURCE_ATTRIBUTES="service.name=sk-financial-analyst-local" +OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317" +OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="http://localhost:4318" +# application insights connection string is added if you prefer not using collector. +APPLICATIONINSIGHTS_CONNECTION_STRING= diff --git a/python/common/configurator/config_reader.py b/python/common/configurator/config_reader.py index 3a6f650..bdb5299 100644 --- a/python/common/configurator/config_reader.py +++ b/python/common/configurator/config_reader.py @@ -3,12 +3,18 @@ import os import yaml +from azure.monitor.opentelemetry import configure_azure_monitor +from common.configurator.otel import config_otel from dotenv import load_dotenv def load_yaml(file_path): """Load a YAML file.""" load_dotenv() + if (os.environ.get("APPLICATIONINSIGHTS_CONNECTION_STRING")) is not None: + configure_azure_monitor() + else: + config_otel() with open(file_path, "r") as stream: return yaml.safe_load(os.path.expandvars(stream.read())) diff --git a/python/requirements.txt b/python/requirements.txt index 945b264..027272c 100644 --- a/python/requirements.txt +++ b/python/requirements.txt @@ -14,7 +14,7 @@ flake8==7.1.1 pep8-naming==0.14.1 pytest==8.3.3 pytest-cov==5.0.0 -opentelemetry-instrumentation==0.49b2 +## otel collector opentelemetry-instrumentation-openai==0.33.12 opentelemetry-instrumentation-fastapi==0.49b2 opentelemetry-distro==0.49b2 @@ -22,3 +22,6 @@ opentelemetry-exporter-otlp==1.28.2 fastapi==0.115.4 uvicorn==0.32.0 pydantic==2.8.2 +## set this only when you want to directly instrument using +## application insights without collector +azure-monitor-opentelemetry==1.6.4 diff --git a/python/sk_financial_analyst/README.md b/python/sk_financial_analyst/README.md index d99386f..525fb4d 100644 --- a/python/sk_financial_analyst/README.md +++ b/python/sk_financial_analyst/README.md @@ -82,7 +82,7 @@ python -m sk_financial_analyst.executors.single_item_executor --stock_ticker ` is set by default to `MSFT`. You can run: ```bash -python -m sk_financial_analyst.executors.single_item_executor --help +python -m çsingle_item_executor --help ``` to see all available command line options. diff --git a/python/sk_financial_analyst/deployment/durable_function/function_app.py b/python/sk_financial_analyst/deployment/durable_function/function_app.py index e2f0e86..33ae88f 100644 --- a/python/sk_financial_analyst/deployment/durable_function/function_app.py +++ b/python/sk_financial_analyst/deployment/durable_function/function_app.py @@ -7,6 +7,8 @@ import azure.functions as func from azure.identity import DefaultAzureCredential from azure.keyvault.secrets import SecretClient +from azure.monitor.opentelemetry import configure_azure_monitor +from common.configurator import otel from llm_application.financial_health_analysis import FinancialHealthAnalysis app = df.DFApp(http_auth_level=func.AuthLevel.FUNCTION) @@ -69,6 +71,11 @@ async def generate_report(stock): structured_report_generator_model = os.environ.get("REPORT_GENERATOR_MODEL_NAME") aoai_api_version = os.environ.get("AOAI_API_VERSION") + if (os.environ.get("APPLICATIONINSIGHTS_CONNECTION_STRING")) is not None: + configure_azure_monitor() + else: + otel.config_otel() + credential = DefaultAzureCredential(managed_identity_client_id=managed_identity_client_id) aoai_token = credential.get_token(auth_provider_endpoint).token diff --git a/python/sk_financial_analyst/deployment/durable_function/requirements.txt b/python/sk_financial_analyst/deployment/durable_function/requirements.txt index d2bd46c..ba73486 100644 --- a/python/sk_financial_analyst/deployment/durable_function/requirements.txt +++ b/python/sk_financial_analyst/deployment/durable_function/requirements.txt @@ -13,3 +13,11 @@ edgartools yfinance==0.2.40 semantic-kernel pydantic==2.8.2 +## otel collector +opentelemetry-instrumentation-openai==0.33.12 +opentelemetry-instrumentation-fastapi==0.49b2 +opentelemetry-distro==0.49b2 +opentelemetry-exporter-otlp==1.28.2 +## set this only when you want to directly instrument using +## application insights without collector +azure-monitor-opentelemetry==1.6.4 diff --git a/python/sk_financial_analyst/executors/aml/aml_batch_executor.py b/python/sk_financial_analyst/executors/aml/aml_batch_executor.py index f3533af..57c3633 100644 --- a/python/sk_financial_analyst/executors/aml/aml_batch_executor.py +++ b/python/sk_financial_analyst/executors/aml/aml_batch_executor.py @@ -16,6 +16,8 @@ from azure.ai.ml.entities import Environment from azure.ai.ml.parallel import RunFunction, parallel_run_function from azure.identity import DefaultAzureCredential +from azure.monitor.opentelemetry import configure_azure_monitor +from common.configurator import otel from dotenv import load_dotenv @@ -118,7 +120,12 @@ def main(): """ args = parse_args() load_dotenv(override=True) - + # if application connection string is available, directly use azure monitor connection + # else collector is used. + if (os.environ.get("APPLICATIONINSIGHTS_CONNECTION_STRING")) is not None: + configure_azure_monitor() + else: + otel.config_otel() subscription_id = os.getenv("AZURE_SUBSCRIPTION_ID") resource_group = os.getenv("AML_RESOURCE_GROUP_NAME") workspace = os.getenv("AML_WORKSPACE_NAME") diff --git a/python/sk_financial_analyst/executors/aml/aml_env.yaml b/python/sk_financial_analyst/executors/aml/aml_env.yaml index ee01b5e..4c78d99 100644 --- a/python/sk_financial_analyst/executors/aml/aml_env.yaml +++ b/python/sk_financial_analyst/executors/aml/aml_env.yaml @@ -10,13 +10,17 @@ dependencies: - azure-identity==1.19.0 - azure-keyvault-secrets==4.9.0 - azure-ai-evaluation==1.0.0b5 - - azure-monitor-opentelemetry-exporter==1.0.0b31 - pyyaml==6.0.2 - requests==2.32.3 - edgartools==2.34.2 - python-dotenv==1.0.1 - yfinance==0.2.40 - semantic-kernel==1.11.0 - - opentelemetry-api==1.27.0 - - opentelemetry-sdk==1.27.0 - - opentelemetry-semantic-conventions==0.48b0 + ## otel collector + - opentelemetry-instrumentation-openai==0.33.12 + - opentelemetry-instrumentation-fastapi==0.49b2 + - opentelemetry-distro==0.49b2 + - opentelemetry-exporter-otlp==1.28.2 + ## set this only when you want to directly instrument using + ## application insights without collector + - azure-monitor-opentelemetry==1.6.4 diff --git a/python/sk_financial_analyst/executors/single_item_executor.py b/python/sk_financial_analyst/executors/single_item_executor.py index ae87142..e02a8fc 100644 --- a/python/sk_financial_analyst/executors/single_item_executor.py +++ b/python/sk_financial_analyst/executors/single_item_executor.py @@ -8,7 +8,7 @@ from azure.identity import DefaultAzureCredential from azure.keyvault.secrets import SecretClient -from common.configurator import config_reader, otel +from common.configurator import config_reader from opentelemetry import trace from opentelemetry.trace import SpanKind from sk_financial_analyst.llm_application.financial_health_analysis import FinancialHealthAnalysis @@ -35,7 +35,7 @@ async def generate_report(config_file, stock_ticker): config_data = config_reader.load_yaml(config_file) logger.info("Otel configuration started..") - otel.config_otel() + tracer = trace.get_tracer(__name__) logger.info("Otel configuration successful..") diff --git a/python/sk_financial_analyst/routes/routes.py b/python/sk_financial_analyst/routes/routes.py index 5a6a0f1..f656e62 100644 --- a/python/sk_financial_analyst/routes/routes.py +++ b/python/sk_financial_analyst/routes/routes.py @@ -3,7 +3,7 @@ from azure.identity import DefaultAzureCredential from azure.keyvault.secrets import SecretClient -from common.configurator import config_reader, otel +from common.configurator import config_reader from fastapi import APIRouter, FastAPI from opentelemetry import trace from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor @@ -11,6 +11,8 @@ from opentelemetry.trace import SpanKind from sk_financial_analyst.llm_application.financial_health_analysis import FinancialHealthAnalysis +# Load the configuration data +config_data = config_reader.load_yaml("./sk_financial_analyst/config/config.yaml") logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # from llm_application import financial_health_analysis @@ -19,7 +21,7 @@ router = APIRouter() logger.info("Otel configuration started..") -otel.config_otel() + OpenAIInstrumentor().instrument() FastAPIInstrumentor.instrument_app(app) tracer = trace.get_tracer(__name__) @@ -31,8 +33,7 @@ async def run_financial_health_analysis(stock_ticker: str): try: with tracer.start_as_current_span("run_financial_analysis_report", kind=SpanKind.SERVER) as span: logger.info("Starting finacial report generation..") - # Load the configuration data - config_data = config_reader.load_yaml("./sk_financial_analyst/config/config.yaml") + key_vault_url = os.environ.get("KEY_VAULT_URL") # Get values from the configuration data From 383009cb211514eed90a8e91f6b889697858e026 Mon Sep 17 00:00:00 2001 From: Irene Stanely Date: Wed, 29 Jan 2025 10:10:53 -0600 Subject: [PATCH 2/8] add application connection string to env --- .github/workflows/platform_ci_python.yml | 1 + .github/workflows/platform_pr_python.yml | 2 ++ python/sk_financial_analyst/README.md | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/platform_ci_python.yml b/.github/workflows/platform_ci_python.yml index cb301c9..76804a3 100644 --- a/.github/workflows/platform_ci_python.yml +++ b/.github/workflows/platform_ci_python.yml @@ -66,6 +66,7 @@ NEWS_ANALYST_MODEL_NAME: ${{ vars.NEWS_ANALYST_MODEL_NAME }} FINANCIAL_ANALYST_MODEL_NAME: ${{ vars.FINANCIAL_ANALYST_MODEL_NAME }} REPORT_GENERATOR_MODEL_NAME: ${{ vars.REPORT_GENERATOR_MODEL_NAME }} + APPLICATIONINSIGHTS_CONNECTION_STRING: ${{secrets.APPLICATIONINSIGHTS_CONNECTION_STRING}} run: | python -u -m sk_financial_analyst.executors.single_item_executor --logging_enabled diff --git a/.github/workflows/platform_pr_python.yml b/.github/workflows/platform_pr_python.yml index a70919b..8a9a40d 100644 --- a/.github/workflows/platform_pr_python.yml +++ b/.github/workflows/platform_pr_python.yml @@ -55,5 +55,7 @@ NEWS_ANALYST_MODEL_NAME: ${{ vars.NEWS_ANALYST_MODEL_NAME }} FINANCIAL_ANALYST_MODEL_NAME: ${{ vars.FINANCIAL_ANALYST_MODEL_NAME }} REPORT_GENERATOR_MODEL_NAME: ${{ vars.REPORT_GENERATOR_MODEL_NAME }} + APPLICATIONINSIGHTS_CONNECTION_STRING: ${{secrets.APPLICATIONINSIGHTS_CONNECTION_STRING}} + run: | python -u -m sk_financial_analyst.executors.single_item_executor --logging_enabled \ No newline at end of file diff --git a/python/sk_financial_analyst/README.md b/python/sk_financial_analyst/README.md index 525fb4d..b1dd2a8 100644 --- a/python/sk_financial_analyst/README.md +++ b/python/sk_financial_analyst/README.md @@ -82,7 +82,7 @@ python -m sk_financial_analyst.executors.single_item_executor --stock_ticker ` is set by default to `MSFT`. You can run: ```bash -python -m çsingle_item_executor --help +python -m single_item_executor --help ``` to see all available command line options. From d030bb2ca37f24e2ff5f6da058d2287d86cf73c0 Mon Sep 17 00:00:00 2001 From: Irene Stanely Date: Wed, 29 Jan 2025 10:59:07 -0600 Subject: [PATCH 3/8] trigger the pr build --- .github/workflows/platform_pr_python.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/platform_pr_python.yml b/.github/workflows/platform_pr_python.yml index 8a9a40d..1e6c458 100644 --- a/.github/workflows/platform_pr_python.yml +++ b/.github/workflows/platform_pr_python.yml @@ -56,6 +56,5 @@ FINANCIAL_ANALYST_MODEL_NAME: ${{ vars.FINANCIAL_ANALYST_MODEL_NAME }} REPORT_GENERATOR_MODEL_NAME: ${{ vars.REPORT_GENERATOR_MODEL_NAME }} APPLICATIONINSIGHTS_CONNECTION_STRING: ${{secrets.APPLICATIONINSIGHTS_CONNECTION_STRING}} - run: | python -u -m sk_financial_analyst.executors.single_item_executor --logging_enabled \ No newline at end of file From 220620cd17e80eb20c10c19be91380f272b7c63f Mon Sep 17 00:00:00 2001 From: Irene Stanely Date: Thu, 30 Jan 2025 10:30:17 -0600 Subject: [PATCH 4/8] add application connetion string --- .github/workflows/platform_ci_python.yml | 2 +- .github/workflows/platform_pr_python.yml | 2 +- python/common/configurator/config_reader.py | 2 +- python/sk_financial_analyst/executors/aml/aml_batch_executor.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/platform_ci_python.yml b/.github/workflows/platform_ci_python.yml index 76804a3..7696376 100644 --- a/.github/workflows/platform_ci_python.yml +++ b/.github/workflows/platform_ci_python.yml @@ -50,7 +50,7 @@ working-directory: python run: | python -m pip install --upgrade pip - pip install -r requirements.txt + pip install --upgrade -r requirements.txt - name: Azure login uses: azure/login@v2 diff --git a/.github/workflows/platform_pr_python.yml b/.github/workflows/platform_pr_python.yml index 1e6c458..a47641b 100644 --- a/.github/workflows/platform_pr_python.yml +++ b/.github/workflows/platform_pr_python.yml @@ -39,7 +39,7 @@ working-directory: python run: | python -m pip install --upgrade pip - pip install -r requirements.txt + pip install --upgrade -r requirements.txt - name: Azure login uses: azure/login@v2 diff --git a/python/common/configurator/config_reader.py b/python/common/configurator/config_reader.py index bdb5299..b88f5c5 100644 --- a/python/common/configurator/config_reader.py +++ b/python/common/configurator/config_reader.py @@ -12,7 +12,7 @@ def load_yaml(file_path): """Load a YAML file.""" load_dotenv() if (os.environ.get("APPLICATIONINSIGHTS_CONNECTION_STRING")) is not None: - configure_azure_monitor() + configure_azure_monitor(connection_string=os.environ.get("APPLICATIONINSIGHTS_CONNECTION_STRING")) else: config_otel() with open(file_path, "r") as stream: diff --git a/python/sk_financial_analyst/executors/aml/aml_batch_executor.py b/python/sk_financial_analyst/executors/aml/aml_batch_executor.py index 57c3633..a7be5f6 100644 --- a/python/sk_financial_analyst/executors/aml/aml_batch_executor.py +++ b/python/sk_financial_analyst/executors/aml/aml_batch_executor.py @@ -123,7 +123,7 @@ def main(): # if application connection string is available, directly use azure monitor connection # else collector is used. if (os.environ.get("APPLICATIONINSIGHTS_CONNECTION_STRING")) is not None: - configure_azure_monitor() + configure_azure_monitor(connection_string=os.environ.get("APPLICATIONINSIGHTS_CONNECTION_STRING")) else: otel.config_otel() subscription_id = os.getenv("AZURE_SUBSCRIPTION_ID") From af62842ae4c8af5d240ef719691e1d42d5f3b766 Mon Sep 17 00:00:00 2001 From: Irene Stanely Date: Thu, 30 Jan 2025 11:00:08 -0600 Subject: [PATCH 5/8] revert readme changes --- python/sk_financial_analyst/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/sk_financial_analyst/README.md b/python/sk_financial_analyst/README.md index 5d4b811..fa96525 100644 --- a/python/sk_financial_analyst/README.md +++ b/python/sk_financial_analyst/README.md @@ -82,7 +82,7 @@ python -m sk_financial_analyst.executors.single_item_executor --stock_ticker ` is set by default to `MSFT`. You can run: ```bash -python -m single_item_executor --help +python -m sk_financial_analyst.executors.single_item_executor --help ``` to see all available command line options. From f7a2de6da282debb2f0b5e62548cd3c602d9fcaa Mon Sep 17 00:00:00 2001 From: Irene Stanely Date: Thu, 30 Jan 2025 12:47:10 -0600 Subject: [PATCH 6/8] add working directory --- .github/workflows/platform_pr_python.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/platform_pr_python.yml b/.github/workflows/platform_pr_python.yml index 0c69e3a..ac94807 100644 --- a/.github/workflows/platform_pr_python.yml +++ b/.github/workflows/platform_pr_python.yml @@ -39,6 +39,7 @@ uses: actions/checkout@v3 - name: Check Azure CLI Availability + working-directory: python run: | echo "Current PATH: $PATH" which az From eaffafd4eac76f7152fee4619da8de3b2b4a14a7 Mon Sep 17 00:00:00 2001 From: Irene Stanely Date: Thu, 30 Jan 2025 13:11:09 -0600 Subject: [PATCH 7/8] add app insights connection to github env --- .github/workflows/platform_pr_python.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/platform_pr_python.yml b/.github/workflows/platform_pr_python.yml index ac94807..98c161a 100644 --- a/.github/workflows/platform_pr_python.yml +++ b/.github/workflows/platform_pr_python.yml @@ -67,5 +67,6 @@ echo "Verifying Python Path" which python echo "Installed Packages:" + echo APPLICATIONINSIGHTS_CONNECTION_STRING=${{ secrets.APPLICATIONINSIGHTS_CONNECTION_STRING}} >> $GITHUB_ENV pip list python -u -m sk_financial_analyst.executors.single_item_executor --logging_enabled From 1002e2ae3dc554ed9d874f649d016d6d6ddfb731 Mon Sep 17 00:00:00 2001 From: Irene Stanely Date: Mon, 3 Feb 2025 10:13:54 -0600 Subject: [PATCH 8/8] check if the right value is passed --- python/common/configurator/config_reader.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/python/common/configurator/config_reader.py b/python/common/configurator/config_reader.py index b88f5c5..f476873 100644 --- a/python/common/configurator/config_reader.py +++ b/python/common/configurator/config_reader.py @@ -11,8 +11,10 @@ def load_yaml(file_path): """Load a YAML file.""" load_dotenv() - if (os.environ.get("APPLICATIONINSIGHTS_CONNECTION_STRING")) is not None: - configure_azure_monitor(connection_string=os.environ.get("APPLICATIONINSIGHTS_CONNECTION_STRING")) + connection_string = os.environ.get("APPLICATIONINSIGHTS_CONNECTION_STRING") + if connection_string is not None: + print(f"connection string: {connection_string}") + configure_azure_monitor(connection_string=connection_string) else: config_otel() with open(file_path, "r") as stream: