Skip to content

Commit 2cc5bde

Browse files
authored
Merge branch 'master' into users/sanjuyadav/Node24
2 parents bc8534d + 2413afc commit 2cc5bde

File tree

9 files changed

+2481
-14
lines changed

9 files changed

+2481
-14
lines changed

src/Agent.Sdk/Knob/AgentKnobs.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,5 +898,20 @@ public class AgentKnobs
898898
"If true, use structured enhanced logging format with timestamps, components, and operations",
899899
new EnvironmentKnobSource("AZP_USE_ENHANCED_LOGGING"),
900900
new BuiltInDefaultKnobSource("false"));
901+
902+
public static readonly Knob EnableEnhancedContainerDiagnostics = new Knob(
903+
nameof(EnableEnhancedContainerDiagnostics),
904+
"When enabled, uses ContainerOperationProviderEnhanced with detailed tracing and duration logging for container operations",
905+
new PipelineFeatureSource("EnableEnhancedContainerDiagnostics"),
906+
new EnvironmentKnobSource("AGENT_ENABLE_ENHANCED_CONTAINER_LOGGING"),
907+
new BuiltInDefaultKnobSource("false"));
908+
909+
910+
public static readonly Knob EnableDockerExecDiagnostics = new Knob(
911+
nameof(EnableDockerExecDiagnostics),
912+
"If true, collect and report comprehensive diagnostics when docker exec commands fail, including container state, resource limits, logs, and platform-specific analysis.",
913+
new PipelineFeatureSource("EnableDockerExecDiagnostics"),
914+
new EnvironmentKnobSource("AGENT_ENABLE_DOCKER_EXEC_DIAGNOSTICS"),
915+
new BuiltInDefaultKnobSource("false"));
901916
}
902917
}

src/Agent.Worker/Container/ContainerDiagnosticsManager.cs

Lines changed: 585 additions & 0 deletions
Large diffs are not rendered by default.

src/Agent.Worker/Container/DockerCommandManager.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public async Task<DockerVersion> DockerVersion(IExecutionContext context)
8282
}
8383

8484
Version clientVersion = null;
85-
var clientVersionMatchResult = verRegex.Match(serverVersionStr);
85+
var clientVersionMatchResult = verRegex.Match(clientVersionStr);
8686
if (clientVersionMatchResult.Success && !string.IsNullOrEmpty(clientVersionMatchResult.Value))
8787
{
8888
if (!Version.TryParse(clientVersionMatchResult.Value, out clientVersion))
@@ -498,6 +498,7 @@ private static async Task<int> ExecuteDockerCommandAsyncWithRetries(IExecutionCo
498498
retryCount++;
499499
}
500500

501+
context.Output(StringUtil.Loc("DockerCommandFinalExitCode", command, exitCode));
501502
return exitCode;
502503
}
503504

src/Agent.Worker/ContainerOperationProviderEnhanced.cs

Lines changed: 1407 additions & 0 deletions
Large diffs are not rendered by default.

src/Agent.Worker/Handlers/Handler.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ protected void AddPrependPathToEnvironment()
285285
prepend.Add(ExecutionContext.TranslatePathForStepTarget(path));
286286
}
287287
containerStepHost.PrependPath = string.Join(Path.PathSeparator.ToString(), prepend.Reverse<string>());
288+
// Set docker exec diagnostics feature flag from ExecutionContext
289+
containerStepHost.EnableDockerExecDiagnostics = AgentKnobs.EnableDockerExecDiagnostics.GetValue(ExecutionContext).AsBoolean();
288290
}
289291
else
290292
{

src/Agent.Worker/Handlers/StepHost.cs

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public interface IContainerStepHost : IStepHost
4343
{
4444
ContainerInfo Container { get; set; }
4545
string PrependPath { get; set; }
46+
bool EnableDockerExecDiagnostics { get; set; }
4647
}
4748

4849
[ServiceLocator(Default = typeof(DefaultStepHost))]
@@ -101,6 +102,7 @@ public sealed class ContainerStepHost : AgentService, IContainerStepHost
101102
{
102103
public ContainerInfo Container { get; set; }
103104
public string PrependPath { get; set; }
105+
public bool EnableDockerExecDiagnostics { get; set; }
104106
public event EventHandler<ProcessDataReceivedEventArgs> OutputDataReceived;
105107
public event EventHandler<ProcessDataReceivedEventArgs> ErrorDataReceived;
106108

@@ -221,20 +223,47 @@ public async Task<int> ExecuteAsync(string workingDirectory,
221223
var payloadJson = JsonUtility.ToString(payload);
222224
redirectStandardIn.Enqueue(payloadJson);
223225
HostContext.GetTrace(nameof(ContainerStepHost)).Info($"Payload: {payloadJson}");
224-
return await processInvoker.ExecuteAsync(workingDirectory: HostContext.GetDirectory(WellKnownDirectory.Work),
225-
fileName: containerEnginePath,
226-
arguments: containerExecutionArgs,
227-
environment: null,
228-
requireExitCodeZero: requireExitCodeZero,
229-
outputEncoding: outputEncoding,
230-
killProcessOnCancel: killProcessOnCancel,
231-
redirectStandardIn: redirectStandardIn,
232-
inheritConsoleHandler: inheritConsoleHandler,
233-
continueAfterCancelProcessTreeKillAttempt: continueAfterCancelProcessTreeKillAttempt,
234-
cancellationToken: cancellationToken);
226+
227+
int exitCode = 0;
228+
try
229+
{
230+
exitCode = await processInvoker.ExecuteAsync(workingDirectory: HostContext.GetDirectory(WellKnownDirectory.Work),
231+
fileName: containerEnginePath,
232+
arguments: containerExecutionArgs,
233+
environment: null,
234+
requireExitCodeZero: requireExitCodeZero,
235+
outputEncoding: outputEncoding,
236+
killProcessOnCancel: killProcessOnCancel,
237+
redirectStandardIn: redirectStandardIn,
238+
inheritConsoleHandler: inheritConsoleHandler,
239+
continueAfterCancelProcessTreeKillAttempt: continueAfterCancelProcessTreeKillAttempt,
240+
cancellationToken: cancellationToken);
241+
}
242+
catch (Exception ex)
243+
{
244+
// Log the exception
245+
var trace = HostContext.GetTrace(nameof(ContainerStepHost));
246+
trace.Error($"Docker exec failed: {ex.GetType().Name}: {ex.Message}");
247+
248+
// Check if docker exec diagnostics feature is enabled
249+
// Value is set by the Handler from ExecutionContext
250+
if (EnableDockerExecDiagnostics)
251+
{
252+
// Collect comprehensive diagnostics when docker exec fails
253+
trace.Info("Docker exec diagnostics enabled, collecting diagnostics");
254+
var diagnosticsManager = HostContext.GetService<Container.IContainerDiagnosticsManager>();
255+
await diagnosticsManager.CollectDockerExecFailureDiagnosticsAsync(ex, containerEnginePath, containerExecutionArgs, Container.ContainerId);
256+
}
257+
else
258+
{
259+
trace.Info("Docker exec diagnostics disabled, skipping diagnostic collection");
260+
}
261+
throw; // Re-throw the original exception
262+
}
263+
return exitCode;
235264
}
236265
}
237-
266+
238267
private class ContainerStandardInPayload
239268
{
240269
[JsonProperty("handler")]

src/Agent.Worker/JobExtension.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public abstract class JobExtension : AgentService, IJobExtension
5858
// download all required tasks.
5959
// make sure all task's condition inputs are valid.
6060
// build up three list of steps for jobrunner. (pre-job, job, post-job)
61+
#pragma warning disable CA1505
6162
public async Task<List<IStep>> InitializeJob(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message)
6263
{
6364
Trace.Entering();
@@ -313,7 +314,20 @@ public async Task<List<IStep>> InitializeJob(IExecutionContext jobContext, Pipel
313314

314315
if (context.Containers.Count > 0 || context.SidecarContainers.Count > 0)
315316
{
316-
var containerProvider = HostContext.GetService<IContainerOperationProvider>();
317+
// Get container provider - uses enhanced version if feature flag is enabled
318+
IContainerOperationProvider containerProvider;
319+
if (AgentKnobs.EnableEnhancedContainerDiagnostics.GetValue(context).AsBoolean())
320+
{
321+
// Create and initialize enhanced provider manually since it's not registered with ServiceLocator
322+
var enhancedProvider = new ContainerOperationProviderEnhanced();
323+
enhancedProvider.Initialize(HostContext);
324+
containerProvider = enhancedProvider;
325+
}
326+
else
327+
{
328+
containerProvider = HostContext.GetService<IContainerOperationProvider>();
329+
}
330+
317331
var containers = new List<ContainerInfo>();
318332
containers.AddRange(context.Containers);
319333
containers.AddRange(context.SidecarContainers);

src/Misc/layoutbin/en-US/strings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@
277277
"DirExpireLimit": "Directory expiration limit: {0} days.",
278278
"DiscoverBuildDir": "Discover stale build directories that haven't been used for more than {0} days.",
279279
"DiscoverReleaseDir": "Discover stale release directories that haven't been used for more than {0} days.",
280+
"DockerCommandFinalExitCode": "Final exit code for {0}: {1}",
280281
"DownloadAgent": "Downloading {0} agent",
281282
"DownloadArtifactFinished": "Downloading artifact finished.",
282283
"DownloadArtifacts": "Download Artifacts",

0 commit comments

Comments
 (0)