Skip to content
Merged
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
4 changes: 3 additions & 1 deletion agentops-cli/src/commands/product.js
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,10 @@ function productAudit(options = {}) {
'azure-ingest-privacy-plan',
fileIncludes('agentops-cli/src/lib/azure/v2-ingest-plan.js', ['--allow-content', 'AgentOpsContent_CL', 'schema_versioning', 'schema_migration_policy', 'logs-ingestion-upload-plan'])
&& fileIncludes('agentops-cli/src/commands/azure-ingest.js', ['logs-upload', '--yes', 'az', 'rest'])
&& fileIncludes('infra/bicep/v2-ingestion.bicep', ['AgentOpsRunSummary_CL', 'dataCollectionRules', 'streamDeclarations', 'logsIngestionEndpoint'])
&& fileIncludes('infra/bicep/main.bicep', ['deployV2Ingestion', 'AGENTOPS_LOGS_INGESTION_ENDPOINT', 'AGENTOPS_DCR_IMMUTABLE_ID'])
&& fileIncludes('docs/azure-v2-ingestion.md', ['AgentOpsContent_CL', '--allow-content', 'SchemaVersion', 'schema migration policy', 'azure-ingest logs-upload']),
['agentops-cli/src/lib/azure/v2-ingest-plan.js', 'agentops-cli/src/commands/azure-ingest.js', 'docs/azure-v2-ingestion.md'],
['agentops-cli/src/lib/azure/v2-ingest-plan.js', 'agentops-cli/src/commands/azure-ingest.js', 'infra/bicep/v2-ingestion.bicep', 'infra/bicep/main.bicep', 'docs/azure-v2-ingestion.md'],
[]
));

Expand Down
25 changes: 20 additions & 5 deletions docs/azure-v2-ingestion.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,25 @@ It does not create Azure resources or upload data. For metadata-only saved-view,

Use Azure Monitor Logs Ingestion API with a Data Collection Rule:

1. Create one custom Log Analytics table per `AgentOps*_CL` table.
2. Create one DCR stream per table using the columns reported by `agentops azure-ingest plan`.
3. Send each JSONL row to the matching DCR stream.
4. Import the V2 dashboard pack from `grafana/dashboards/v2/`.
1. Deploy the optional V2 ingestion infrastructure:

```bash
az deployment group create \
--resource-group <rg> \
--template-file infra/bicep/main.bicep \
--parameters deployV2Ingestion=true
```

2. Export the deployment outputs:

```bash
export AGENTOPS_LOGS_INGESTION_ENDPOINT="<AGENTOPS_LOGS_INGESTION_ENDPOINT output>"
export AGENTOPS_DCR_IMMUTABLE_ID="<AGENTOPS_DCR_IMMUTABLE_ID output>"
```

3. Confirm one custom Log Analytics table per `AgentOps*_CL` table and one DCR stream per table exist.
4. Send each JSONL row to the matching DCR stream.
5. Import the V2 dashboard pack from `grafana/dashboards/v2/`.

`azure-ingest logs-upload` turns the reviewed plan into Azure Monitor Logs Ingestion API calls. It is dry-run by default and requires `--yes` before it runs `az rest`:

Expand Down Expand Up @@ -72,7 +87,7 @@ agentops azure-ingest upload-plan \
--container agentops-shared \
--prefix team-a/latest
```
5. Run `agentops validate-azure --last 24h`.
Run `agentops validate-azure --last 24h` after sharing artifacts.

The dashboards never require raw prompts, responses, file contents, tool arguments, or tool results. If you intentionally enable content capture, keep it in `AgentOpsContent_CL`, use `agentops azure-ingest plan --allow-content`, and expose it only through a separate, access-controlled workspace/dashboard.

Expand Down
20 changes: 20 additions & 0 deletions infra/bicep/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ param actionerAssistantUrl string = ''
@description('Deploy shared Azure Blob storage for metadata-only saved-view and recommendation exports.')
param deploySharedStore bool = false

@description('Deploy AgentOps V2 custom tables plus Data Collection Endpoint/Rule for Logs Ingestion API uploads.')
param deployV2Ingestion bool = false

@allowed([
'Enabled'
'Disabled'
Expand Down Expand Up @@ -186,6 +189,18 @@ module sharedStore 'shared-store.bicep' = if (deploySharedStore) {
}
}

module v2Ingestion 'v2-ingestion.bicep' = if (deployV2Ingestion) {
name: 'v2-ingestion'
params: {
location: location
workspaceName: logAnalytics.outputs.name
baseName: baseName
environmentName: environmentName
retentionInDays: effectiveLogRetentionDays
tags: tags
}
}

resource sharedStoreAccount 'Microsoft.Storage/storageAccounts@2023-01-01' existing = if (deployActioner && deploySharedStore) {
name: sharedStoreName
}
Expand Down Expand Up @@ -257,3 +272,8 @@ output SHARED_STORE_ACCOUNT_NAME string = deploySharedStore ? sharedStore!.outpu
output SHARED_STORE_BLOB_ENDPOINT string = deploySharedStore ? sharedStore!.outputs.blobEndpoint : ''
output SHARED_STORE_CONTAINER_NAME string = deploySharedStore ? sharedStore!.outputs.containerName : ''
output SHARED_STORE_RESOURCE_ID string = deploySharedStore ? sharedStore!.outputs.resourceId : ''
output V2_INGESTION_DEPLOYED bool = deployV2Ingestion
output AGENTOPS_LOGS_INGESTION_ENDPOINT string = deployV2Ingestion ? v2Ingestion!.outputs.logsIngestionEndpoint : ''
output AGENTOPS_DCR_IMMUTABLE_ID string = deployV2Ingestion ? v2Ingestion!.outputs.dataCollectionRuleImmutableId : ''
output AGENTOPS_DCR_RESOURCE_ID string = deployV2Ingestion ? v2Ingestion!.outputs.dataCollectionRuleResourceId : ''
output AGENTOPS_V2_TABLE_COUNT int = deployV2Ingestion ? v2Ingestion!.outputs.tableCount : 0
Loading
Loading