Writing to the container execution log
Note
Logging is not free of charge. For more information, see the Yandex Cloud Logging documentation.
- In the management console
, select the folder with your container. - Select Serverless Containers.
- Select the container you want to configure logging for.
- Go to the Editor tab.
- Under Logging, select the following in the Destination field:
Not specified
: To disable logging.Folder
: To write logs to the default log group for the folder the container is in.- (Optional) In the Min. logging level field, select the minimum logging level.
Log group
: To write logs to a custom log group.- (Optional) In the Min. logging level field, select the minimum logging level.
- In the Log group field, select the log group to write the logs to. If you do not have a log group, create one.
- At the top of the page, click Create revision.
If you set the minimum logging level, logs of that level and higher will be written to the execution log. With no minimum logging level set, all container logs will be written to the execution log.
If you do not have the Yandex Cloud command line interface yet, install and initialize it.
The folder specified in the CLI profile is used by default. You can specify a different folder using the --folder-name
or --folder-id
parameter.
Logging destination
If a custom log group is not specified in the container revision parameters or logging is not turned off, the container automatically writes all logs to the default log group for the folder it resides in.
To write logs to a custom log group, provide the log group ID in the --log-group-id
parameter when creating a container revision. The log group must reside in the same folder as the container.
Minimum logging level
To set a minimum logging level, specify it in the --min-log-level
parameter when creating a container revision.
If you set the minimum logging level, logs of that level and higher will be written to the execution log. With no minimum logging level set, all container logs will be written to the execution log.
Disabling logging
To disable logging, specify the --no-logging
parameter when creating a container revision.
Command example
To write logs to a custom log group, run this command:
yc serverless container revision deploy \
--container-id <container_ID> \
--image <Docker_image_URL> \
--service-account-id <service_account_ID> \
--log-folder-id <folder_ID> \
--min-log-level <minimum_logging_level>
Where:
--container-id
: Container ID. To find out the ID, get a list of containers.--image
: Docker image URL.--service-account-id
: ID of the service account with permissions to download a Docker image.--log-group-id
: ID of the log group to write logs to.--min-log-level
: Minimum logging level. This is an optional parameter.
Result:
done (5s)
id: bba9vrtrjlld********
container_id: bbanb9mvu1dl********
created_at: "2024-05-08T07:22:45.378Z"
image:
image_url: cr.yandex/crprip91p1q9********/ubuntu:hello
image_digest: sha256:aa55c46fba9b14b8d8de16e2f8a07d716edfb1dbbb9433b827214ad2********
resources:
memory: "1073741824"
cores: "1"
core_fraction: "100"
execution_timeout: 3s
service_account_id: ajeh91ebakk1********
status: ACTIVE
log_options:
log_group_id: e23824sf51g5********
min_level: ERROR
Terraform
For more information about the provider resources, see the documentation on the Terraform
If you change the configuration files, Terraform automatically detects which part of your configuration is already deployed, and what should be added or removed.
If you don't have Terraform, install it and configure the Yandex Cloud provider.
Logging destination
If a custom log group is not specified in the container revision parameters or logging is not turned off, the container automatically writes all logs to the default log group for the folder it resides in.
To write logs to a custom log group, in the log_options
section, provide the log group ID in the log_group_id
parameter when creating a container revision. The log group must reside in the same folder as the container.
Minimum logging level
To set a minimum logging level, specify it in the log_group_id
parameter when creating a container revision.
If you set the minimum logging level, logs of that level and higher will be written to the execution log. With no minimum logging level set, all container logs will be written to the execution log.
Disabling logging
To disable logging, under log_options
, set the disabled
parameter to true
when creating a container revision.
Example
To write logs to a custom log group:
-
Open the Terraform configuration file and add the
log_options
section to theyandex_serverless_container
resource description:Here is an example of the configuration file structure:
resource "yandex_serverless_container" "<container_name>" { name = "<container_name>" service_account_id = "<service_account_ID>" memory = <RAM_amount> image { url = "<Docker_image_URL>" } log_options { folder_id = "<folder_ID>" min_level = "<minimum_logging_level>" } }
Where:
name
: Container name.service_account_id
: ID of the service account with permissions to download a Docker image.memory
: Required memory. The default value is 128 MB.url
: Docker image URL.folder_id
: Folder ID.min_level
: Minimum logging level. This is an optional parameter.
For more information about the
yandex_serverless_container
resource parameters, see the provider documentation . -
Create resources:
-
In the terminal, change to the folder where you edited the configuration file.
-
Make sure the configuration file is correct using the command:
terraform validate
If the configuration is correct, the following message is returned:
Success! The configuration is valid.
-
Run the command:
terraform plan
The terminal will display a list of resources with parameters. No changes are made at this step. If the configuration contains errors, Terraform will point them out.
-
Apply the configuration changes:
terraform apply
-
Confirm the changes: type
yes
in the terminal and press Enter.
-
To write to the container execution log, use the deployRevision REST API method for the Container resource or the ContainerService/DeployRevision gRPC API call.
Structured logs
Apart from text, you can write structured logs to the standard output stream (stdout
) and standard error output stream (stderr
).
Applications and Dockerfile examples
index.js
const winston = require('winston');
const express = require('express');
const logger = winston.createLogger({
level: 'debug',
format: winston.format.json(),
transports: [new winston.transports.Console()],
});
const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.get("/", (req, res) => {
logger.info({"message": "My log message", "my-key": "my-value"})
return res.send("Hello, world!");
});
app.listen(process.env.PORT);
Dockerfile
FROM node:16-slim
WORKDIR /app
RUN npm install winston express
COPY ./index.js .
CMD [ "node", "index.js" ]
requirements.txt
python-json-logger==2.0.4
sanic==22.12.0
index.py
import logging
import os
from pythonjsonlogger import jsonlogger
from sanic import Sanic
from sanic.response import text
class YcLoggingFormatter(jsonlogger.JsonFormatter):
def add_fields(self, log_record, record, message_dict):
super(YcLoggingFormatter, self).add_fields(log_record, record, message_dict)
log_record['logger'] = record.name
log_record['level'] = str.replace(str.replace(record.levelname, "WARNING", "WARN"), "CRITICAL", "FATAL")
app = Sanic(__name__)
logHandler = logging.StreamHandler()
logHandler.setFormatter(YcLoggingFormatter('%(message)s %(level)s %(logger)s'))
logger = logging.getLogger('MyLogger')
logger.propagate = False
logger.addHandler(logHandler)
logger.setLevel(logging.DEBUG)
@app.route("/")
async def hello(request):
logger.info("My log message", extra={"my-key": "my-value"})
return text("Hello, world!", status=200)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=int(os.environ['PORT']), motd=False, access_log=False)
Dockerfile
FROM python:3.10-slim
WORKDIR /app
COPY ./index.py .
COPY ./requirements.txt .
RUN pip install --no-cache-dir --prefer-binary --requirement=./requirements.txt
CMD [ "python", "index.py" ]
index.go
package main
import (
"go.uber.org/zap"
"net/http"
"os"
)
func main() {
zapConfig := zap.NewProductionConfig()
zapConfig.DisableCaller = true
zapConfig.Level.SetLevel(zap.DebugLevel)
logger, _ := zapConfig.Build()
portStr := os.Getenv("PORT")
http.Handle("/", handler{logger})
http.ListenAndServe(":"+portStr, nil)
}
type handler struct {
logger *zap.Logger
}
func (h handler) ServeHTTP(writer http.ResponseWriter, _ *http.Request) {
h.logger.Info(
"My log message",
zap.String("my-key", "my-value"),
)
writer.WriteHeader(200)
_, _ = writer.Write([]byte("Hello, world!"))
}
Dockerfile
FROM golang:latest AS build
WORKDIR /app
ADD index.go .
ADD go.mod .
ADD go.sum .
RUN go build -a -tags netgo -ldflags '-w -extldflags "-static"' -o server-app *.go
FROM scratch
COPY --from=build /app/server-app /server-app
ENTRYPOINT ["/server-app"]