Skip to content

Commit 1839598

Browse files
test(logs): add e2e IIS log separation
The unit pipeline test constructs the preprocessor directly, so a wiring or config regression can concatenate IIS W3C records while that test stays green. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 321ee41 commit 1839598

2 files changed

Lines changed: 66 additions & 6 deletions

File tree

test/new-e2e/tests/agent-log-pipelines/linux-log/file-tailing/config/config.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,8 @@ logs:
33
path: '/var/log/e2e_test_logs/hello-world.log'
44
service: hello
55
source: custom_log
6+
- type: file
7+
path: '/var/log/e2e_test_logs/iis-w3c.log'
8+
service: iis-w3c
9+
source: iis
10+
auto_multi_line_detection: true

test/new-e2e/tests/agent-log-pipelines/linux-log/file-tailing/file_tailing_test.go

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,23 @@ var logConfig string
3737
const (
3838
logFileName = "hello-world.log"
3939
logFilePath = utils.LinuxLogsFolderPath + "/" + logFileName
40+
41+
iisLogFileName = "iis-w3c.log"
42+
iisLogFilePath = utils.LinuxLogsFolderPath + "/" + iisLogFileName
43+
iisService = "iis-w3c"
44+
// Distinctive substrings from consecutive IIS W3C records. A concatenated
45+
// intake message contains both.
46+
iisGetToken = "GET /ZenIT/Service/v13/core/Consent"
47+
iisPostToken = "POST /ZenIT/Service/v13/core/Logger"
4048
)
4149

50+
// iisW3CRecords is a timestamped #Date header plus two 10.1.48.10 records.
51+
// CombiningAggregator only concatenates aggregate lines onto an open
52+
// startGroup, so the header is required to reproduce the regression.
53+
const iisW3CRecords = `#Date: 2026-08-11 10:34:49
54+
2026-08-11 10:34:49 W3SVC1 10.1.48.10 GET /ZenIT/Service/v13/core/Consent land=DE 443 ndl\SVC-Zenit-NDL0167 10.1.48.122 Mozilla/5.0 200 0 0 19571 1051
55+
2026-08-11 10:34:50 W3SVC1 10.1.48.10 POST /ZenIT/Service/v13/core/Logger - 443 ndl\SVC-Zenit-NDL0167 10.1.48.122 Mozilla/5.0 204 0 0 504 6`
56+
4257
// TestLinuxVMFileTailingSuite runs the E2E test suite for the log agent with a Linux VM and fake intake.
4358
func TestLinuxVMFileTailingSuite(t *testing.T) {
4459
options := []e2e.SuiteOption{
@@ -61,12 +76,13 @@ func (s *LinuxFakeintakeSuite) BeforeTest(suiteName, testName string) {
6176

6277
// Ensure no logs are present in fakeintake before testing starts
6378
s.EventuallyWithT(func(c *assert.CollectT) {
64-
logs, err := s.Env().FakeIntake.Client().FilterLogs("hello")
65-
require.NoError(c, err, "Unable to filter logs by the service 'hello'.")
66-
// If logs are found, print their content for debugging
67-
if !assert.Empty(c, logs, "Logs were found when none were expected.") {
68-
cat, _ := s.Env().RemoteHost.Execute(fmt.Sprintf("cat %s && cat %s/hello-world-2.log", logFilePath, utils.LinuxLogsFolderPath))
69-
s.T().Logf("Logs detected when none were expected: %v", cat)
79+
for _, service := range []string{"hello", iisService} {
80+
logs, err := s.Env().FakeIntake.Client().FilterLogs(service)
81+
require.NoError(c, err, "Unable to filter logs by the service '%s'.", service)
82+
if !assert.Empty(c, logs, "Logs were found for service '%s' when none were expected.", service) {
83+
cat, _ := s.Env().RemoteHost.Execute(fmt.Sprintf("cat %s %s %s/hello-world-2.log 2>/dev/null || true", logFilePath, iisLogFilePath, utils.LinuxLogsFolderPath))
84+
s.T().Logf("Logs detected when none were expected: %v", cat)
85+
}
7086
}
7187
}, 2*time.Minute, 10*time.Second)
7288

@@ -226,3 +242,42 @@ func (s *LinuxFakeintakeSuite) testLogRecreateRotation() {
226242
// Check intake for new logs
227243
utils.CheckLogsExpected(s.T(), s.Env().FakeIntake, "hello", "hello-world-new-content", []string{})
228244
}
245+
246+
// TestIISW3CRecordsStaySeparate writes consecutive IIS W3C records through
247+
// file tailing with auto multiline enabled and asserts fakeintake receives
248+
// them as separate messages. The unit pipeline test constructs the
249+
// preprocessor directly and cannot catch a wiring or config regression.
250+
func (s *LinuxFakeintakeSuite) TestIISW3CRecordsStaySeparate() {
251+
t := s.T()
252+
253+
s.Env().RemoteHost.MustExecute("sudo touch " + iisLogFilePath)
254+
output, err := s.Env().RemoteHost.Execute(fmt.Sprintf("sudo chmod +r %s && echo true", iisLogFilePath))
255+
require.NoError(t, err, "Unable to adjust permissions for the log file '%s'.", iisLogFilePath)
256+
require.Equal(t, "true", strings.TrimSpace(output), "Unable to adjust permissions for the log file '%s'.", iisLogFilePath)
257+
258+
utils.AssertAgentTailerOK(s, iisLogFileName)
259+
utils.AppendLog(s, iisLogFileName, iisW3CRecords, 1)
260+
261+
s.EventuallyWithT(func(c *assert.CollectT) {
262+
logs, err := s.Env().FakeIntake.Client().FilterLogs(iisService)
263+
require.NoError(c, err, "Unable to filter logs by the service '%s'.", iisService)
264+
265+
var getOnly, postOnly, combined int
266+
for _, log := range logs {
267+
hasGet := strings.Contains(log.Message, iisGetToken)
268+
hasPost := strings.Contains(log.Message, iisPostToken)
269+
switch {
270+
case hasGet && hasPost:
271+
combined++
272+
case hasGet:
273+
getOnly++
274+
case hasPost:
275+
postOnly++
276+
}
277+
}
278+
279+
require.GreaterOrEqual(c, getOnly, 1, "GET IIS record was not received as its own message; got %d logs for service %s", len(logs), iisService)
280+
require.GreaterOrEqual(c, postOnly, 1, "POST IIS record was not received as its own message; got %d logs for service %s", len(logs), iisService)
281+
assert.Zero(c, combined, "GET and POST IIS records were concatenated into one intake message")
282+
}, 2*time.Minute, 10*time.Second)
283+
}

0 commit comments

Comments
 (0)