@@ -25,7 +25,6 @@ import (
2525 "github.com/gruntwork-io/terragrunt/internal/experiment"
2626 "github.com/gruntwork-io/terragrunt/internal/remotestate"
2727 "github.com/gruntwork-io/terragrunt/internal/strict/controls"
28- "github.com/gruntwork-io/terragrunt/telemetry"
2928
3029 "github.com/mitchellh/mapstructure"
3130
@@ -1154,60 +1153,75 @@ func ParseConfigFile(ctx *ParsingContext, l log.Logger, configPath string, inclu
11541153
11551154 hclCache := cache .ContextCache [* hclparse.File ](ctx , HclCacheContextKey )
11561155
1157- err := telemetry .TelemeterFromContext (ctx ).Collect (ctx , "parse_config_file" , map [string ]any {
1158- "config_path" : configPath ,
1159- "working_dir" : ctx .TerragruntOptions .WorkingDir ,
1160- }, func (_ context.Context ) error {
1161- childKey := "nil"
1162- if includeFromChild != nil {
1163- childKey = includeFromChild .String ()
1164- }
1156+ // Build cache key components before tracing to determine cache hit status
1157+ childKey := "nil"
1158+ if includeFromChild != nil {
1159+ childKey = includeFromChild .String ()
1160+ }
1161+
1162+ decodeListKey := "nil"
1163+ if ctx .PartialParseDecodeList != nil {
1164+ decodeListKey = fmt .Sprintf ("%v" , ctx .PartialParseDecodeList )
1165+ }
11651166
1166- decodeListKey := "nil"
1167- if ctx .PartialParseDecodeList != nil {
1168- decodeListKey = fmt .Sprintf ("%v" , ctx .PartialParseDecodeList )
1167+ fileInfo , err := os .Stat (configPath )
1168+ if err != nil {
1169+ if os .IsNotExist (err ) {
1170+ return nil , TerragruntConfigNotFoundError {Path : configPath }
11691171 }
11701172
1171- fileInfo , err := os .Stat (configPath )
1172- if err != nil {
1173- if os .IsNotExist (err ) {
1174- return TerragruntConfigNotFoundError {Path : configPath }
1175- }
1173+ return nil , errors .Errorf ("failed to get file info: %w" , err )
1174+ }
11761175
1177- return errors .Errorf ("failed to get file info: %w" , err )
1178- }
1176+ cacheKey := fmt .Sprintf ("%v-%v-%v-%v-%v" ,
1177+ configPath ,
1178+ ctx .TerragruntOptions .WorkingDir ,
1179+ childKey ,
1180+ decodeListKey ,
1181+ fileInfo .ModTime ().UnixMicro (),
1182+ )
11791183
1180- cacheKey := fmt .Sprintf ("%v-%v-%v-%v-%v" ,
1181- configPath ,
1182- ctx .TerragruntOptions .WorkingDir ,
1183- childKey ,
1184- decodeListKey ,
1185- fileInfo .ModTime ().UnixMicro (),
1186- )
1184+ // Check cache hit status before tracing
1185+ _ , cacheHit := hclCache .Get (ctx , cacheKey )
11871186
1188- var file * hclparse. File
1187+ isPartial := len ( ctx . PartialParseDecodeList ) > 0
11891188
1190- // TODO: Remove lint ignore
1191- if cacheConfig , found := hclCache .Get (ctx , cacheKey ); found { //nolint:contextcheck
1192- file = cacheConfig
1193- } else {
1194- // Parse the HCL file into an AST body that can be decoded multiple times later without having to re-parse
1195- file , err = hclparse .NewParser (ctx .ParserOptions ... ).ParseFromFile (configPath )
1196- if err != nil {
1197- return err
1189+ err = TraceParseConfigFile (
1190+ ctx ,
1191+ configPath ,
1192+ ctx .TerragruntOptions .WorkingDir ,
1193+ isPartial ,
1194+ ctx .PartialParseDecodeList ,
1195+ includeFromChild ,
1196+ cacheHit ,
1197+ func (_ context.Context ) error {
1198+ var file * hclparse.File
1199+
1200+ // TODO: Remove lint ignore
1201+ if cacheConfig , found := hclCache .Get (ctx , cacheKey ); found { //nolint:contextcheck
1202+ file = cacheConfig
1203+ } else {
1204+ // Parse the HCL file into an AST body that can be decoded multiple times later without having to re-parse
1205+ var parseErr error
1206+
1207+ file , parseErr = hclparse .NewParser (ctx .ParserOptions ... ).ParseFromFile (configPath )
1208+ if parseErr != nil {
1209+ return parseErr
1210+ }
1211+ // TODO: Remove lint ignore
1212+ hclCache .Put (ctx , cacheKey , file ) //nolint:contextcheck
11981213 }
1214+
11991215 // TODO: Remove lint ignore
1200- hclCache .Put (ctx , cacheKey , file ) //nolint:contextcheck
1201- }
1216+ var parseErr error
12021217
1203- // TODO: Remove lint ignore
1204- config , err = ParseConfig (ctx , l , file , includeFromChild ) //nolint:contextcheck
1205- if err != nil {
1206- return err
1207- }
1218+ config , parseErr = ParseConfig (ctx , l , file , includeFromChild ) //nolint:contextcheck
1219+ if parseErr != nil {
1220+ return parseErr
1221+ }
12081222
1209- return nil
1210- })
1223+ return nil
1224+ })
12111225 if err != nil {
12121226 return config , err
12131227 }
@@ -1285,7 +1299,12 @@ func ParseConfig(
12851299 ctx = ctx .WithValues (unitValues )
12861300
12871301 // Decode just the Base blocks. See the function docs for DecodeBaseBlocks for more info on what base blocks are.
1288- baseBlocks , err := DecodeBaseBlocks (ctx , l , file , includeFromChild )
1302+ var baseBlocks * DecodedBaseBlocks
1303+
1304+ // TODO: Remove lint ignore
1305+ baseBlocks , err = TraceParseBaseBlocks (ctx , l , file .ConfigPath , func (_ context.Context ) (* DecodedBaseBlocks , error ) {
1306+ return DecodeBaseBlocks (ctx , l , file , includeFromChild ) //nolint:contextcheck
1307+ })
12891308 if err != nil {
12901309 errs = errs .Append (err )
12911310 }
@@ -1296,6 +1315,13 @@ func ParseConfig(
12961315 ctx = ctx .WithLocals (baseBlocks .Locals )
12971316 }
12981317
1318+ // Emit additional trace with comprehensive base blocks details
1319+ if baseBlocks != nil {
1320+ _ = TraceParseBaseBlocksResult (ctx , file .ConfigPath , baseBlocks , func (_ context.Context ) error {
1321+ return nil
1322+ })
1323+ }
1324+
12991325 if ! ctx .SkipOutputsResolution && ctx .DecodedDependencies == nil {
13001326 // Decode just the `dependency` blocks, retrieving the outputs from the target terragrunt config in the
13011327 // process.
@@ -1314,7 +1340,15 @@ func ParseConfig(
13141340
13151341 // Decode the rest of the config, passing in this config's `include` block or the child's `include` block, whichever
13161342 // is appropriate
1317- terragruntConfigFile , err := decodeAsTerragruntConfigFile (ctx , l , file , evalContext )
1343+ var terragruntConfigFile * terragruntConfigFile
1344+
1345+ err = TraceParseConfigDecode (ctx , file .ConfigPath , func (_ context.Context ) error {
1346+ var decodeErr error
1347+
1348+ terragruntConfigFile , decodeErr = decodeAsTerragruntConfigFile (ctx , l , file , evalContext )
1349+
1350+ return decodeErr
1351+ })
13181352 if err != nil {
13191353 errs = errs .Append (err )
13201354 }
@@ -1331,7 +1365,27 @@ func ParseConfig(
13311365 // If this file includes another, parse and merge it. Otherwise, just return this config.
13321366 // If there have been errors during this parse, don't attempt to parse the included config.
13331367 if ctx .TrackInclude != nil {
1334- mergedConfig , err := handleInclude (ctx , l , config , false )
1368+ // Extract include paths for telemetry
1369+ includeCount := len (ctx .TrackInclude .CurrentList )
1370+ includePaths := make ([]string , 0 , includeCount )
1371+
1372+ for _ , inc := range ctx .TrackInclude .CurrentList {
1373+ if inc .Path != "" {
1374+ includePaths = append (includePaths , inc .Path )
1375+ }
1376+ }
1377+
1378+ var mergedConfig * TerragruntConfig
1379+
1380+ // TODO: Remove lint ignore
1381+ err = TraceParseIncludeMerge (ctx , file .ConfigPath , includeCount , includePaths , func (childCtx context.Context ) error {
1382+ var mergeErr error
1383+
1384+ // Use the child context for trace propagation so include parsing is a child span
1385+ mergedConfig , mergeErr = handleInclude (ctx .WithContext (childCtx ), l , config , false ) //nolint:contextcheck
1386+
1387+ return mergeErr
1388+ })
13351389 if err != nil {
13361390 errs = errs .Append (err )
13371391 return config , errs .ErrorOrNil ()
0 commit comments