Skip to content

Commit 70c769a

Browse files
authored
Merge pull request #49 from alphagov/pp-14099/handle-transforming-adot-logs
[PP-14099]: Handle transforming ADOT logs
2 parents 395f66e + 4d53d82 commit 70c769a

File tree

5 files changed

+89
-0
lines changed

5 files changed

+89
-0
lines changed

spec/fixtures/adot_fixtures.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { Fixture } from './general_fixtures'
2+
3+
export const anADOTCloudWatchEvent: Fixture = {
4+
input: {
5+
deliveryStreamArn: 'someDeliveryStreamArn',
6+
invocationId: 'someId',
7+
region: 'eu-west-1',
8+
records: [{
9+
approximateArrivalTimestamp: 1234,
10+
recordId: 'LogEvent-1',
11+
data: Buffer.from(JSON.stringify({
12+
owner: '223851549868',
13+
logGroup: 'test-12_adot_frontend',
14+
logStream: 'logStream',
15+
subscriptionFilters: [],
16+
messageType: 'DATA_MESSAGE',
17+
logEvents: [
18+
{
19+
id: 'cloudwatch-log-message-id-1',
20+
timestamp: 1234,
21+
message: '2025/05/28 10:13:36 ADOT Collector version: v0.43.3'
22+
},
23+
{
24+
id: 'cloudwatch-log-gmessage-id-2',
25+
timestamp: 1235,
26+
message: '2025-05-28T10:13:36.838Z warn awsemfexporter@v0.117.0/emf_exporter.go:92 the default value for DimensionRollupOption will be changing to NoDimensionRollupin a future release. See https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/23997 for moreinformation {"kind": "exporter", "data_type": "metrics", "name": "awsemf"}'
27+
}
28+
]
29+
})).toString('base64')
30+
}]
31+
},
32+
expected: {
33+
records: [{
34+
result: 'Ok',
35+
recordId: 'LogEvent-1',
36+
data: Buffer.from([
37+
{
38+
host: 'logStream',
39+
source: 'adot',
40+
sourcetype: 'generic_single_line',
41+
index: 'pay_devops',
42+
event: '2025/05/28 10:13:36 ADOT Collector version: v0.43.3',
43+
fields: {
44+
account: 'test',
45+
environment: 'test-12',
46+
service: 'frontend'
47+
},
48+
time: 1234.000
49+
},
50+
{
51+
host: 'logStream',
52+
source: 'adot',
53+
sourcetype: 'generic_single_line',
54+
index: 'pay_devops',
55+
event: '2025-05-28T10:13:36.838Z warn awsemfexporter@v0.117.0/emf_exporter.go:92 the default value for DimensionRollupOption will be changing to NoDimensionRollupin a future release. See https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/23997 for moreinformation {"kind": "exporter", "data_type": "metrics", "name": "awsemf"}',
56+
fields: {
57+
account: 'test',
58+
environment: 'test-12',
59+
service: 'frontend'
60+
},
61+
time: 1235.000
62+
}
63+
].map(x => JSON.stringify(x)).join('\n')).toString('base64')
64+
}]
65+
}
66+
}

spec/index.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import {
66
anInvalidApplicationLogFirehoseTransformationEventRecord
77
} from './fixtures/application_fixtures'
88

9+
import {
10+
anADOTCloudWatchEvent
11+
} from './fixtures/adot_fixtures'
12+
913
import {
1014
aBastionLogCloudWatchEvent
1115
} from './fixtures/bastion_fixtures'
@@ -81,6 +85,16 @@ describe('Processing CloudWatchLogEvents', () => {
8185
expect(Buffer.from(result.records[1].data as string, 'base64').toString()).toEqual(Buffer.from(expectedSecondRecord.data as string, 'base64').toString())
8286
})
8387
})
88+
describe('From ADOT', () => {
89+
test('should transform adot logs from CloudWatch', async () => {
90+
const result = await handler(anADOTCloudWatchEvent.input, mockContext, mockCallback) as FirehoseTransformationResult
91+
92+
const expectedRecord = anADOTCloudWatchEvent.expected.records[0]
93+
expect(result.records[0].result).toEqual(expectedRecord.result)
94+
expect(result.records[0].recordId).toEqual(expectedRecord.recordId)
95+
expect(Buffer.from(result.records[0].data as string, 'base64').toString()).toEqual(Buffer.from(expectedRecord.data as string, 'base64').toString())
96+
})
97+
})
8498
describe('From Bastion', () => {
8599
test('should transform bastion logs from CloudWatch', async () => {
86100
const result = await handler(aBastionLogCloudWatchEvent.input, mockContext, mockCallback) as FirehoseTransformationResult

src/extractTime.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ export function parseTimeFromLog(log: string, logType: CloudWatchLogTypes): numb
153153
switch (logType) {
154154
case CloudWatchLogTypes.app:
155155
return extractAppLogTime(log)
156+
case CloudWatchLogTypes.adot:
157+
// Adot has many different time formats, so we'll rely on the cloudwatch timestamp instead
158+
return undefined
156159
case CloudWatchLogTypes.bastion:
157160
return extractBastionLogTime(log)
158161
case CloudWatchLogTypes.squid:

src/transformData.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ function sourceTypeFromLogGroup(logType: CloudWatchLogTypes, msg: string): strin
152152
switch (logType) {
153153
case CloudWatchLogTypes.app:
154154
return 'ST004:application_json'
155+
case CloudWatchLogTypes.adot:
156+
// ADOT has logs in many formats, so better to just set a geenric source type
157+
return 'generic_single_line'
155158
case CloudWatchLogTypes.bastion:
156159
return 'linux_bastion'
157160
case CloudWatchLogTypes['nginx-forward-proxy']:
@@ -184,6 +187,8 @@ function indexFromLogType(logType: CloudWatchLogTypes): string {
184187
switch (logType) {
185188
case CloudWatchLogTypes.app:
186189
return 'pay_application'
190+
case CloudWatchLogTypes.adot:
191+
return 'pay_devops'
187192
case CloudWatchLogTypes.bastion:
188193
return 'pay_host'
189194
case CloudWatchLogTypes['nginx-forward-proxy']:

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export type EnvVars = {
3737
}
3838

3939
export enum CloudWatchLogTypes {
40+
'adot',
4041
'app',
4142
'apt',
4243
'audit',

0 commit comments

Comments
 (0)