@@ -20,13 +20,15 @@ namespace Microsoft.Azure.Functions.PowerShellWorker
20
20
{
21
21
using System . Diagnostics ;
22
22
using LogLevel = Microsoft . Azure . WebJobs . Script . Grpc . Messages . RpcLog . Types . Level ;
23
+ using System . Runtime . InteropServices ;
23
24
24
25
internal class RequestProcessor
25
26
{
26
27
private readonly MessagingStream _msgStream ;
27
28
private readonly System . Management . Automation . PowerShell _firstPwshInstance ;
28
29
private readonly PowerShellManagerPool _powershellPool ;
29
30
private DependencyManager _dependencyManager ;
31
+ private string _pwshVersion ;
30
32
31
33
// Holds the exception if an issue is encountered while processing the function app dependencies.
32
34
private Exception _initTerminatingError ;
@@ -37,11 +39,12 @@ internal class RequestProcessor
37
39
private Dictionary < StreamingMessage . ContentOneofCase , Func < StreamingMessage , StreamingMessage > > _requestHandlers =
38
40
new Dictionary < StreamingMessage . ContentOneofCase , Func < StreamingMessage , StreamingMessage > > ( ) ;
39
41
40
- internal RequestProcessor ( MessagingStream msgStream , System . Management . Automation . PowerShell firstPwshInstance )
42
+ internal RequestProcessor ( MessagingStream msgStream , System . Management . Automation . PowerShell firstPwshInstance , string pwshVersion )
41
43
{
42
44
_msgStream = msgStream ;
43
45
_firstPwshInstance = firstPwshInstance ;
44
46
_powershellPool = new PowerShellManagerPool ( ( ) => new RpcLogger ( msgStream ) ) ;
47
+ _pwshVersion = pwshVersion ;
45
48
46
49
// Host sends capabilities/init data to worker
47
50
_requestHandlers . Add ( StreamingMessage . ContentOneofCase . WorkerInitRequest , ProcessWorkerInitRequest ) ;
@@ -95,6 +98,9 @@ internal async Task ProcessRequestLoop()
95
98
96
99
internal StreamingMessage ProcessWorkerInitRequest ( StreamingMessage request )
97
100
{
101
+ var stopwatch = new Stopwatch ( ) ;
102
+ stopwatch . Start ( ) ;
103
+
98
104
var workerInitRequest = request . WorkerInitRequest ;
99
105
Environment . SetEnvironmentVariable ( "AZUREPS_HOST_ENVIRONMENT" , $ "AzureFunctions/{ workerInitRequest . HostVersion } ") ;
100
106
Environment . SetEnvironmentVariable ( "POWERSHELL_DISTRIBUTION_CHANNEL" , $ "Azure-Functions:{ workerInitRequest . HostVersion } ") ;
@@ -117,6 +123,22 @@ internal StreamingMessage ProcessWorkerInitRequest(StreamingMessage request)
117
123
RemoteSessionNamedPipeServer . CreateCustomNamedPipeServer ( pipeName ) ;
118
124
}
119
125
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
+
120
142
return response ;
121
143
}
122
144
@@ -180,11 +202,10 @@ internal StreamingMessage ProcessFunctionLoadRequest(StreamingMessage request)
180
202
return response ;
181
203
}
182
204
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.
188
209
if ( ! _isFunctionAppInitialized && ! functionLoadRequest . Metadata . IsProxy )
189
210
{
190
211
try
@@ -519,6 +540,17 @@ private void SetupAppRootPathAndModulePath(FunctionLoadRequest functionLoadReque
519
540
. InvokeAndClearCommands ( ) ;
520
541
}
521
542
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
+
522
554
#endregion
523
555
}
524
556
}
0 commit comments