Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions openapi/openapiv2.json
Original file line number Diff line number Diff line change
Expand Up @@ -10045,6 +10045,28 @@
}
}
},
"v1Action": {
"type": "object",
"properties": {
"actionCount": {
"type": "integer",
"format": "int32"
}
}
},
"v1ActionMetadata": {
"type": "object",
"properties": {
"actions": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/v1Action"
},
"title": "A history event can be attributed to multiple metering subtypes\nEx. EVENT_TYPE_WORKFLOW_EXECUTION_STARTED, which is used by both Start\nWorkflow Execution and Scheduled Workflow Executions.\ngrpc:StartWorkflowExecution and grpc:StartWorkflowExecution.Scheduled.Adjusted"
}
}
},
"v1ActivityExecutionInfo": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -12461,6 +12483,10 @@
},
"description": "Links associated with the event."
},
"actionMetadata": {
"$ref": "#/definitions/v1ActionMetadata",
"description": "Actions metering metadata for the event."
},
"workflowExecutionStartedEventAttributes": {
"$ref": "#/definitions/v1WorkflowExecutionStartedEventAttributes"
},
Expand Down
22 changes: 22 additions & 0 deletions openapi/openapiv3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7237,6 +7237,24 @@ paths:
$ref: '#/components/schemas/Status'
components:
schemas:
Action:
type: object
properties:
actionCount:
type: integer
format: int32
ActionMetadata:
type: object
properties:
actions:
type: array
items:
$ref: '#/components/schemas/Action'
description: |-
A history event can be attributed to multiple metering subtypes
Ex. EVENT_TYPE_WORKFLOW_EXECUTION_STARTED, which is used by both Start
Workflow Execution and Scheduled Workflow Executions.
grpc:StartWorkflowExecution and grpc:StartWorkflowExecution.Scheduled.Adjusted
ActivityExecutionInfo:
type: object
properties:
Expand Down Expand Up @@ -9707,6 +9725,10 @@ components:
items:
$ref: '#/components/schemas/Link'
description: Links associated with the event.
actionMetadata:
allOf:
- $ref: '#/components/schemas/ActionMetadata'
description: Actions metering metadata for the event.
workflowExecutionStartedEventAttributes:
$ref: '#/components/schemas/WorkflowExecutionStartedEventAttributes'
workflowExecutionCompletedEventAttributes:
Expand Down
5 changes: 4 additions & 1 deletion temporal/api/history/v1/message.proto
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import "temporal/api/update/v1/message.proto";
import "temporal/api/workflow/v1/message.proto";
import "temporal/api/sdk/v1/task_complete_metadata.proto";
import "temporal/api/sdk/v1/user_metadata.proto";
import "temporal/api/server/v1/message.proto";

// Always the first event in workflow history
message WorkflowExecutionStartedEventAttributes {
Expand Down Expand Up @@ -1114,7 +1115,9 @@ message HistoryEvent {
temporal.api.sdk.v1.UserMetadata user_metadata = 301;
// Links associated with the event.
repeated temporal.api.common.v1.Link links = 302;
// The event details. The type must match that in `event_type`.
// Actions metering metadata for the event.
temporal.api.server.v1.ActionMetadata action_metadata = 303;

oneof attributes {
WorkflowExecutionStartedEventAttributes workflow_execution_started_event_attributes = 6;
WorkflowExecutionCompletedEventAttributes workflow_execution_completed_event_attributes = 7;
Expand Down
20 changes: 20 additions & 0 deletions temporal/api/server/v1/message.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
syntax = "proto3";

package temporal.api.server.v1;

option go_package = "go.temporal.io/api/server/v1;server";
option java_package = "io.temporal.api.server.v1";
option java_outer_classname = "MessageProto";
option java_multiple_files = true;

message ActionMetadata {
// A history event can be attributed to multiple metering subtypes
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

metering subtypes actions

// Ex. EVENT_TYPE_WORKFLOW_EXECUTION_STARTED, which is used by both Start
// Workflow Execution and Scheduled Workflow Executions.
// grpc:StartWorkflowExecution and grpc:StartWorkflowExecution.Scheduled.Adjusted
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TO-DO: remove this line

repeated Action actions = 1;
Comment on lines +11 to +15
Copy link
Member

@cretz cretz Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit confusing to read as a public consumer of the API. Not sure "metering subtypes" and such make sense here. From an outsider POV, can you help me understand when this field would be set and on which history events?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this is a starter but definitely will need a more comprehensive explanation. The idea is that history events are attributed to a potentially billable aspect. For example, if we come across a EVENT_TYPE_WORKFLOW_EXECUTION_STARTED, we might see an action count of 1, or even 3 (if we find that it was actually started via a scheduled workflow instead of a regular start wf exectution). We can, alternatively, have history events with an action of 0, which would mean they are not billable. We're planning on intercepting frontend requests to enrich history event data with a corresponding action count.

Copy link
Member

@cretz cretz Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think you should store redundant action information in history if it can be reliably derived from history based on known events. Adding this redundant information affects everyone's history format that they store on disk for several uses and it's unnecessary information.

We should instead just store action information that otherwise cannot be derived from history (e.g. queries and heartbeats). And IMO that information doesn't need to be on history anyways, it can be part of general workflow information.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this information can be derived from history and it may be redundant, but the objective here is to improve billing visibility so that by having this metadata readily available in history, users would not have to implement their own billing analyzer logic in order for them to calculate their Temporal usages/bills. To minimize polluting this field, we are ideally starting small by only including the most relevant fields required.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@cretz cretz Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a public repo, internal links may not make as much sense, can discuss internally

users would not have to implement their own billing analyzer logic in order for them to calculate their Temporal usages/bills

No, we can implement this for them. Someone already has to implement some logic to count the actions, how is counting the events different?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are a few other potential options if we feel strongly about not adding metering metadata to the history event:

  1. GetWorkflowExecutionHistory takes some form of verbosity flag or argument, which, if specified, only populates the data on the history event then.

  2. We add a separate endpoint that takes in a (workflowid, runid) and returns billable information/metadata about the Workflow.

Any preferences between the above two, or are there any other options we are missing

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea behind using a repeated message here is that we can have multiple actions attributed to a HistoryEvent. This makes it easier to extend later down the road (ie if we want to add more metadata to the Action message such as action_id or display_category).

}

message Action {
int32 action_count = 1;
}
Loading