mirror of
https://github.com/temporalio/skill-temporal-developer.git
synced 2026-09-14 13:52:58 +08:00
b5719bc143
* Add initial skill for testing, which is simply Steve's skill (#1) * Add initial skill for testing, which is simply Steve's skill * Rename skill to 'temporal-dev' and update version Updated skill name and version for Temporal Python. * Use claude to merge Steve's, Max's, and Mason's skills. (#2) * Use claude to merge Steve's, Max's, and Mason's skills. Did a review pass using claude's skill devlopment skills * Add missing things from Steve * trigger tweaks * Add in common gotchas from Johann * add simple feedback mechanism (#3) * Change skill name to kebab-case, for compatibility with Amp and Cline (#7) * Clean up references/core/ai-integration.md * Clean up references/core/common-gotchas.md * Clean up references/core/common-gotchas.md * Clean up references/core/determinism.md * Clean up references/core/determinism.md * Update error-reference.md * Update interactive-workflows.md * Clean up patterns.md * Cut shell scripts * Edit troubleshooting.md * remove interceptors for now * remove dynamic workflows * clarify on heartbeating of async activity completions, and prompt it a bit in relation to signals * Improve references/python/advanced-features.md * Use explicit namespace in connect * remove duplicated content from determinism.md, clean up * Improve references/python/data-handling.md * Prefer start_to_close_timeout * don't explicitely provide defaults for retry policies * error-handling.md cleanup * move idempotency patterns to patterns.md * remove multi-param activities * small edits * Unify sandbox stuff into one file * local activities aren't experimental * Clean up references/python/sync-vs-async.md * Cleanup observability.md, remove duplicated search attributes * Cut otel for now * cut a lot of duplicate stuff from python gotchas, address comments * de-duplicate content * Lots of improvements to testing * cleanup to top level of skill (like CLI install instructions), and to top-level of python * Improve patterns.md * clean up ai-patterns.md * Update readme with installation instructions * remove ts directory * De-couple core from python and TypeScript as much as possible * Remove TypeScript hints * add prompting for feedback at startup - wait for ethan on slack channel * shorten url * Update slack channel * Automated pass over on python cleanup & deduplication * Remove multi-patching from Python, since its obvious, dont waste tokens on it. (#34) * Add TypeScript (#31) Adds initial support for TypeScript to the skill --------- Co-authored-by: James Watkins-Harvey <mjameswh@users.noreply.github.com> Co-authored-by: Chris Olszewski <chrisdolszewski@gmail.com> * Fix typos and reference links (#36) * Fix typos and reference links * 2 more typo fixes * quick edit to readme (#37) * Fix saga compensations to run under cancellation protection (#43) When a workflow is cancelled mid-saga, compensations must run in a cancellation-protected scope, otherwise they are immediately cancelled before they can execute. - Python: wrap compensation loop in asyncio.shield() so it runs even when the workflow receives a CancelledError - TypeScript: wrap compensation loop in CancellationScope.nonCancellable() so it runs even when the root scope is cancelled (per official docs: "Cleanup logic must be in a nonCancellable scope") - TypeScript: also fix compensation registration order — register BEFORE calling the activity (was already correct in Python) Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> * Update readme for public preview (#45) * a few more readme tweaks (#46) * Add MIT License to the project (#47) * Add Go (supersedes other PR) (#38) * progress on go * Go translation workflow completed. * missed a few spots * Manual edits * Address feedback * Add gotcha about anonymous local activities * Sample code for payload converter * clarify sdk protection mechanisms * Setup CODEOWNERS to AI SDK team (#48) * Align version number in SKILL.md and plugin.json. (#49) --------- Co-authored-by: James Watkins-Harvey <mjameswh@users.noreply.github.com> Co-authored-by: Chris Olszewski <chrisdolszewski@gmail.com> Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
154 lines
4.3 KiB
Markdown
154 lines
4.3 KiB
Markdown
# Go SDK Observability
|
|
|
|
## Overview
|
|
|
|
The Go SDK provides replay-safe logging via `workflow.GetLogger`, metrics via the Tally library with Prometheus export, and tracing via OpenTelemetry, OpenTracing, or Datadog.
|
|
|
|
## Logging / Replay-Aware Logging
|
|
|
|
### Workflow Logging
|
|
|
|
Use `workflow.GetLogger(ctx)` for replay-safe logging. This logger automatically suppresses duplicate messages during replay.
|
|
|
|
```go
|
|
func MyWorkflow(ctx workflow.Context, input string) (string, error) {
|
|
logger := workflow.GetLogger(ctx)
|
|
logger.Info("Workflow started", "input", input)
|
|
|
|
var result string
|
|
err := workflow.ExecuteActivity(ctx, MyActivity, input).Get(ctx, &result)
|
|
if err != nil {
|
|
logger.Error("Activity failed", "error", err)
|
|
return "", err
|
|
}
|
|
|
|
logger.Info("Workflow completed", "result", result)
|
|
return result, nil
|
|
}
|
|
```
|
|
|
|
The workflow logger automatically:
|
|
- Suppresses duplicate logs during replay
|
|
- Includes workflow context (workflow ID, run ID, etc.)
|
|
|
|
### Activity Logging
|
|
|
|
Use `activity.GetLogger(ctx)` for context-aware activity logging:
|
|
|
|
```go
|
|
func MyActivity(ctx context.Context, input string) (string, error) {
|
|
logger := activity.GetLogger(ctx)
|
|
logger.Info("Processing input", "input", input)
|
|
// ...
|
|
return "done", nil
|
|
}
|
|
```
|
|
|
|
Activity logger includes:
|
|
- Activity ID, type, and task queue
|
|
- Workflow ID and run ID
|
|
- Attempt number (for retries)
|
|
|
|
### Adding Persistent Fields
|
|
|
|
Use `log.With` to create a logger with key-value pairs included in every entry:
|
|
|
|
```go
|
|
logger := log.With(workflow.GetLogger(ctx), "orderId", orderId, "customerId", customerId)
|
|
logger.Info("Processing order") // includes orderId and customerId
|
|
```
|
|
|
|
## Customizing the Logger
|
|
|
|
Set a custom logger via `client.Options{Logger: myLogger}`. Implement the `log.Logger` interface (Debug, Info, Warn, Error methods).
|
|
|
|
### Using slog (Go 1.21+)
|
|
|
|
```go
|
|
import (
|
|
"log/slog"
|
|
"os"
|
|
|
|
tlog "go.temporal.io/sdk/log"
|
|
)
|
|
|
|
slogHandler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})
|
|
logger := tlog.NewStructuredLogger(slog.New(slogHandler))
|
|
|
|
c, err := client.Dial(client.Options{
|
|
Logger: logger,
|
|
})
|
|
```
|
|
|
|
### Using Third-Party Loggers (Logrus, Zap, etc.)
|
|
|
|
Use the [logur](https://github.com/logur/logur) adapter package:
|
|
|
|
```go
|
|
import (
|
|
"github.com/sirupsen/logrus"
|
|
logrusadapter "logur.dev/adapter/logrus"
|
|
"logur.dev/logur"
|
|
)
|
|
|
|
logger := logur.LoggerToKV(logrusadapter.New(logrus.New()))
|
|
c, err := client.Dial(client.Options{
|
|
Logger: logger,
|
|
})
|
|
```
|
|
|
|
## Metrics
|
|
|
|
Use the Tally library (`go.temporal.io/sdk/contrib/tally`) with Prometheus:
|
|
|
|
```go
|
|
import (
|
|
sdktally "go.temporal.io/sdk/contrib/tally"
|
|
"github.com/uber-go/tally/v4"
|
|
"github.com/uber-go/tally/v4/prometheus"
|
|
)
|
|
|
|
func newPrometheusScope(c prometheus.Configuration) tally.Scope {
|
|
reporter, err := c.NewReporter(
|
|
prometheus.ConfigurationOptions{},
|
|
)
|
|
if err != nil {
|
|
log.Fatalln("error creating prometheus reporter", err)
|
|
}
|
|
scopeOpts := tally.ScopeOptions{
|
|
CacheReporter: reporter,
|
|
Separator: "_",
|
|
SanitizeOptions: &sdktally.PrometheusSanitizeOptions,
|
|
}
|
|
scope, _ := tally.NewRootScope(scopeOpts, time.Second)
|
|
scope = sdktally.NewPrometheusNamingScope(scope)
|
|
return scope
|
|
}
|
|
|
|
c, err := client.Dial(client.Options{
|
|
MetricsHandler: sdktally.NewMetricsHandler(newPrometheusScope(prometheus.Configuration{
|
|
ListenAddress: "0.0.0.0:9090",
|
|
TimerType: "histogram",
|
|
})),
|
|
})
|
|
```
|
|
|
|
Key SDK metrics:
|
|
- `temporal_workflow_task_execution_latency` -- Workflow task processing time
|
|
- `temporal_activity_execution_latency` -- Activity execution time
|
|
- `temporal_workflow_task_replay_latency` -- Replay duration
|
|
- `temporal_request` -- Client requests to server
|
|
- `temporal_activity_schedule_to_start_latency` -- Time from scheduling to start
|
|
|
|
## Search Attributes (Visibility)
|
|
|
|
See the Search Attributes section of `references/go/data-handling.md`
|
|
|
|
## Best Practices
|
|
|
|
1. Always use `workflow.GetLogger(ctx)` in workflows -- never `fmt.Println` or `log.Println` (they produce duplicates on replay)
|
|
2. Use `activity.GetLogger(ctx)` in activities for structured context
|
|
3. Set up Prometheus metrics in production
|
|
4. Use search attributes for operational visibility and debugging
|
|
5. Use `workflow.IsReplaying(ctx)` only for custom side-effect-free logging -- the built-in logger handles replay suppression automatically
|