Skip to content

Commit 0ad57db

Browse files
committed
Assert the derived log stream and clean up test log destinations on success
Log validation scanned every stream in the group and passed if any one of them matched. That grew with each new VM writing to the shared group, and it could not tell a routing bug from a delivery failure -- a stream named wrongly was simply skipped. The agent derives the stream as {host.id}/{service.name}, both of which the test already knows, so it now asserts that exact name and the check covers routing as well as delivery. Both suites now also remove the log destination they created, but only when validation passed, so a failing run leaves its logs behind as evidence. The VM deletes just its own stream because /aws/cwagent/otlp is shared across runs; the AKS group name carries the per-run cluster, so the whole group goes. Neither touches aws/spans, which is service-managed and shared with other suites. The VM role gains logs:DeleteLogStream since that test runs on the VM under it. The AKS test runs on the runner under the runner's own credentials.
1 parent ff14957 commit 0ad57db

3 files changed

Lines changed: 32 additions & 20 deletions

File tree

terraform/azure/vm/iam.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ data "aws_iam_policy_document" "cwagent_permissions" {
6767
"cloudwatch:ListMetrics",
6868
"cloudwatch:GetMetricData",
6969
"logs:GetLogEvents",
70+
# Cleanup: the test deletes its own stream from the shared /aws/cwagent/otlp group when it finishes.
71+
"logs:DeleteLogStream",
7072
# StartQuery/GetQueryResults validate OTLP trace delivery via the aws/spans log group. That group
7173
# is only populated where the X-Ray trace segment destination is set to CloudWatchLogs, which is a
7274
# per-region setting -- hence the region default in variables.tf.

test/azure/aks/aks_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,13 @@ func validateLogs() status.TestResult {
8282
// where the agent's identity transform fills service.namespace from k8s.namespace.name.
8383
// AssertLogsNotEmpty guards against a vacuous pass on an empty window.
8484
logGroup := fmt.Sprintf("/aws/cwagent/%s/otlp", env.AKSClusterName)
85+
// Clean up only on success: the group name carries this run's cluster so the whole group is
86+
// disposable, but on failure it is left in place as evidence for whoever debugs the run.
87+
defer func() {
88+
if testResult.Status == status.SUCCESSFUL {
89+
awsservice.DeleteLogGroup(logGroup)
90+
}
91+
}()
8592
logStream := fmt.Sprintf("amazon-cloudwatch/amazon-cloudwatch/%s", serviceName)
8693
marker := fmt.Sprintf("aks_otlp_log_%s", env.AKSClusterName)
8794
const maxRetries = 4

test/azure/vm/azurevm_test.go

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -118,36 +118,39 @@ func TestAzureVM(t *testing.T) {
118118

119119
func measuredMetrics() []string { return []string{"azurevm_otlp_counter", "azurevm_otlp_gauge"} }
120120

121-
// validateLogs confirms the OTLP log record landed in the default:otel log group for this host.
121+
// validateLogs confirms the OTLP log record landed in the default:otel log group on the stream the
122+
// agent's log routing is expected to derive for this host.
122123
func validateLogs() status.TestResult {
123124
testResult := status.TestResult{Name: "AzureVM_Logs", Status: status.FAILED}
124125

125-
// Retry on the same schedule as the AKS log path: the stream and its events can both lag the
126-
// load window, so a single attempt fails on ingestion delay rather than on delivery.
126+
// The agent routes OTLP logs to {host.id}/{service.name}, so assert that exact stream: it makes the
127+
// check prove log routing rather than just delivery, and keeps cost flat as the shared group
128+
// accumulates a stream per VM. Retries match the AKS path, since the stream and events both lag.
129+
logStream := fmt.Sprintf("%s/%s", env.InstanceId, serviceName)
130+
// Clean up only on success: the group is shared by every VM run, so drop this run's stream but never
131+
// the group. On failure the stream is left in place as evidence for whoever debugs the run.
132+
defer func() {
133+
if testResult.Status == status.SUCCESSFUL {
134+
awsservice.DeleteLogStream(otlpLogGroup, logStream)
135+
}
136+
}()
127137
marker := fmt.Sprintf("azurevm_otlp_log_%s", env.InstanceId)
128138
const maxRetries = 4
129139
const retryInterval = 30 * time.Second
130140
for attempt := 1; attempt <= maxRetries; attempt++ {
131141
since := time.Now().Add(-loadWindow - time.Minute)
132142
until := time.Now()
133-
134-
streams := awsservice.GetLogStreams(otlpLogGroup)
135-
if len(streams) == 0 {
136-
testResult.Reason = fmt.Errorf("attempt %d: no log streams found in %s", attempt, otlpLogGroup)
137-
}
138-
for _, stream := range streams {
139-
log.Printf("[AzureVM_Logs] attempt %d: checking %s/%s", attempt, otlpLogGroup, *stream.LogStreamName)
140-
err := awsservice.ValidateLogs(
141-
otlpLogGroup, *stream.LogStreamName, &since, &until,
142-
awsservice.AssertLogsNotEmpty(),
143-
awsservice.AssertPerLog(awsservice.AssertLogContainsSubstring(marker)),
144-
)
145-
if err == nil {
146-
testResult.Status = status.SUCCESSFUL
147-
return testResult
148-
}
149-
testResult.Reason = err
143+
log.Printf("[AzureVM_Logs] attempt %d: checking %s/%s", attempt, otlpLogGroup, logStream)
144+
err := awsservice.ValidateLogs(
145+
otlpLogGroup, logStream, &since, &until,
146+
awsservice.AssertLogsNotEmpty(),
147+
awsservice.AssertPerLog(awsservice.AssertLogContainsSubstring(marker)),
148+
)
149+
if err == nil {
150+
testResult.Status = status.SUCCESSFUL
151+
return testResult
150152
}
153+
testResult.Reason = err
151154
if attempt < maxRetries {
152155
log.Printf("[AzureVM_Logs] %v — retrying in %v", testResult.Reason, retryInterval)
153156
time.Sleep(retryInterval)

0 commit comments

Comments
 (0)