Skip to content

Commit dfc9503

Browse files
authored
feat: stacks opentelemtry (#4109)
* stack opentelemetry * generate metrics * Add outputs metrics fetching * Telemetry exporting * Updated lint issues * Env variables update
1 parent f1eca89 commit dfc9503

File tree

3 files changed

+89
-22
lines changed

3 files changed

+89
-22
lines changed

cli/commands/stack/stack.go

+40-7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import (
55
"os"
66
"path/filepath"
77

8+
"github.com/gruntwork-io/terragrunt/telemetry"
9+
"github.com/zclconf/go-cty/cty"
10+
811
"github.com/gruntwork-io/terragrunt/cli/commands/common/runall"
912
"github.com/gruntwork-io/terragrunt/config"
1013

@@ -35,7 +38,12 @@ func RunGenerate(ctx context.Context, opts *options.TerragruntOptions) error {
3538

3639
opts.Logger.Infof("Generating stack from %s", opts.TerragruntStackConfigPath)
3740

38-
return config.GenerateStacks(ctx, opts)
41+
return telemetry.TelemeterFromContext(ctx).Collect(ctx, "stack_generate", map[string]any{
42+
"stack_config_path": opts.TerragruntStackConfigPath,
43+
"working_dir": opts.WorkingDir,
44+
}, func(ctx context.Context) error {
45+
return config.GenerateStacks(ctx, opts)
46+
})
3947
}
4048

4149
// Run execute stack command.
@@ -44,7 +52,14 @@ func Run(ctx context.Context, opts *options.TerragruntOptions) error {
4452
return err
4553
}
4654

47-
if err := RunGenerate(ctx, opts); err != nil {
55+
err := telemetry.TelemeterFromContext(ctx).Collect(ctx, "stack_run", map[string]any{
56+
"stack_config_path": opts.TerragruntStackConfigPath,
57+
"working_dir": opts.WorkingDir,
58+
}, func(ctx context.Context) error {
59+
return RunGenerate(ctx, opts)
60+
})
61+
62+
if err != nil {
4863
return err
4964
}
5065

@@ -59,12 +74,23 @@ func RunOutput(ctx context.Context, opts *options.TerragruntOptions, index strin
5974
return err
6075
}
6176

77+
var outputs map[string]map[string]cty.Value
78+
6279
// collect outputs
63-
outputs, err := config.StackOutput(ctx, opts)
80+
err := telemetry.TelemeterFromContext(ctx).Collect(ctx, "stack_output", map[string]any{
81+
"stack_config_path": opts.TerragruntStackConfigPath,
82+
"working_dir": opts.WorkingDir,
83+
}, func(ctx context.Context) error {
84+
stackOutputs, err := config.StackOutput(ctx, opts)
85+
outputs = stackOutputs
86+
87+
return err
88+
})
6489
if err != nil {
6590
return errors.New(err)
6691
}
67-
// write outputs
92+
93+
// render outputs
6894

6995
writer := opts.Writer
7096

@@ -89,14 +115,21 @@ func RunOutput(ctx context.Context, opts *options.TerragruntOptions, index strin
89115
}
90116

91117
// RunClean cleans the stack directory
92-
func RunClean(_ context.Context, opts *options.TerragruntOptions) error {
118+
func RunClean(ctx context.Context, opts *options.TerragruntOptions) error {
93119
if err := checkStackExperiment(opts); err != nil {
94120
return err
95121
}
96122

97123
baseDir := filepath.Join(opts.WorkingDir, stackDir)
98-
opts.Logger.Debugf("Cleaning stack directory: %s", baseDir)
99-
err := os.RemoveAll(baseDir)
124+
err := telemetry.TelemeterFromContext(ctx).Collect(ctx, "stack_clean", map[string]any{
125+
"stack_config_path": opts.TerragruntStackConfigPath,
126+
"working_dir": opts.WorkingDir,
127+
}, func(ctx context.Context) error {
128+
opts.Logger.Debugf("Cleaning stack directory: %s", baseDir)
129+
err := os.RemoveAll(baseDir)
130+
131+
return err
132+
})
100133

101134
if err != nil {
102135
return errors.Errorf("failed to clean stack directory: %s %w", baseDir, err)

config/stack.go

+28-11
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"path/filepath"
88
"strings"
99

10+
"github.com/gruntwork-io/terragrunt/telemetry"
11+
1012
"github.com/gruntwork-io/terragrunt/internal/ctyhelper"
1113
"github.com/gruntwork-io/terragrunt/internal/worker"
1214

@@ -156,8 +158,19 @@ func StackOutput(ctx context.Context, opts *options.TerragruntOptions) (map[stri
156158

157159
dir := filepath.Dir(path)
158160
unitDir := filepath.Join(dir, stackDir, unit.Path)
159-
output, err := unit.ReadOutputs(ctx, opts, unitDir)
160161

162+
var output map[string]cty.Value
163+
164+
err := telemetry.TelemeterFromContext(ctx).Collect(ctx, "unit_output", map[string]any{
165+
"unit_name": unit.Name,
166+
"unit_source": unit.Source,
167+
"unit_path": unit.Path,
168+
}, func(ctx context.Context) error {
169+
unitOutput, err := unit.ReadOutputs(ctx, opts, unitDir)
170+
output = unitOutput
171+
172+
return err
173+
})
161174
if err != nil {
162175
return nil, errors.New(err)
163176
}
@@ -220,11 +233,13 @@ func generateUnits(ctx context.Context, opts *options.TerragruntOptions, pool *w
220233

221234
opts.Logger.Infof("Processing unit %s", unitCopy.Name)
222235

223-
if err := processComponent(ctx, opts, &item); err != nil {
224-
return err
225-
}
226-
227-
return nil
236+
return telemetry.TelemeterFromContext(ctx).Collect(ctx, "stack_generate_unit", map[string]any{
237+
"unit_name": unitCopy.Name,
238+
"unit_source": unitCopy.Source,
239+
"unit_path": unitCopy.Path,
240+
}, func(ctx context.Context) error {
241+
return processComponent(ctx, opts, &item)
242+
})
228243
})
229244
}
230245

@@ -251,11 +266,13 @@ func generateStacks(ctx context.Context, opts *options.TerragruntOptions, pool *
251266

252267
opts.Logger.Infof("Processing stack %s", stackCopy.Name)
253268

254-
if err := processComponent(ctx, opts, &item); err != nil {
255-
return err
256-
}
257-
258-
return nil
269+
return telemetry.TelemeterFromContext(ctx).Collect(ctx, "stack_generate_stack", map[string]any{
270+
"stack_name": stackCopy.Name,
271+
"stack_source": stackCopy.Source,
272+
"stack_path": stackCopy.Path,
273+
}, func(ctx context.Context) error {
274+
return processComponent(ctx, opts, &item)
275+
})
259276
})
260277
}
261278

test/integration_serial_test.go

+21-4
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ func TestTerragruntLogLevelEnvVarUnparsableLogsError(t *testing.T) {
487487
}
488488

489489
func TestTerragruntProduceTelemetryTraces(t *testing.T) {
490-
t.Setenv("TERRAGRUNT_TELEMETRY_TRACE_EXPORTER", "console")
490+
t.Setenv("TG_TELEMETRY_TRACE_EXPORTER", "console")
491491

492492
helpers.CleanupTerraformFolder(t, testFixtureHooksBeforeAndAfterPath)
493493
tmpEnvPath := helpers.CopyEnvironment(t, testFixtureHooksBeforeAndAfterPath)
@@ -503,8 +503,25 @@ func TestTerragruntProduceTelemetryTraces(t *testing.T) {
503503
assert.Contains(t, output, "\"Name\":\"hook_after_hook_2\"")
504504
}
505505

506+
func TestTerragruntStackProduceTelemetryTraces(t *testing.T) {
507+
t.Setenv("TG_TELEMETRY_TRACE_EXPORTER", "console")
508+
509+
helpers.CleanupTerraformFolder(t, testFixtureStacksBasic)
510+
tmpEnvPath := helpers.CopyEnvironment(t, testFixtureStacksBasic)
511+
rootPath := util.JoinPath(tmpEnvPath, testFixtureStacksBasic, "live")
512+
513+
output, _, err := helpers.RunTerragruntCommandWithOutput(t, "terragrunt stack generate --experiment stacks --working-dir "+rootPath)
514+
require.NoError(t, err)
515+
516+
// check that output have Telemetry json output
517+
assert.Contains(t, output, "\"SpanContext\":")
518+
assert.Contains(t, output, "\"TraceID\":")
519+
assert.Contains(t, output, "\"Name\":\"stack_generate_unit\"")
520+
assert.Contains(t, output, "\"Name\":\"stack_generate\"")
521+
}
522+
506523
func TestTerragruntProduceTelemetryMetrics(t *testing.T) {
507-
t.Setenv("TERRAGRUNT_TELEMETRY_METRIC_EXPORTER", "console")
524+
t.Setenv("TG_TELEMETRY_METRIC_EXPORTER", "console")
508525

509526
helpers.CleanupTerraformFolder(t, testFixtureHooksBeforeAndAfterPath)
510527
tmpEnvPath := helpers.CopyEnvironment(t, testFixtureHooksBeforeAndAfterPath)
@@ -523,7 +540,7 @@ func TestTerragruntProduceTelemetryMetrics(t *testing.T) {
523540
}
524541

525542
func TestTerragruntProduceTelemetryTracesWithRootSpanAndTraceID(t *testing.T) {
526-
t.Setenv("TERRAGRUNT_TELEMETRY_TRACE_EXPORTER", "console")
543+
t.Setenv("TG_TELEMETRY_TRACE_EXPORTER", "console")
527544
t.Setenv("TRACEPARENT", "00-b2ff2d54551433d53dd807a6c94e81d1-0e6f631d793c718a-01")
528545

529546
helpers.CleanupTerraformFolder(t, testFixtureHooksBeforeAndAfterPath)
@@ -543,7 +560,7 @@ func TestTerragruntProduceTelemetryTracesWithRootSpanAndTraceID(t *testing.T) {
543560
}
544561

545562
func TestTerragruntProduceTelemetryInCasOfError(t *testing.T) {
546-
t.Setenv("TERRAGRUNT_TELEMETRY_TRACE_EXPORTER", "console")
563+
t.Setenv("TG_TELEMETRY_TRACE_EXPORTER", "console")
547564
t.Setenv("TRACEPARENT", "00-b2ff2d54551433d53dd807a6c94e81d1-0e6f631d793c718a-01")
548565

549566
helpers.CleanupTerraformFolder(t, testFixtureHooksBeforeAndAfterPath)

0 commit comments

Comments
 (0)