@@ -20,13 +20,15 @@ namespace Microsoft.Azure.Functions.PowerShellWorker
2020{
2121 using System . Diagnostics ;
2222 using LogLevel = Microsoft . Azure . WebJobs . Script . Grpc . Messages . RpcLog . Types . Level ;
23+ using System . Runtime . InteropServices ;
2324
2425 internal class RequestProcessor
2526 {
2627 private readonly MessagingStream _msgStream ;
2728 private readonly System . Management . Automation . PowerShell _firstPwshInstance ;
2829 private readonly PowerShellManagerPool _powershellPool ;
2930 private DependencyManager _dependencyManager ;
31+ private string _pwshVersion ;
3032
3133 // Holds the exception if an issue is encountered while processing the function app dependencies.
3234 private Exception _initTerminatingError ;
@@ -37,11 +39,12 @@ internal class RequestProcessor
3739 private Dictionary < StreamingMessage . ContentOneofCase , Func < StreamingMessage , StreamingMessage > > _requestHandlers =
3840 new Dictionary < StreamingMessage . ContentOneofCase , Func < StreamingMessage , StreamingMessage > > ( ) ;
3941
40- internal RequestProcessor ( MessagingStream msgStream , System . Management . Automation . PowerShell firstPwshInstance )
42+ internal RequestProcessor ( MessagingStream msgStream , System . Management . Automation . PowerShell firstPwshInstance , string pwshVersion )
4143 {
4244 _msgStream = msgStream ;
4345 _firstPwshInstance = firstPwshInstance ;
4446 _powershellPool = new PowerShellManagerPool ( ( ) => new RpcLogger ( msgStream ) ) ;
47+ _pwshVersion = pwshVersion ;
4548
4649 // Host sends capabilities/init data to worker
4750 _requestHandlers . Add ( StreamingMessage . ContentOneofCase . WorkerInitRequest , ProcessWorkerInitRequest ) ;
@@ -95,6 +98,9 @@ internal async Task ProcessRequestLoop()
9598
9699 internal StreamingMessage ProcessWorkerInitRequest ( StreamingMessage request )
97100 {
101+ var stopwatch = new Stopwatch ( ) ;
102+ stopwatch . Start ( ) ;
103+
98104 var workerInitRequest = request . WorkerInitRequest ;
99105 Environment . SetEnvironmentVariable ( "AZUREPS_HOST_ENVIRONMENT" , $ "AzureFunctions/{ workerInitRequest . HostVersion } ") ;
100106 Environment . SetEnvironmentVariable ( "POWERSHELL_DISTRIBUTION_CHANNEL" , $ "Azure-Functions:{ workerInitRequest . HostVersion } ") ;
@@ -117,6 +123,22 @@ internal StreamingMessage ProcessWorkerInitRequest(StreamingMessage request)
117123 RemoteSessionNamedPipeServer . CreateCustomNamedPipeServer ( pipeName ) ;
118124 }
119125
126+ try
127+ {
128+ var rpcLogger = new RpcLogger ( _msgStream ) ;
129+ rpcLogger . SetContext ( request . RequestId , null ) ;
130+
131+ response . WorkerInitResponse . WorkerMetadata = GetWorkerMetadata ( _pwshVersion ) ;
132+
133+ rpcLogger . Log ( isUserOnlyLog : false , LogLevel . Trace , string . Format ( PowerShellWorkerStrings . WorkerInitCompleted , stopwatch . ElapsedMilliseconds ) ) ;
134+ }
135+ catch ( Exception e )
136+ {
137+ status . Status = StatusResult . Types . Status . Failure ;
138+ status . Exception = e . ToRpcException ( ) ;
139+ return response ;
140+ }
141+
120142 return response ;
121143 }
122144
@@ -180,11 +202,10 @@ internal StreamingMessage ProcessFunctionLoadRequest(StreamingMessage request)
180202 return response ;
181203 }
182204
183- // Ideally, the initialization should happen when processing 'WorkerInitRequest', however, the 'WorkerInitRequest'
184- // message doesn't provide information about the FunctionApp. That information is not available until the first
185- // 'FunctionLoadRequest' comes in. Therefore, we run initialization here.
186- // Also, we receive a FunctionLoadRequest when a proxy is configured. Proxies don't have the Metadata.Directory set
187- // which would cause initialization issues with the PSModulePath. Since they don't have that set, we skip over them.
205+ // Ideally, the initialization should happen when processing 'WorkerInitRequest'. However, we defer the initialization
206+ // until the first 'FunctionLoadRequest' which contains the information about whether Managed Dependencies is enabled for the function app,
207+ // and if it is, we add the Managed Dependencies path to the PSModulePath.
208+ // Also, we receive a FunctionLoadRequest when a proxy is configured. This is just a no-op on the worker size, so we skip over them.
188209 if ( ! _isFunctionAppInitialized && ! functionLoadRequest . Metadata . IsProxy )
189210 {
190211 try
@@ -519,6 +540,17 @@ private void SetupAppRootPathAndModulePath(FunctionLoadRequest functionLoadReque
519540 . InvokeAndClearCommands ( ) ;
520541 }
521542
543+ private WorkerMetadata GetWorkerMetadata ( string pwshVersion )
544+ {
545+ var data = new WorkerMetadata ( ) ;
546+ data . WorkerBitness = RuntimeInformation . OSArchitecture . ToString ( ) ;
547+ data . WorkerVersion = typeof ( Worker ) . Assembly . GetName ( ) . Version . ToString ( ) ;
548+ data . RuntimeVersion = pwshVersion ;
549+ data . RuntimeName = "powershell" ;
550+
551+ return data ;
552+ }
553+
522554 #endregion
523555 }
524556}
0 commit comments