(aws-events-targets): LogGroupTargetInput.fromObjectV2 doesn't support mixing static and dynamic fields in message
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the feature
When using `CloudWatchLogGroup` as an EventBridge rule target with `LogGroupTargetInput.fromObjectV2()`, there's no way to create structured log messages that mix static string values with dynamic `EventField.fromPath()` values. This limitation makes it difficult to add context (like log levels or static messages) to events being logged.
### Use Case
I should be able to create structured log messages that include both:
- Static fields like `"level": "ERROR"`
- Dynamic fields from the event like `EventField.fromPath("$.detail.taskArn")`
Something like:
```typescript
LogGroupTargetInput.fromObjectV2({
timestamp: EventField.fromPath("$.time"),
message: {
level: "ERROR", // Static field
message: "Task failed", // Static field
taskArn: EventField.fromPath("$.detail.taskArn"), // Dynamic field
clusterArn: EventField.fromPath("$.detail.clusterArn"), // Dynamic field
}
})
```
However, today, the `LogGroupTargetInputOptions` interface only supports two fields:
```typescript
export interface LogGroupTargetInputOptions {
readonly timestamp?: any;
readonly message?: any;
}
```
This means:
1. The `message` field must be a flat string or single `EventField`, not a structured object
2. There's no way to add additional fields at the top level (like `level`)
3. The validation in `CloudWatchLogGroup` enforces exactly `{timestamp, message}` format
You can see this with this simple repro:
```typescript
import { Rule, EventField } from 'aws-cdk-lib/aws-events';
import { CloudWatchLogGroup, LogGroupTargetInput } from 'aws-cdk-lib/aws-events-targets';
import * as logs from 'aws-cdk-lib/aws-logs';
const rule = new Rule(this, 'MyRule', {
eventPattern: {
source: ['aws.ecs'],
detailType: ['ECS Task State Change'],
},
});
const logGroup = new logs.LogGroup(this, 'MyLogGroup');
// This doesn't work - can't add 'level' or mix static/dynamic in message
rule.addTarget(new CloudWatchLogGroup(logGroup, {
logEvent: LogGroupTargetInput.fromObjectV2({
timestamp: EventField.fromPath("$.time"),
message: // ??? No good option here for structured logging
}),
}));
```
**Attempted workarounds:**
1. Using `JSON.stringify()` - doesn't work because `EventField` objects don't serialize
2. Using array `.join("")` - doesn't work because `EventField` objects can't be concatenated
3. Using template literals - doesn't work because `EventField` objects aren't strings
4. Using the deprecated `event` property with `RuleTargetInput.fromObject()` - gets validation errors
### Proposed Solution
Option 1: Extend `LogGroupTargetInputOptions` to support structured messages:
```typescript
export interface LogGroupTargetInputOptions {
readonly timestamp?: any;
readonly message?: any;
readonly additionalFields?: Record; // NEW
}
```
Option 2: Allow `message` to be an object with mixed static/dynamic fields, similar to how `RuleTargetInput.fromObject()` works:
```typescript
LogGroupTargetInput.fromObjectV2({
timestamp: EventField.fromPath("$.time"),
message: {
level: "ERROR",
taskArn: EventField.fromPath("$.detail.taskArn"),
}
})
```
Option 3: Relax the validation in `CloudWatchLogGroup.validateInputTemplate()` to allow additional fields beyond just `timestamp` and `message`.
### Other Information
## Workaround
Currently, the only way to achieve this is to create a custom class that extends `LogGroupTargetInput` and bypasses CDK validation:
```typescript
class CustomLogGroupTargetInput extends LogGroupTargetInput {
constructor(
private readonly inputPathsMap: Record,
private readonly inputTemplate: string,
) {
super();
}
bind(_rule: IRule): RuleTargetInputProperties {
return {
inputPathsMap: this.inputPathsMap,
inputTemplate: this.inputTemplate,
};
}
}
// Usage:
rule.addTarget(
new CloudWatchLogGroup(logGroup, {
logEvent: new CustomLogGroupTargetInput(
{
"detail-taskArn": "$.detail.taskArn",
"time": "$.time",
},
'{"timestamp":
This works but bypasses type safety and CDK's abstraction.
### Acknowledgements
- [ ] I may be able to implement this feature request
- [ ] This feature might incur a breaking change
### AWS CDK Library version (aws-cdk-lib)
2.199.0
### AWS CDK CLI version
2.1007.0 (build d3f6c3c)
### Environment details (OS name and version, etc.)
MacOS
Contributor guide
Research direction
Start by tracing LogGroupTargetInput.fromObjectV2(), LogGroupTargetInputOptions, and CloudWatchLogGroup.validateInputTemplate() to understand the current timestamp/message shape and EventField handling. Resolve which proposed API shape is intended, then verify that mixed static and dynamic structured messages are accepted and rendered correctly without bypassing validation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, typescript
- Domain
- cloud
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100