Component
OpenTelemetry.Instrumentation.AWSLambda
Is your feature request related to a problem?
GetFaasTrigger classifies HTTP triggers as http and, SQS/SNS triggers as pubsub. Every other event source still reportsfaas.trigger = other, including S3.
A function triggered by an S3 object event is responding to a data source operation, which the conventions describe as the datasource trigger type. The conventions name S3 explicitly in the attribute definitions:
faas.document.collection:
"The name of the source on which the triggering operation was performed. For example, in Cloud Storage or S3 corresponds to the bucket name"
faas.document.name:
"The document name/table subjected to the operation. For example, in Cloud Storage or S3 is the name of the file"
So S3 is not an inferred fit for datasource — it is one of the two examples the specification was written around, and it currently reports other.
What is the expected behavior?
Report faas.trigger = datasource for S3 events, together with the faas.document.* attributes the conventions require.
Only datasource is not satisfied by setting faas.trigger alone. The Datasource section
requires:
| Attribute |
Requirement level |
faas.document.collection |
Required |
faas.document.operation |
Required |
faas.document.name |
Recommended |
faas.document.time |
Recommended |
Setting faas.trigger = datasource without the two required attributes would be less conformant than the current other, so the attributes have to be part of the same change.
S3 maps completely. Every attribute has a real property on S3Event.S3EventNotificationRecord :
| Attribute |
Source |
Type |
faas.document.collection |
S3.Bucket.Name |
string |
faas.document.name |
S3.Object.Key |
string |
faas.document.operation |
EventName, mapped below |
string |
faas.document.time |
EventTime |
DateTime |
Both Required attributes come from real properties, which is what makes S3 implementable today: collection is S3.Bucket.Name directly, and operation is derived from EventName. Note that faas.document.time is typed as a string in the conventions while EventTime is a DateTime, so it would be formatted as ISO 8601 with an invariant culture rather than via a default ToString().
Batching is not a problem for S3. The S3 documentation states that "Amazon S3 event notifications send one event entry for each notification message", and S3 invokes Lambda by asynchronous push rather than through a polled event source mapping. So an S3Event normally carries a single record, and the per-record faas.document.* attributes describe the invocation unambiguously.
Trigger detection mirrors the merged pubsub change and stays small:
private static bool IsDatasourceRequest<TInput>(TInput input) =>
input is S3Event or S3Event.S3EventNotificationRecord;
private static string GetFaasTrigger<TInput>(TInput input)
{
if (IsHttpRequest(input))
{
return "http";
}
if (IsPubSubRequest(input))
{
return "pubsub";
}
return IsDatasourceRequest(input) ? "datasource" : "other";
}
The record-level type is included for the same reason #5146 included SQSEvent.SQSMessage and SNSEvent.SNSRecord: a handler may take an individual record, and GetFaasTrigger should classify it consistently with the batch type.
Which alternative solutions or features have you considered?
Emitting faas.trigger = datasource on its own, without the faas.document.* attributes. This would be a one-line change, but faas.document.collection and faas.document.operation are Required for the
datasource trigger, so the result would be a span that declares itself a datasource invocation and then omits two required attributes. That is arguably worse than the current other, which claims nothing. Rejected.
Leaving S3 as other. Defensible in the sense that nothing is broken today, but other is specified as "if none of the others apply", and datasource demonstrably does apply — the conventions name S3 in the attribute descriptions. Consumers filtering on faas.trigger = datasource to find data-driven invocations silently miss all S3 Lambda spans.
Avoiding the new package dependency by duck typing on the input's type name (input.GetType().FullName == "Amazon.Lambda.S3Events.S3Event") instead of referencing Amazon.Lambda.S3Events. This keeps the dependency footprint unchanged, but reads the bucket and key by reflection or dynamic, which is fragile, harder to unit test, and works against IsAotCompatible=true.
Deriving the attributes in the user's handler rather than the instrumentation. Possible today with Activity.Current?.SetTag(...), but it pushes convention knowledge onto every consumer and would not be consistent across SDKs. This is the kind of mapping the instrumentation exists to do.
Additional context
1. Is a new package dependency on Amazon.Lambda.S3Events acceptable?
This is the only hard blocker. The project currently references Amazon.Lambda.APIGatewayEvents, Amazon.Lambda.ApplicationLoadBalancerEvents, Amazon.Lambda.Core, Amazon.Lambda.SNSEvents and Amazon.Lambda.SQSEvents. Adding Amazon.Lambda.S3Events means a new dependency for every consumer of this package, including those with no S3 triggers, and the project sets IsAotCompatible=true, so the trimming impact would need checking.
2. How should faas.document.operation handle S3's event types?
faas.document.operation has well-known values insert, edit and delete, and the registry states that if one of them applies "then the respective value MUST be used; otherwise, a custom value MAY be used".
S3 sends composite event names, so the mapping has to key off the family prefix before : rather than the whole value. S3 publishes eleven event-type families, of which only two map to a well-known value:
Amazon S3 API Reference:
| S3 event family |
Well-known value |
ObjectCreated:Put, :Post, :Copy, :CompleteMultipartUpload |
insert |
ObjectRemoved:Delete, :DeleteMarkerCreated |
delete |
LifecycleExpiration:Delete, :DeleteMarkerCreated |
delete? — see below |
ObjectRestore:*, LifecycleTransition, IntelligentTiering, ObjectTagging:*, ObjectAnnotation:*, ObjectAcl:Put, Replication:*, s3:TestEvent |
none applies |
Further notes
The AWS Lambda conventions do not cover S3. The AWS Lambda page has specific sections for API Gateway and SQS but none for S3, so only the generic FaaS Datasource section applies. Given that section names S3 directly? may be we would rather need a clarificationraised in semantic-conventions first ?
All four faas.document.* attributes are Development stability, consistent with the other experimental FaaS attributes this instrumentation already emits.
Tip
React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.
Component
OpenTelemetry.Instrumentation.AWSLambda
Is your feature request related to a problem?
GetFaasTriggerclassifies HTTP triggers ashttpand, SQS/SNS triggers aspubsub. Every other event source still reportsfaas.trigger = other, including S3.A function triggered by an S3 object event is responding to a data source operation, which the conventions describe as the
datasourcetrigger type. The conventions name S3 explicitly in the attribute definitions:faas.document.collection:"The name of the source on which the triggering operation was performed. For example, in Cloud Storage or S3 corresponds to the bucket name"
faas.document.name:"The document name/table subjected to the operation. For example, in Cloud Storage or S3 is the name of the file"
So S3 is not an inferred fit for
datasource— it is one of the two examples the specification was written around, and it currently reportsother.What is the expected behavior?
Report
faas.trigger = datasourcefor S3 events, together with thefaas.document.*attributes the conventions require.Only
datasourceis not satisfied by settingfaas.triggeralone. The Datasource sectionrequires:
faas.document.collectionfaas.document.operationfaas.document.namefaas.document.timeSetting
faas.trigger = datasourcewithout the two required attributes would be less conformant than the currentother, so the attributes have to be part of the same change.S3 maps completely. Every attribute has a real property on S3Event.S3EventNotificationRecord :
faas.document.collectionS3.Bucket.Namestringfaas.document.nameS3.Object.Keystringfaas.document.operationEventName, mapped belowstringfaas.document.timeEventTimeDateTimeBoth Required attributes come from real properties, which is what makes S3 implementable today:
collectionisS3.Bucket.Namedirectly, andoperationis derived fromEventName. Note thatfaas.document.timeis typed as a string in the conventions whileEventTimeis aDateTime, so it would be formatted as ISO 8601 with an invariant culture rather than via a defaultToString().Batching is not a problem for S3. The S3 documentation states that "Amazon S3 event notifications send one event entry for each notification message", and S3 invokes Lambda by asynchronous push rather than through a polled event source mapping. So an
S3Eventnormally carries a single record, and the per-recordfaas.document.*attributes describe the invocation unambiguously.Trigger detection mirrors the merged
pubsubchange and stays small:The record-level type is included for the same reason #5146 included
SQSEvent.SQSMessageandSNSEvent.SNSRecord: a handler may take an individual record, andGetFaasTriggershould classify it consistently with the batch type.Which alternative solutions or features have you considered?
Emitting
faas.trigger = datasourceon its own, without thefaas.document.*attributes. This would be a one-line change, butfaas.document.collectionandfaas.document.operationare Required for thedatasource trigger, so the result would be a span that declares itself a datasource invocation and then omits two required attributes. That is arguably worse than the current
other, which claims nothing. Rejected.Leaving S3 as
other. Defensible in the sense that nothing is broken today, butotheris specified as "if none of the others apply", anddatasourcedemonstrably does apply — the conventions name S3 in the attribute descriptions. Consumers filtering onfaas.trigger = datasourceto find data-driven invocations silently miss all S3 Lambda spans.Avoiding the new package dependency by duck typing on the input's type name (
input.GetType().FullName == "Amazon.Lambda.S3Events.S3Event") instead of referencingAmazon.Lambda.S3Events. This keeps the dependency footprint unchanged, but reads the bucket and key by reflection ordynamic, which is fragile, harder to unit test, and works againstIsAotCompatible=true.Deriving the attributes in the user's handler rather than the instrumentation. Possible today with
Activity.Current?.SetTag(...), but it pushes convention knowledge onto every consumer and would not be consistent across SDKs. This is the kind of mapping the instrumentation exists to do.Additional context
1. Is a new package dependency on
Amazon.Lambda.S3Eventsacceptable?This is the only hard blocker. The project currently references
Amazon.Lambda.APIGatewayEvents,Amazon.Lambda.ApplicationLoadBalancerEvents,Amazon.Lambda.Core,Amazon.Lambda.SNSEventsandAmazon.Lambda.SQSEvents. AddingAmazon.Lambda.S3Eventsmeans a new dependency for every consumer of this package, including those with no S3 triggers, and the project setsIsAotCompatible=true, so the trimming impact would need checking.2. How should
faas.document.operationhandle S3's event types?faas.document.operationhas well-known valuesinsert,editanddelete, and the registry states that if one of them applies "then the respective value MUST be used; otherwise, a custom value MAY be used".S3 sends composite event names, so the mapping has to key off the family prefix before
:rather than the whole value. S3 publishes eleven event-type families, of which only two map to a well-known value:Amazon S3 API Reference:
ObjectCreated:Put,:Post,:Copy,:CompleteMultipartUploadinsertObjectRemoved:Delete,:DeleteMarkerCreateddeleteLifecycleExpiration:Delete,:DeleteMarkerCreateddelete? — see belowObjectRestore:*,LifecycleTransition,IntelligentTiering,ObjectTagging:*,ObjectAnnotation:*,ObjectAcl:Put,Replication:*,s3:TestEventFurther notes
The AWS Lambda conventions do not cover S3. The AWS Lambda page has specific sections for API Gateway and SQS but none for S3, so only the generic FaaS Datasource section applies. Given that section names S3 directly? may be we would rather need a clarificationraised in
semantic-conventionsfirst ?All four
faas.document.*attributes are Development stability, consistent with the other experimental FaaS attributes this instrumentation already emits.Tip
React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding
+1orme too, to help us triage it. Learn more here.