Welcome back to BackSpace Academy. In this lecture we're going to talk about 2
the Lambda service. We'll start off by talking about runtimes. What they are and 3
how they can set up our lambda instance when it's invoked and also we'll talk 4
about how a Lambda function executes. Then we'll talk about how we can develop 5
our code and package it and then deploy it to a Lambda function. We'll talk about 6
the different ways in which a Lambda function can be invoked. We'll talk about 7
how our Lambda function can connect to the internet, can connect to private 8
subnets, can connect to databases. Then we'll talk about how can get the maximum 9
performance out of our Lambda function and then finally we'll talk about how we 10
can monitor the performance of our Lambda function. A runtime is 11
run when the Lambda function is invoked. The first thing that it does it will 12
read the function setup code and that could be setting up that lambda instance 13
for running Nodejs or Python or whatever and there may be other things that need 14
to be set up as well for that Lambda function or that Lambda invoked instance. 15
Once that Lambda instance has been set up then the runtime will read the 16
handler name from an environment variable. Now the handler, that is a code 17
that you supply with maybe Nodejs or maybe Python whatever, but that is your 18
code that you are going to be running on this Lambda instance. It will then read 19
the invocation events. So for example if we had an s3 event that is triggered 20
when we upload an object into an s3 bucket then that event data will include 21
a whole heap of things. Among others it will have the s3 bucket name, it will 22
have the s3 object that was uploaded. So all of the information that was within 23
that event will be passed from the Lambda 24
runtime API and that information will then be passed over to the handler to process. 25
Then once a handler has done its bit and has done its code, it will post that 26
response back to the runtime and the runtime will then forward that on to the 27
lambda runtime API. Now there are managed run times that are 28
available for Nodejs, Python, Java, dotnet, Ruby and Go, now theoretically you can 29
create a custom runtime for any language that you want you're not limited to the 30
AWS managed runtimes but of course it's going to be a lot of work for you to 31
create your own custom runtime but if you want to do that it is possible. So a 32
custom run time it will run in the standard lambda execution environment, as 33
before it will use a runtime api to receive events and then send those 34
responses back. So the way that you set up a custom run time is that in your 35
functions runtime definition when you're creating that function you need to set 36
that to provided. Once you've done that you need to create a script and that 37
could be a shell script it could be a script in a language that 38
is included in the Amazon Linux distribution or it could be a binary 39
executable file. Once you've created that you put that inside of your deployment 40
package or within a layer within your deployment package and the entry point 41
that Lambda will be looking for provided the functions runtime is set to provide 42
it it will then look for an entry point called bootstrap. So that bootstrap will 43
be a script that will start to run that runtime executable or that runtime 44
script. 45
In order to understand lambda properly we need to understand the execution 46
context of an instance and this is going to be quite different to an ec2 instance 47
because these are temporary short-lived instances, so the execution context is a 48
temporary runtime environment that initializes those external dependencies 49
that our handler requires, our main code will reference a lot of external 50
dependencies, they could be libraries they could be packages whatever they are 51
and Lambda will maintain the execution context for some time allowing reuse 52
because the way that works is that when we invoke a lambda function it's going 53
to take time to initialize those external dependencies. So if we can reuse 54
those it's going to make the invocation time, that the latency to launch these 55
temporary instances, a lot quicker. The way that we can take advantage of the 56
execution context to reduce the invocation latency, the latency that it 57
takes to invoke these instances, is that we can have our objects declare outside 58
of the functions Handler and so when that function is disposed those methods 59
that are outside of that function handler method remain initialized. 60
That could be a database connection and so database connections they can take 61
quite a bit of time, that could take quite a few seconds for those to occur, 62
so keeping those database connections open and to be reused by other instances 63
makes sense. Another thing that we need to keep in mind is that we have a 64
temporary directory on all of our lambda instances. So normally when that instance 65
is terminated that temporary directory contents will also be lost, but for a 66
certain amount of time that remains and can be reused by other instances. Also 67
background processes and callbacks, if they're defined outside of the function 68
handler, may remain for a certain amount of time as well and so care must 69
be taken because you may lose content if it's in that temporary directory. So that 70
is temporary and make sure that you treat it as temporary also any unwanted 71
background processes that may still exist you need to make sure that those 72
are terminated when the instance is terminated. 73
In order to deploy a Lambda function you need to create a Lambda deployment 74
package and that is simply a zip archive that contains all of your function code 75
and its dependencies. You can create that zip archive and you can upload it 76
using the console when you're creating your Lambda function or you can put it 77
into an Amazon s3 bucket and reference at s3 bucket. If the deployment package 78
is greater than 50 MB you must use Amazon s3. Now your external packages 79
they don't need to be in that zip archive you can reference those in a 80
package JSON if it's a Nodejs application or in a requirements.txt 81
if it's a Python application and from there you can use the Sam CLI build 82
command which can create that package and put that in the correct location 83
ready for deployment. 84
When we have created our Lambda deployment package in a zip archive we 85
can go to the Lambda console and create that function and simply supply that 86
code or else reference an s3 bucket that has that code. We can also use cloud 87
formation and we do that by having a type AWS Lambda function and we need to 88
define some properties the code which will be the s3 bucket that contains that 89
code or if it's not very long we can just put the code as inline code 90
in that in that code property. We also have the handler and that will be the 91
code that Lambda calls to execute your function. So that will be the file and 92
also the name of the handler we also need to have a role for the Lambda 93
function. So that will define what permissions are that Lambda function 94
will have so we need to define an ARN or Amazon resource number of that role 95
and the type of runtime, what language are we going to be using is it going 96
to be Nodejs, is it going to be Python, Java. We need to define that as well 97
and it's a good idea to give it a function name but if it's missing cloud 98
formation will generate a unique one for you. We can also use the command line 99
interface or one of the many software development kits and we use a create 100
function command to do that and again we will need to define the code the handler 101
the role and the runtime for that command. 102
The serverless application model or Sam for short is a part of the cloud formation 103
specification and it can simplify the the deployment of our serverless 104
applications that may include not only Lambda but other services servers such 105
as API gateway. In order to tell cloud formation that we're going to be using 106
the serverless application model, in our template we need to have transform and 107
then AWS service command in there and then after that we need to define our 108
resources. As in any cloud formation template we must have resources. There 109
could be a combination of cloud formation and Sam resources. It could 110
be a function, api, state machine, a dynamodb table, but it could also have a 111
reference as well to an ec2 instance. It doesn't have to be simply serverless 112
resources that we're defining. There is also something that is unique to the 113
Sam model and that is the Global's and those that are used to define shared 114
configurations throughout this template. For example if all of your 115
instances that you are launching your Lambda instances are going to be using 116
the same NodeJS runtime, then you can use that runtime across all of those. You 117
don't need to, you can define it as a global and then share that across all of 118
those. You don't need to define that again and the same with the the handler 119
as well if you want to reuse that handler without having to define it for 120
every single one of those those definitions for a function and so we 121
have the Sam command-line interface and we can use the Sam build command and 122
that will prepare our code for deployment. It will read our Nodejs 123
package JSON or our Python requirements txt file and it will prepare that. 124
It will build our application ready for deployment and put it into the right 125
location for us and then we simply do Sam deploy and that will deploy our 126
application and then that application will appear in the Lambda console as an 127
application, and those Sam apps can be simply 128
managed using the Lambda console. If we make changes to our lambda functions 129
code, and we don't want to affect the current production version that is being 130
used what we can do is that we can publish a new version of that Lambda 131
function, and what that will do is that will create a new function that will 132
have a totally different Amazon resource name and so that won't affect our 133
current version which will have a different ARN. What we can do is that 134
we can make those changes to the code and then we can publish that new version 135
and that new version will include that code and any dependencies. It will 136
include the runtime from the previous version and any settings including the 137
environment variables. The way we create a new version is that we go into the 138
Lambda console. We select our function. We make the changes to our code and then we 139
simply publish a new version and that will create a new function with a new ARN 140
or we can go into the Amazon command line interface and we can use the 141
command Lambda publish - version. Now one thing that you need to take into 142
consideration is that when you have a changed ARN of a Lambda function any 143
resource to base policies that reference that ARN won't work anymore and also 144
any events that reference that ARN. For example you may have an s3 event that 145
triggers when something is uploaded to an s3 bucket and he that is referencing 146
the old ARN then that will no longer work or will no longer perform how you 147
expected to perform, so you need to take that into consideration. 148
Once a version has been published its code cannot be changed, so going 149
to the lambda console and trying to change that code, it just won't let 150
you do that, and so what you need to do is that you need to select the latest 151
version and that is your working version of that code you make your changes in 152
that and then you can publish another version, but once a 153
version has been published you cannot change it after. You have to just use 154
your current version and make your changes to the current version. In order 155
to overcome the problem of having these changing ARN every time we have a 156
different version, what we can do is that we can create an alias, and an alias is a 157
pointer to a specific version of a Lambda function and that alias will have 158
its own unique ARN and so we can update an alias that was pointing to an old 159
version and then we can get that to point to our new version and we're 160
keeping that same ARN. So we can get our our function code tested and working 161
properly and then we can use our alias to point to the new version and what we 162
can do is we can shift traffic between those two versions based on a percentage 163
of weights. So what we could do is that we could start off having only 10% of 164
our traffic going to the new version and then slowly migrate that over to all of 165
our traffic and that's going to reduce a headaches for us if there's any problems, 166
we're not going to get a big mass of users that are going to have problems, 167
and so those resource based policies and any events they can reference the alias 168
ARN and so always our alias ARN will be pointing to that version of that 169
Lambda function that we want as our production version. So we can 170
do that in the Lambda console or we can use the command line interface in the 171
command there is Lambda create - alias. 172
Environment variables are version specific key value pairs for example you 173
might have database name as a key and then the name of that database as a 174
value for that key and what they do is they allow you to store secret securely 175
and adjust your functions behavior without updating your code. So for 176
example it might have your database connection details such as a username 177
and password so you can update those without having to go into your code and 178
updating your code. It's also very important for storing those secrets 179
securely and outside of your functions code, it's far better to put them in 180
environment variables rather than hard coding them in your code. You need to 181
take into consideration that they cannot be changed after a version has been 182
published so you need to use your your latest working version and then 183
make those changes to those environment variables. So the way that we use 184
environment variables is that we can go into the Lambda console, we select our 185
function and we just do environment variables and add environment variable, 186
we can also use the AWS command-line interface or one of the many software 187
development kits and the command there is lambda and then update function 188
configuration and then - - environment and then we will define the variables 189
and the key and value of those variables. We can also use the serverless application 190
model or cloud formation. In the properties of our function we need to 191
define environment and then variables and then key and then the value. 192
As we have learned from our discussion on the execution context the invoking of 193
our Lambda function can be slowed down if a lot of packages and libraries need 194
to be initialized beforehand and also our zip archive can be quite big 195
if it includes these packages and libraries as well and so what we do is 196
we define that outside of our our lambda function handler and so that is going to 197
make sure that that can be reused later, and what we can also do is that we can 198
take advantage of putting all of these libraries and packages into a zip 199
archive and putting them into a layer and those layers can be reused by other 200
Lambda functions and that allows us to keep that deployment package small. We 201
can define up to five layers per function but the function code and all 202
of these layers must still be less than 250 MB we can use the Lambda console to 203
define a layer and upload that zip archive or we can use the AWS 204
command-line interface and the command is lambda update function configuration 205
and then the - - layers to define that layer. We can also use the serverless 206
application model or cloud formation and define it now template resources and the 207
resources will be libs and the type will be AWS serverless layer version and then we 208
just need to define the content URI, which will be the location of that zip 209
archive that contains all of these libraries and packages. 210
The serverless application repository is a managed repository for Sam applications 211
and it allows for us to share and reuse our applications and we can also search 212
for applications that have been made and published for open use by other users as 213
well and also by Amazon Web Services. The serverless application repository console 214
can be used to publish any of our Sam applications or we can use the CLI Sam 215
publish command which will also publish our application to the SAR. What we need 216
to do is that we need to include a metadata section into our Sam template 217
and that will include details such as our name, the name of the 218
application, the description, the license for that application and the source code 219
URL. If it's a github repository the source code URL for that as well. If we 220
want to use an application that's on the serverless application repository we can 221
simply go to the console and we can browse and search for that and we will 222
find any application that we've put on there or others have put on there that 223
are for public use or AWS has put on there. Once we've found one 224
that we'd like to use, we can configure that. We can set our environment 225
variables and any parameters for that, such as a size of our function and all 226
that sort of thing and then we can deploy them as a Sam application 227
and we can manage that in the Lambda management console. 228
There are a number of different ways of invoking a lambda function. If we want to 229
invoke a lambda function for testing we can simply use the lambda console after 230
we've created that function and we can simply test and that will invoke that 231
lambda function and it will send a test event to that Lambda function or we 232
can use one of the many software development kits or the command-line 233
interface. There are two different types of invocation the first one being 234
synchronous invocation which is a standard one and that is where we wait 235
for that function to process the event that we have sent to it and then we're 236
going to wait for that Lambda function to return a response. The other way that 237
we can invoke a Lambda function is with as synchronous invocation and in that 238
situation the Lambda service will queue the event for processing and it 239
will return a response immediately before that Lambda function 240
has even been invoked and so we don't have to wait around for that 241
response we're going to get a response straight away if we would like to take 242
advantage of a synchronous invocation we need to have an invocation type as event. 243
So events they can invoke a function directly for example you may have an s3 244
event on an Amazon s3 bucket, so when an object is uploaded to 245
that bucket an s3 event will trigger and directly invoke a Lambda function or 246
we can have the Lambda service itself can read an event source so that could 247
be a stream it could be a Kinesis stream or a dynamo DB stream or it could be an 248
sqs queue. So the Lambda service will read that and when it needs to it will invoke 249
a function and so that is called Lambda event source mapping. So here we can see 250
we've got synchronous invocation and in that way we've got our clients they 251
could be a resource it could be an iam user 252
whatever, it is has created an event and that has invoked a Lambda function and 253
those clients are waiting for a response to come back. So here we can see we've 254
got a synchronous invocation and so our clients are going to create an event and 255
that is going to go into an event queue and as soon as it goes into an event 256
queue so immediately the Lambda service will send a response back and then the 257
Lambda service will then invoke a Lambda function and pass the event details from 258
that event queue and finally we've got event source mapping and so here is 259
showing event source mapping with a Kinesis stream. So we've got our 260
user or resource or whatever that is creating records that are going into 261
a Kinesis data stream, so the Lambda service will be doing event source 262
mapping, it will be reading that Kinesis data stream and based on what's in that 263
Kinesis data stream, it will be invoking a lambda function and sending their 264
event as a batch to be processed by that Lambda function. If it fails to invoke 265
that Lambda function or the event fails to be processed then the event will go 266
into a failed event destination queue. 267
Services that invoke Lambda functions synchronously include the API gateway, 268
Lambda@Edge, Kinesis data firehose but as opposed to the Kinesis streams, data 269
firehose will be synchronously invoked, step functions will invoke synchronously 270
and application load balancer. Services that invoke asynchronously include 271
Amazon s3, SNS, SES, cloud formation, cloud watch logs & events and also 272
code commit and code pipeline. Services that Lambda reads events from by using 273
event source mapping and that is the streams and queue. So we've got Kinesis 274
streams, dynamodb streams and SQS queues. So Lambda 275
will read those and the Lambda service will invoke those Lambda functions based 276
on what's in those streams or in that queue. 277
By default a Lambda function cannot connect to any resources inside of a 278
private subnet in your VPC and the reason is because your VPC is your own 279
private space within the cloud and the Lambda service is not going to operate 280
inside of your private space in the cloud, it operates in the AWS VPC and so 281
what we need to do is that we need to associate that VPC with our lambda 282
function and then the lambda service will create network interfaces within 283
our private subnets that will allow those Lambda functions to connect to 284
private subnets or resources within a private subnet. Now because network 285
interfaces are being created it requires a role so our lambda service will 286
require an execution role to create network interfaces. So the way that we do 287
that is that in the Lambda console we associate a VPC the subnets and also 288
the security groups with the Lambda function. So we go into the Lambda 289
console we edit that Lambda function we scroll down into VPC and we define 290
custom VPC. Once that's done and it takes a little bit of time, the Lambda 291
service will go through and will create a network interface to 292
allow access within that private subnet. We can also use the command line 293
interface or one of the many software development kits and the command there 294
is Lambda create function or lambda update function configuration if it's an 295
existing lambda function and then we just need to define with a VPC config 296
the subnet IDs of our private subnets and any security group IDs as well. We 297
can also do that with Cloudformation or the serverless application model 298
and we just go into the function properties and we define VPC config and 299
again we define those subnet IDs for the private subnets and these security 300
groups IDs as well. Okay so here we can see how it all works so we've got the 301
AWS cloud and we've got our customer owned our VPC and AWS that they have 302
their AWS lambda VPC so we don't own that VPC, that's not our VPC, our 303
customer, our VPC is on the right hand side and the AWS VPC there is on the 304
left hand side and so our lambda functions are located inside of that AWS 305
at VPC so AWS so we'll create a VPC to VPC net instance or net service and so 306
that will connect to an elastic network interface that the Lambda service will 307
create inside of our VPC and so that will allow our Lambda functions to 308
access resources inside of those private subnets 309
by default your Lambda function also cannot connect to the internet so what 310
we need to do is that we need to have a VPC with a public subnet and being a 311
public subject it's going to have a route to an Internet gateway and we need 312
to allow our Lambda function to access the internet through that public subnet 313
and it does that again by creating a network interface inside of that public 314
subnet, so we require our lambda service to have a execution role to create 315
network interfaces, so when we're creating our function we need to define 316
that execution role that will have those permissions to create those network 317
interfaces then we have a public subnet and then our public subnet must 318
also have a NAT gateway or a NAT instance inside of it and that will 319
allow their outbound traffic once we've done that we can associate 320
that VP C and that public subnet to that function in a similar way that we 321
associate our private subnets as well and we do that again using the Lambda 322
console using the CLS DK's or also using cloud formation or the service 323
application model 324
as we know from our discussion on the execution context database connections 325
that need to be initialized can increase our functions invocation latency which 326
is not a good thing so what we need to do is that we need to make sure that our 327
our connections are defined outside of our function handler and that will allow 328
those for being reused after our function is to terminate it now even 329
better than that we can use the Amazon RDS proxy service if we're using RDS 330
instances or the RDS service and what that will do is it will maintain 331
connections for connections to that RDS service and it will have a single 332
endpoint for that so we need to have an execution role for our lambda function 333
that must have access to that database instance or the RDS proxy service that 334
we've set up and so that execution role can be used 335
for authenticating with the RDS proxy service instead of having to use a 336
username and password and so that again is going to reduce our latency we can 337
just jump straight in with that execution role and start using that that 338
database immediately without having to go through and supplying that username 339
and password 340
if we have a large amount of files that need to be accessed by our Lambda 341
functions we can connect our lambda functions to the elastic file system and 342
the EFS file system can be mounted to our functions local directory and it can 343
use that in the same way that it uses its temporary folder but it will use it 344
as a permanent storage and that permanent storage will also be used and 345
available for all of your functions so the way that we do that is that we can 346
use the Lambda console and then add file system or select our EFS volume and then 347
we'll define the local mount path and that will start with MNT and then you 348
will define that that local mount path what that will be and so from there your 349
Lambda function can access those those files through that local mount path or 350
we can use a CLI or the software development kits and the command there 351
is Lambda create function for a new function or Lambda update function 352
configuration for an existing function and then we simply do the file system 353
configs and define that elastic filesystem in there or we can use cloud 354
formation or this service application model and defining our template for our 355
functions properties define file assistant configs and then again define 356
that elastic filesystem 357
concurrency is that number of requests that your function is serving at a given 358
time and that is subject to a regional limit that is shared by all of your 359
functions so it's not possible to have a zillion concurrent invocations of your 360
functions it's subject to a regional or limit what you can do if you have got 361
critical functions that you want to make sure have a high level of concurrency 362
available you can define a reserved concurrency and that will ensure that 363
that function can always reach a certain level of concurrency but your other 364
functions they cannot use that reserve concurrency that you've allocated to 365
that function if you find that you that you have a certain time period that you 366
want to provision a certain amount of concurrency for then you can use 367
provisioned concurrency and that allows you to allocate a level of concurrency 368
before they increase in invitations from an increase in demand occurs and that 369
will ensure that those requests are served by initialized instances so it 370
will not only make sure that the concurrency is available it will make 371
sure that those instances are initialized and ready to go we can also 372
use the AWS application auto scaling service to manage this provision 373
concurrency so making sure that we have initialized instances available and we 374
can do that based on a schedule or we can do that based on demand based on 375
utilization in the same way that we do with it with a ec2 auto scaling group we 376
can have this we can have this provision concern see of these provisioned 377
instances or in vacations auto scaling automatically for us but of course you 378
also need to take into consideration that it may be cheaper 379
to use an auto scaling ec2 group rather than using Lambda because you're paying 380
for the convenience of a service service so make sure that you you do your 381
testing and make sure that there's no cost to you of using this this great 382
service of having these great out-of-the-box scaling in and out using 383
the application auto scaling when you create a Lambda function and you define 384
its configuration the atlandis service will allocate the CPU power of that 385
function linearly in proportion to the amount of memory that you have 386
configured what that means is that you cannot directly change the CPU power of 387
a Lambda function what you can do is that you can increase the memory of that 388
function significantly and that will increase the CPU power at 1792 and make 389
a function has equivalent of one 4v CPU so if you double the memory then that 390
will allow for 2 4 V CPUs so setting the memory for a lambda function implicitly 391
sets not only the CPU power but also the network power or the network 392
connectivity and also some other resources as well so memory is your main 393
thing that you define if you're finding that your function cannot handle your 394
code increase the memory of that function 395
land of functions can be used as a target for an application low balancer 396
and that has a number of significant advantages it allows requests to be 397
received from the internet by the application low balances single endpoint 398
it also allows you to create load balancer rules to route those HTTP 399
requests to a specific function based upon a path or based upon values inside 400
of the header of that request and that is very important because you could have 401
a Lambda function for for e-commerce a Lambda function for image processing and 402
you can define the exact resources that you want to do that you could also have 403
those critical functions having a higher level of concurrency available to other 404
functions that aren't so critical and making sure that those requests go to 405
those right locations of those critical those critical functions now the alb it 406
invokes those functions synchronously with an event containing the request 407
body and any metadata with that request 408
by default land that monitors your functions and sends metrics for those 409
functions to the cloud watts service and you can view those those monitoring 410
graphs of those metrics in the Lambda console okay in the dashboard here we've 411
got we can see the invitations that will be the number of invitations at that 412
point in time so if there's 20 invitations of a function that will show 413
up there the duration that the invitation lasted for the error counts 414
and the success rate the number of times that the the function needed to be 415
throttled due to too many requests we also have their iterator age what that 416
is is that when we're using Lambda service with a stream or with a s qsq it 417
will be the age from when that record entered the stream to when the Lambda 418
function was in vote and so that more vary depending hobb on how big that 419
stream is and qyz we also have dead letter errors and so those will be 420
errors or there will be requests that could not be served by the Lambda 421
function and they will go into a dead letter Q 422
the metrics that are sent to the cloud service after your function has 423
processed an event can be divided into three main types being invocation 424
performance or concurrency metrics the first one there is invocations a number 425
of in the invocations of our function that we have at that point in time the 426
errors at that point in time the number of times that the function needed to be 427
throttled we have the provision concurrency implications how many of 428
those vacations are on provision concurrency how many of those are from 429
provision concurrency spillover into standard invitations also we have as 430
synchronous ones as purely for synchronous invitations and they are the 431
dead letter error so where a event failed to be delivered and also it 432
failed to enter the dead letter queue as well and also we have destination 433
delivery failures where that event failed to be delivered as well we also 434
have there the performance metrics being the duration of that of that invocation 435
and the iterator age so where we're using a stream or a queue the age of 436
that record from when it entered that stream to win the Lambda service invoke 437
that function and the concurrency metrics so the concurrent executions of 438
that function the provision concurrent execution to how many of those are 439
provisioned concurrency and the provision concurrency utilization how 440
much are we utilizing of that provision concurrency and our unreserved 441
concurrency execution so how many of those are operating on unreserved to 442
concurrency when you create a lambda function the 443
Lambda service automatically creates a cloud watch log group for that that 444
Lambda function and whenever that Lambda function is invoked it will create a log 445
stream for each of those indications of that Lambda function and when that 446
Lambda function is invoked its runtime will send details about each of those 447
invitations to that specific logger stream now we can also take advantage of 448
this cloud watch log in this log stream by sending details about what's 449
occurring in our code so we can send a command they can send a message to that 450
log stream the way that we do that is at where function code that outputs to the 451
console will output to that quell our watch logs because our lambda service 452
doesn't have a console scream so it outputs that directly to our cloud watch 453
log so the way that we do that is we use the console dot log command in nodejs 454
or the print command in python and that will send that that message 455
whatever is in that console.log command or that print command will go 456
directly to that log stream. 457
If we want to monitor access to the Lambda service and our Lambda functions 458
we can use the cloudtrail service to do that and cloudtrail will capture all of 459
the API calls made to Lambda from the console from the command line interface 460
or from one of the many software development kits and it will store that 461
in a cloudtrail log and that will in each one of those entries will have the 462
IP address of that user it will have the IAM user or the role that was used to 463
access Lambda and also the timestamp of that API call. So if a trail is enabled 464
then all of the events will be saved to Amazon s3. If you haven't enabled a trail 465
you can still see the most recent events in the cloud trail console log event 466
history. So that brings us to the end of a pretty detailed discussion on the 467
Lambda service and it's a great service and a really fun one to get your hands on. So 468
coming up next we're going to have some labs on Lambda and I hope you enjoy 469
those and I look forward to seeing you in the next ones.