Customizing Task Logs
Flyte allows you to customize task execution log links by defining URI templates that are populated with metadata from the execution environment. This is primarily achieved through the TemplateLogPlugin, which implements the Plugin interface to generate dynamic URLs for various log providers like Cloudwatch, Stackdriver, or custom Kubernetes dashboards.
Configuring Custom Log Templates
To add custom log links to your Flyte deployment, you configure the TemplateLogPlugin within the logs section of the Flyte configuration. Each plugin defines a display name and one or more URI templates.
import (
"github.com/flyteorg/flyte/v2/flyteplugins/go/tasks/pluginmachinery/tasklog"
"github.com/flyteorg/flyte/v2/gen/go/flyteidl2/core"
)
// Example of a Cloudwatch log template configuration
cloudwatchPlugin := tasklog.TemplateLogPlugin{
DisplayName: "Cloudwatch Logs",
TemplateURIs: []tasklog.TemplateURI{
"https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#logEventViewer:group=/flyte-production/kubernetes;stream=var.log.containers.{{.podName}}_{{.namespace}}_{{.containerName}}-{{.containerId}}.log",
},
MessageFormat: core.TaskLog_JSON,
}
When Flyte generates the log link, it replaces the placeholders (e.g., {{.podName}}) with actual values from the Input struct provided during task execution.
Available Template Variables
The TemplateLogPlugin supports a wide range of variables derived from the Input struct and the TaskExecutionID. These are defined in flyteplugins/go/tasks/pluginmachinery/tasklog/template.go:
| Variable | Description |
|---|---|
{{ .podName }} | The name of the Kubernetes pod. |
{{ .namespace }} | The Kubernetes namespace where the task is running. |
{{ .containerID }} | The ID of the container (automatically stripped of prefixes like docker://). |
{{ .containerName }} | The name of the container within the pod. |
{{ .generatedName }} | A DNS-1123 compatible unique name for the task execution. |
{{ .taskID }} | The name of the task. |
{{ .executionName }} | The name of the workflow execution. |
{{ .nodeID }} | The unique ID of the node in the workflow graph. |
{{ .podRFC3339StartTime }} | The start time of the pod in RFC3339 format. |
{{ .podUnixStartTime }} | The start time of the pod as a Unix timestamp. |
Implementing Dynamic Log Links
Dynamic log links allow you to pull values from the task's configuration metadata using the {{ .taskConfig.<key> }} syntax. This is useful for tools like VSCode or interactive debuggers where the connection details (like a port) are specific to the task instance.
To use dynamic links, define them in the DynamicTemplateURIs field of the TemplateLogPlugin:
// Example for a VSCode interactive link
vscodePlugin := tasklog.TemplateLogPlugin{
Name: "vscode",
DisplayName: "VSCode Link",
DynamicTemplateURIs: []tasklog.TemplateURI{"vscode://flyteinteractive:{{ .taskConfig.port }}/{{ .podName }}"},
MessageFormat: core.TaskLog_JSON,
}
For these links to appear, the task must include a matching link_type in its configuration. Flyte's InitializeLogPlugins function in flyteplugins/go/tasks/logs/logging_utils.go checks the TaskTemplate config for a link_type key:
// From flyteplugins/go/tasks/pluginmachinery/tasklog/template.go
config := input.TaskTemplate.GetConfig()
linkType := config["link_type"] // e.g., "vscode"
Injecting Logs via Task Metadata
You can also define log links directly within a task's metadata. Flyte will automatically convert these into TemplateLogPlugin instances during initialization.
In flyteplugins/go/tasks/logs/logging_utils.go, the InitializeLogPlugins function iterates over metadata log links:
if taskTemplate != nil && taskTemplate.GetMetadata() != nil {
for _, logLink := range taskTemplate.GetMetadata().GetLogLinks() {
plugins = append(plugins, tasklog.TemplateLogPlugin{
DisplayName: logLink.GetName(),
TemplateURIs: []tasklog.TemplateURI{logLink.GetUri()},
MessageFormat: logLink.GetMessageFormat(),
LinkType: core.TaskLog_DASHBOARD.String(),
IconUri: logLink.GetIconUri(),
})
}
}
Troubleshooting and Implementation Details
Container ID Sanitization
Flyte automatically strips the container engine prefix from containerID before substitution. If your Kubernetes environment uses cri-o://<id> or docker://<id>, the template variable {{ .containerId }} will only contain the <id> portion. This logic is handled in flyteplugins/go/tasks/pluginmachinery/tasklog/template.go:
containerID := input.ContainerID
stripDelimiter := "://"
if split := strings.Split(input.ContainerID, stripDelimiter); len(split) > 1 {
containerID = split[1]
}
DNS-1123 Compatibility
The {{ .generatedName }} variable is sanitized using utils.ConvertToDNS1123SubdomainCompatibleString. This ensures that if you use the generated name in a URL that requires DNS compatibility (like a subdomain), it will not contain invalid characters like underscores.
Visibility Controls
You can control when log links are visible in the Flyte Console using the following fields in TemplateLogPlugin:
ShowWhilePending: If set totrue, the link is visible as soon as the task is created, even before it starts running.HideOnceFinished: If set totrue, the link disappears once the task reaches a terminal state.