Prepare and test your skills
Prepare and test your skills
Collecting telemetry (opens in a new tab) is the end-to-end pipeline that moves host, application, audit, and network signals from where they are generated into Cloud Logging, Cloud Monitoring, and Cloud Trace for storage and analysis. Host data flows from virtual machines, application data flows from instrumented code through receivers and collectors, and platform data flows from Google Cloud control planes and networks through audit and flow logs. Aggregated sinks then centralize those entries so security, troubleshooting, and compliance can operate on one copy.
The Ops Agent is the primary single-process collector for Compute Engine virtual machines (VMs) that gathers host metrics and system logs without extra configuration. The Ops Agent uses Fluent Bit for high-throughput multi-core log collection and the Google-built OpenTelemetry Collector (opens in a new tab) for metrics and traces, and it installs with one download and one YAML file with proxy support. By default the Ops Agent collects CPU, GPU, memory, and process metrics plus system logs such as Linux /var/log/syslog, /var/log/messages, and Windows Event Log, while VMs without the agent report only basic signals.
Custom collection in the Ops Agent is defined in config.yaml with logging receivers, processors, and pipelines that connect sources to Cloud Logging. A receiver defines where data comes from, a processor defines how entries are transformed or filtered, and a pipeline binds receivers and processors to an export destination in the VM project. Telemetry flows from the log source to the receiver, then through each processor in order, then from the pipeline to Cloud Logging.
Receivers cover sources beyond the defaults:
Processors normalize entries before export by parsing text into structured logs with JSON or regular-expression parsing, modifying entries by removing or renaming fields, excluding unwanted logs by labels and expressions, and concatenating multiline Java, Python, and Golang exceptions. Applications should therefore write JSON-structured logs to a file first, then let the receiver tail that file while processors normalize severity and fields.
Cloud Audit Logs is the platform audit system that writes immutable entries to Cloud Logging for Google Cloud API activity. Entries are organized into four types that differ by trigger and default enablement.
| Log type | Records | Enablement |
|---|---|---|
| Admin Activity | Control-plane writes such as VM creation, IAM change, or cluster deployment | Always written; cannot be disabled or excluded |
| Data Access | Reads of user data such as get, list, or BigQuery select | Disabled by default because volume and cost can be large |
| System Event | Google-initiated maintenance and lifecycle actions | Available for system-generated events |
| Policy Denied | Access attempts denied by policy checks | Available for denied-access auditing |
Access is split by role: applications need roles/logging.logWriter to send entries, humans need roles/logging.viewer to view logs and logging.privateLogViewer for Data Access logs, and administrators need roles/logging.configWriter to create centralizing sinks. Troubleshooting flows from scope to log type to query in Logs Explorer by selecting the organization or project and resource type such as k8s_cluster, choosing activity, data_access, system_event, or policy, filtering on logName and protoPayload.serviceName, and inspecting protoPayload for method, identity, and resource.
Network telemetry extends audit history with packet movement and policy decisions. VPC Flow Logs record connection details for subnets, firewall logs record compute.googleapis.com/firewall allow and block decisions, NAT flow logs record gateway translations, and DNS query logs record resolver activity. Traffic flows from subnets, firewall rules, NAT gateways, and resolvers to Cloud Logging, where sampling rate and metadata annotations control detail for latency diagnosis. An aggregated sink created at the folder or organization level with gcloud logging sinks create plus --include-children routes matching logs from all child projects to one destination, but routing fails until the sink writerIdentity service account is granted write access. Routing copies entries without moving them, so Cloud Logging stores logs twice unless operators add an exclusion filter to child _Default sinks.
A Log Bucket is the Cloud Logging storage container that holds routed entries and enforces retention, region, and Identity and Access Management (IAM) access control. Every project includes _Required and _Default sinks, and every stored entry follows a retention lifecycle where it is kept for a retention period and then deleted. Excluding low-value entries stops cost before ingestion and storage, while shorter retention stops ongoing accumulation, and a bucket upgraded to Observability Analytics for SQL querying cannot be downgraded.
The Log Router evaluates every incoming entry against sinks and forwards matching entries to destinations. A sink contains an inclusion filter that selects entries and exclusion filters that discard matches before storage, so a dropped entry consumes no bucket storage. Source category shapes filtering because platform logs, component logs, security logs, user-written logs, and multicloud logs differ in value, while high-volume debug logs, successful health checks, and repetitive requests are first candidates for exclusion. Volume can also be reduced without dropping streams by sampling request logs, stripping verbose fields with transforms, and masking sensitive fields with redaction.
Destination choice determines query tools, retention, and cost:
Exam tip: Keep short retention in a Log Bucket for troubleshooting and route only high-value logs to BigQuery, because BigQuery adds query-computation cost while Cloud Storage with lifecycle downgrade is cheaper for rarely accessed archives.
Monarch is the globally scalable datastore behind Cloud Monitoring and Google Cloud Managed Service for Prometheus. Data storage in Monarch retains Prometheus data for 24 months, while query evaluation executes PromQL and unions results across all regions and up to 3,500 projects. The metrics scope of a project controls which stored series that project can chart, because by default the scope limits the project to series it stored itself. An operator expands visibility by adding other projects, so alerts, dashboards, and objectives operate over the consolidated set.
Collectors run near each workload and forward to Monarch, so workloads do not need exposure to the global query layer. The Ops Agent collects host CPU, disk, memory, swap, GPU, process, and third-party signals for Apache, Nginx, MySQL, Redis, MongoDB, PostgreSQL, and Java Virtual Machine, and it can scrape Prometheus endpoints and receive OTLP metrics and traces. BindPlane maps on-premises and hybrid metrics into time series stored by a Google Cloud project for the same scope, PromQL, dashboards, and alerting.
| Collector | Configuration model | Choose when |
|---|---|---|
| Managed collection | Kubernetes operator with PodMonitoring resources | Hands-off Kubernetes scraping, scaling, and sharding are needed |
| Self-deployed collection | Drop-in Prometheus binary with existing configs | Complex existing setups must be reused or edge rules must run locally |
| OpenTelemetry Collector | Single agent for metrics, logs, and traces | Push collection, exemplars, or cross-signal workflows matter |
| Ops Agent | Prometheus-like receiver on Compute Engine | VMs need simple discovery plus logging and process metrics |
Cloud Service Mesh telemetry flows from Envoy proxies in the data plane to Google Cloud Observability, where the managed control plane distributes routing and telemetry configuration. Envoy proxies batch each signal on its own schedule, so logs arrive about every 10 seconds, metrics and topology edges about every 1 minute with full topology about every 10 minutes, and traces by sampling typically 1 in 100 requests. Because traffic flows from the client-side Envoy to the server-side Envoy to the destination, both sides can emit telemetry for the same request, which lets operators compare client-observed versus server-observed latency. Dashboards show metrics only for HTTP(S) and gRPC services whose Kubernetes Service port is named http or starts with http-.
A synthetic monitor is a proactive probe that simulates user behavior against endpoints and workflows on a schedule from global locations. A generic HTTP validation sends a real HTTP request to one URL or API and asserts on status and content, which fits pinging a website or validating an API contract. A broken-link checker starts at an origin page and validates many linked pages with browser rendering, which fits marketing sites and portals where one broken link blocks the next step. At runtime traffic flows from the Mocha it block through fetch to an assertion such as expect(externalRes.ok).to.be.true, while the broken-link path flows from the scheduler to runBrokenLinksHandler(options) to the origin page to each discovered link with Puppeteer rendering.
Probe behavior is controlled by an options object with origin_uri, link_limit, selectors, link_order, link_timeout_millis, max_retries, total_synthetic_timeout_millis, and screenshot options. Assertions turn responses into pass or fail, where expected_status_code can require 304 or a class such as STATUS_CLASS_3XX, and per_link_options maps a specific URL to its own expected status while strict success remains elsewhere. Probes that use Puppeteer need at least 1GiB of memory, and retries must fit inside the total timeout. Correlation locates root cause by comparing synthetic failures against backend CPU, memory, queues, and database latency in the same window.
Custom metric pipelines move data from writers to readers through an ordered chain from instrumented application, Ops Agent, Logging, or Managed Service for Prometheus into time series stored against a monitored resource. Every custom point must attach to a monitored resource, and generic_task or generic_node with distinct labels is preferred over global with only project_id because shared global objects can collide. A MetricDescriptor defines type name, description, unit, labels, kind, and value type, with prefixes custom.googleapis.com/, workload.googleapis.com/, external.googleapis.com/user, and external.googleapis.com/prometheus.
| Metric kind | What it stores | Example |
|---|---|---|
| GAUGE | Value at a moment in time | Hourly temperature or queue depth |
| CUMULATIVE | Accumulated total at a moment | Vehicle odometer reading |
| DELTA | Change over a period | Stock gains for a period |
Log-based metrics turn log entries into numeric series without code changes, where data flows from the log entry to the Log Router to the metric to Cloud Monitoring. User-defined log-based metrics can only be counter or distribution types, start counting only after creation with no backfill, and are named logging.googleapis.com/user/NAME. Counter metrics count matches such as 404 Not Found, while distribution metrics store count, mean, sum of squared deviations, and histogram buckets for latency percentiles.
Continue with this study guide: Instrumenting and collecting telemetry
Analyzing logs with Cloud Logging (opens in a new tab) means filtering stored entries with precise Boolean expressions and diagnosing them with visual tools. Cloud Logging uses the same Logging query language in Logs Explorer, the Logging API entries.list method, the gcloud logging read command, and in filters for sinks and log-based metrics. Every query tests indexed LogEntry fields such as resource.type, severity, logName, timestamp, textPayload, jsonPayload, and protoPayload.
The Logging query language builds filters from comparisons joined by logical operators. A comparison is either a global value or a [FIELD_NAME] [OP] [VALUE] test, joined as ["NOT"] comparison { ("AND" | "OR") ["NOT"] comparison }. A simple restriction such as resource.type = "k8s_cluster" tests one field, a conjunctive restriction such as resource.type = "k8s_cluster" AND severity = "ERROR" requires both, and a disjunctive restriction such as resource.type = ("k8s_cluster" OR "gce_instance") matches either. Parentheses control order in complex expressions, separate lines join with implicit AND, and AND, OR, and NOT must be capitalized.
Log names must use the full encoded path because the short display name does not match. The Admin Activity audit log is named cloudaudit.googleapis.com/activity, so the correct test is logName = "projects/my-project-id/logs/cloudaudit.googleapis.com%2Factivity" with %2F for the slash. A precise source filter combines that encoded logName with nested labels such as resource.type = "gce_instance" AND resource.labels.instance_id = "6731710280662790612". Queries cannot exceed 20,000 characters, field names and most string comparisons are case-insensitive, and regular expressions remain case-sensitive.
Exam tip: logName = "projects/my-project-id/logs/activity" matches nothing; use logName = "projects/my-project-id/logs/cloudaudit.googleapis.com%2Factivity" with URL encoding.
Payload and time filtering isolates the exact message and failure window while keeping queries fast. The path textPayload tests unstructured text, jsonPayload.my_favorite_cat tests a field inside JSON, and protoPayload.metadata.event.eventName tests an audit event name. Checking one entry first reveals correct label and payload names, while time filtering uses timestamp with RFC 3339 values that include T, such as timestamp >= "2023-06-27T12:40:00-04:00" AND timestamp <= "2023-06-27T14:40:00-04:00".
| Match style | Match behavior | Choose when |
|---|---|---|
Equality with = | Matches complete field value | Full value is known and precision matters |
Has with : | Substring match inside field | Part of text is known but full value is not |
SEARCH() function | Case-insensitive match on complete text | Case-insensitive search is needed without partial-word matching |
A bare quoted value is a global restriction that implicitly searches every field and is the slowest form. Index-friendly queries prefer conjunctive AND tests on indexed fields such as logName and resource.type and avoid global or substring searches. Queries that use only AND can use indexes better and run faster than OR queries, so when OR is required, grouping clauses with parentheses preserves logic.
Logs Explorer is the console interface for displaying, parsing, and analyzing entries stored in log buckets. The interface combines five areas: the Query pane builds filters, the Fields pane surfaces values and patterns, the Timeline visualizes entries across the time range, the Query results pane lists matches, and the toolbar controls time range, streaming, sharing, and display. The Timeline shows spikes, gaps, or clusters to drill into, while the Fields pane spots anomalous values without reading every payload. Severity provides triage, where severity >= "ERROR" isolates error and critical entries.
Correlation groups entries that share the same trace field into a parent-child view, which simplifies tracing one request across microservices. Trace context originates from OpenTelemetry OTLP data or native writers such as App Engine, Cloud Run functions, and Cloud Run, while Compute Engine and Google Kubernetes Engine (GKE) include trace data when they use the Ops Agent or OpenTelemetry Collector. For correlation all requirements must hold: the trace field is set to TRACE_ID or projects/PROJECT_ID/traces/TRACE_ID, the value is the same across the group, each entry has a different logName, and the parent timestamp is no later than any child timestamp.
To view correlated entries in order:
request_log for App Engine.If an expanded parent shows no children, no other entries in the time range share that trace ID, so widening the range or removing a restrictive filter is next.
Converting log queries into metrics and analytics assets turns a one-time filter into a saved query or continuously evaluated signal. The same Logging query language expression runs in Logs Explorer, the Logging API, and the CLI, so a validated filter can run through gcloud logging read or entries.list without changing logic. When counting, grouping, or trending is needed, the workflow moves to Observability Analytics or to a log-based metric that feeds Cloud Monitoring.
| Interface | Query language | Choose when |
|---|---|---|
| Logs Explorer | Logging query language | Task is finding and viewing individual matching entries |
| Observability Analytics | SQL, including pipe syntax | Task is grouping by hour, averaging latency, counting patterns, or charting trends |
Logs Explorer does not support aggregation like counting entries with a pattern. To aggregate, analytics must be enabled on the bucket and then Observability Analytics must query log views with system schemas or analytics views with user schemas. Entries written before upgrade become analyzable only after backfill, which can take days, and linked BigQuery datasets allow BigQuery to query log data without export. A log-based metric applies a filter to incoming entries so every new match contributes to a Monitoring time series that can be charted and alerted, for example counting sensitive-content accesses.
Exporting and retaining logs means routing copies through sinks to central destinations and keeping them for the required time at lowest cost. Cloud Logging routes entries through sinks to a central logging bucket, Cloud Storage, BigQuery, or Pub/Sub, and each destination enforces its own retention and access. Retention in buckets is configurable from 1 day to 3650 days, while exported copies use locks and partition expiration. Every sink has a writer identity, which is a Google-managed service account, and flow succeeds only after that identity is granted write permission on the destination.
Securing the pipeline requires separation of Cloud Logging roles and permissions (opens in a new tab) for sink management, destination access, and analysis, including Project IAM Admin, Storage Admin, Service Usage Admin, Logging Admin, and Cloud Run Developer for import jobs. Admin Activity audit logs are always written and cannot be configured, excluded, or disabled, even if the Logging API is disabled. Bucket-level retention applies to the entire bucket for 1 to 3650 days regardless of log type, so logs with different needs must use different buckets. A central bucket for organization analysis is created in fixed location global, us, or eu that cannot change, and Bucket Lock prevents early deletion.
| Destination | Primary strength | Choose when |
|---|---|---|
| Cloud Storage | Long-term, cost-effective preservation | Compliance requires infrequent-access audit retention |
| BigQuery | Multi-dimensional analytical querying | Teams need SQL over large organization-wide volumes |
| Pub/Sub | Real-time streaming integration | Logs must flow to apps, third parties, or external SIEM |
Building the centralized export pipeline follows a fixed sequence: set up a single destination with gcloud logging buckets create or bq mk in the aggregation project, create an aggregated sink at organization or folder level, grant the sink writer identity write permission, grant analysts read access, and verify that new matches arrive and are queryable. A separate bucket is recommended instead of reusing _Default so retention, location, and analytics upgrades stay isolated.
Handling sensitive data in logs means preventing, hiding, or transforming regulated fields such as personally identifiable information (PII) and protected health information (PHI) while keeping logs useful. Prevention is most reliable because data never logged cannot leak, so workloads must not place PII, PHI, or credentials in experiment output, resource metadata, build files, or request fields that Logging will capture. Audit logs never include resource contents or query results, but they capture metadata, so names, labels, and request fields are a redaction boundary.
| Mechanism | Scope of hiding | Choose when |
|---|---|---|
| Log views on a log bucket | Entire LogEntry that does not match filter | Different teams should see different subsets |
| Field-level access controls on a log bucket | Individual LogEntry fields such as a PII field | Most users need the log but must not see one field |
Field-level access is finer but carries a tradeoff: Observability Analytics cannot query buckets with field-level controls, so log views must be chosen when analytics compatibility matters. Transformation with Sensitive Data Protection preserves utility through pseudonymization, tokenization, and generalization such as bucketing, where data flows from source log through inspection to de-identified output. Classification uses infoTypes for patterns such as credit card numbers and emails, where direct identifiers identify alone, quasi-identifiers identify when combined such as ZIP plus birth date, and other regulated data covers credentials and health context. Discovery generates data profiles with sensitivity and risk metrics that can flow to Security Command Center and Google SecOps.
Compliance strategy minimizes what is logged, regionalizes where it is stored, limits how long it is kept, encrypts with required key control, and restricts who can read it. Buckets are regional resources, so organizations configure default locations and centralize by region, while Pub/Sub message storage policies and Assured Workloads enforce boundaries. By default Admin Activity and System Event logs are retained 400 days and Data Access logs 30 days, after which copies must live in Cloud Storage or another product. Users with Logs Viewer can access Admin Activity, while Data Access requires Private Logs Viewer, with least privilege, IAM Conditions, and just-in-time elevation further limiting privilege.
Gemini Cloud Assist is an AI collaborator that analyzes operational data to speed diagnosis of complex problems. Interactive chat in the Cloud Assist panel answers questions using current page, project ID, and session memory, while Investigations performs deeper automated analysis inside workflows such as Logs Explorer. All AI output must be validated against raw logs, metrics, and configuration because Gemini can produce plausible but incorrect responses.
The Investigation Overview pane organizes results into three parts: Issue with description including start and stop time, Findings with ranked observations about anomalies, and Hypotheses with recommended remediation. For databases an investigation compares baseline against client latencies, server latencies, CPU, disk, and request count. Implementation turns validated results into operations in order: validate insight in Logs Explorer and dashboards, contain the incident, correct code or configuration through normal deployment, harden monitoring to diagnostic signals, and escalate with context to a Google Cloud support case if unresolved. As of April 10, 2026, creating, running, and editing investigations requires a Premium Support contract.
Continue with this study guide: Managing and analyzing logs
Correlating metrics in Cloud Monitoring means querying related time series together to trace degradation back to its origin. No single chart explains an outage, so analysis compares frontend latency and errors against backend CPU, memory, and storage errors over the same window. Confidence comes from aligning timing, scope, and distribution rather than from any single spike.
The correlated data set comes from several collection paths stored as numeric series in a project:
The metrics scope controls which series can be charted together, because by default a project sees only series it stored. The scope must be expanded to include other projects for multi-project correlation. A time series is identified by metric.type such as compute.googleapis.com/instance/cpu/utilization plus labels such as instance_name, and Monitoring writes one series per combination of resource and metric labels. GAUGE stores point-in-time value, CUMULATIVE stores accumulated total, and DELTA stores change over a period, while DISTRIBUTION preserves spread for percentiles.
Metrics Explorer selects a monitored resource type and metric, then refines with filtering, grouping, and aggregation before overlaying related metrics on the same timeline. Charts can be saved to a custom dashboard once a useful view is found. Google-managed dashboards are created automatically for instantiated resources and App Hub applications, while custom dashboards are required for trends, outliers, or multi-metric comparisons and can combine metric charts with logs, error groups, alert charts, text, and events.
Exam tip: A metrics scope shows only its own project's time series by default, so cross-project correlation requires expanding the scope to include series stored by the other projects.
Metric querying with Prometheus Query Language (PromQL) and Monitoring Query Language (MQL) turns stored series into Cloud Monitoring dashboards (opens in a new tab) and alerting policies. Every chart requires a query that selects metric type, monitored-resource type, and filters, and Metrics Explorer and custom dashboards provide menu-driven, PromQL, and Monitoring-filter interfaces. Managed Service for Prometheus stores Prometheus metrics in Monarch, so both native and Prometheus metrics are queryable with PromQL.
| Query path | Grouping and alignment | Conversion behavior |
|---|---|---|
| Menu-driven interface | Configured with Aggregation and Min Interval menus | Can convert to PromQL, except histograms may not translate |
| Prometheus Query Language (PromQL) | Included directly in expression | Cannot generally convert; unsaved queries discarded on switch |
| Monitoring filter in direct mode | Configured separately after filter selects series | Cannot always convert; filter discarded on switch |
Data flows from Prometheus exporters to collectors that scrape targets and forward samples to Monarch, then Monarch executes PromQL and unions results across regions and up to 3,500 projects in scope. PromQL can query over 6,500 free Monitoring metrics plus custom and log-based metrics, for example avg(compute_googleapis_com:instance_cpu_utilization) for average VM CPU. Monarch retains Prometheus data for 24 months, and existing Grafana dashboards continue to work. Adding a PromQL widget follows order: open Dashboards, add Metric widget, switch to PromQL, enter expression and run.
The Prometheus data model centers on the prometheus_target monitored-resource type with labels project_id, location, cluster, namespace, job, and instance. Non-PromQL queries for Prometheus metrics must specify this resource, while PromQL selects by metric name and labels. Filtering on resource labels rather than metric labels is recommended for high-cardinality metrics. Dynamic filtering via dashboardFilters in JSON re-issues all chart queries with the selected zone or instance constraint. Private access shows a dashboard only to its owner, while shared access shows it to all viewers, and predefined dashboards cannot be modified directly but can be copied.
A Service Level Indicator (SLI) is a measurement of performance derived from metrics such as request counts and latencies. Common examples are availability as successful responses over all responses and latency as calls below threshold over all calls. SLIs can be request-based counting atomic units or windows-based counting good windows. A Service Level Objective (SLO) is a target for an SLI over a compliance period, combining SLI, goal such as 95% or 99%, and period such as rolling 30 days. You can create up to 500 SLOs per service, and a useful SLO targets less than 100% because the gap creates the error budget of (1 − goal) × eligible events.
The burn rate tells how fast the budget is consumed, retrieved by select_slo_burn_rate. A rate greater than 1 means the service will miss the SLO if the error rate is sustained. A complete strategy uses two policies to balance speed against false positives, and alert compliance periods greater than 24 hours are not supported.
| Alert type | Purpose | Lookback period | Starting threshold |
|---|---|---|---|
| Fast-burn alert | Detect disastrous spike needing immediate response | Short 1- or 2-hour lookback | 10x baseline burn rate |
| Slow-burn alert | Detect sustained modest excess and smooth variation | Longer 24-hour lookback | 2x baseline burn rate |
Creating a burn-rate policy follows order: identify SLO identifier, construct condition with selector, threshold, comparison, and duration, select notification channel, and add documentation with playbook links.
Advanced alerting defines conditions over series or log data that create an incident and route notifications. Data flows from the monitored resource to the policy condition, then to an incident record, then through channels to people or systems. A policy evaluates continuously after enablement and cannot be scheduled for business hours only.
| Condition type | When condition is met | Example use |
|---|---|---|
| Metric-threshold | Value stays above or below threshold for retest window | HTTP latency above two seconds for five minutes |
| Metric-absence | Series produces no data for up to 24 hours | No HTTP responses over five minutes |
| Prometheus Query Language (PromQL) | Expression evaluates true, including ratios | Ratio of two metrics or analysis over 25 hours |
| Forecasted metric-value | Forecast predicts violation within 1 hour to 7 days | Disk likely to reach 80% within 24 hours |
Log data uses two paths: log-based policies fire on an individual matching entry, while SQL-based policies periodically analyze aggregations such as more than 50 WARNING entries in 60 minutes. A SQL policy must contain only one condition and runs with five-minute indexing delay plus propagation. Aggregation settings determine which series enter a condition and how points combine, using filters, rolling window alignment, and across-series grouping by labels such as zone. Reliable selection uses monitored-resource labels rather than asynchronously populated metadata labels, and filtering on resource cluster is more stable than metric kubernetes_cluster_name.
Notification routing sends each incident to one or more channels such as email from alerting-noreply@google.com, SMS, Pub/Sub, webhooks to ServiceNow, Slack, PagerDuty, and Mobile App push. When data meets the condition Monitoring creates the incident with status, log links, chart, labels, and duration. If an incident is open and the condition stops being met, Monitoring moves it to closed and sends closure notice. Operators create a snooze to pause evaluation, and creation links selection, triggering, delivery, autoclose, and documentation with dashboard links.
Cloud Billing budgets are alerts-only monitors that track actual and forecasted charges against planned spend. A budget evaluates spend for its scope and period, compares it to threshold rules, and notifies email recipients and Pub/Sub when crossed. Notifications do not stop usage, so control depends on response or automation subscribing to Pub/Sub. Scope can cover billing account, organizations, folders, projects, services, or label such as billingcode, while amount is fixed total or prior-period spend. Because billing lags usage by hours, budgets should sit below available funds.
Alert threshold rules are percentage-of-budget conditions on actual, forecasted, or both costs. By default budgets notify at 50%, 90%, and 100%, and a $100 budget with 110% forecasted rule notifies when projection exceeds $110. Budgets with custom time range cannot alert on forecast. Delivery uses role-based email to billing admins, Monitoring channels for custom emails, and Pub/Sub JSON with alertThresholdExceeded and forecastThresholdExceeded for automation such as scaling down non-production or disabling billing via API.
Alert data moves in fixed order from source event to downstream automation, where a threshold deviation writes networkmanagement.googleapis.com/insights_alarm and a structural change writes insights_event. The log-based policy evaluates the entry, opens an incident, and sends payload through the channel to PagerDuty, Slack, webhook, SMS, email, or Pub/Sub, where Pub/Sub can fan out to a Cloud Run remediation function. The native PagerDuty channel connects through Events API v1 in order: create endpoint in PagerDuty and copy integration key, create Monitoring channel with Display Name matching the service and paste key into Service Key, then attach the channel in policy Notifications. By default all Monitoring severities show as critical in PagerDuty, so orchestration rules must read event.custom_details.incident.severity to set urgency. A webhook posts to any public HTTPS endpoint for ServiceNow, Datadog, OpsGenie, or Rootly when no native channel exists, while Pub/Sub stays private without a public URL.
Formulating effective prompts for Gemini Cloud Assist means writing precise queries that direct the assistant to correlate metrics, surface anomalies, and propose causes. An effective prompt names resource scope, symptom or metric, and time or location window, such as ranking highest-utilization VMs or per-instance network bytes. Context-aware prompting from a Storage, BigQuery, or Cloud SQL page inherits buckets, datasets, or instance context, so the same short question returns a scoped answer. For advanced analysis always include project, region or zone, and time window when page context does not provide them.
Prompts for performance compare utilization, throughput, and saturation across the same window, such as top Dataflow backlog, SQL QPS, near-limit quotas, and idle VMs. Database prompts link query telemetry with load, such as current CPU, high-latency or slowest queries, error-log counts, and affecting issues. Disruption prompts check Personalized Service Health for ongoing incidents. Validation treats AI summaries as hypotheses against independent telemetry, because output can seem plausible but be incorrect. Causation requires a mechanism such as slot-millisecond consumption, reservation throttling, or an Audit Logs identity change, checked via INFORMATION_SCHEMA views such as JOBS and RESERVATIONS. Investigations turn chat into structured analysis with Issue, Findings, and Hypotheses, but as of April 10, 2026 creating or editing them requires Premium Support plus Investigation Creator or Owner.
Continue with this study guide: Managing metrics, dashboards, and alerts
Utilizing tracing frameworks means adding instrumentation code so each request generates spans and traces that flow to a Google Cloud project for storage in Cloud Trace. OpenTelemetry is the recommended vendor-neutral framework, and telemetry flows from the application process to the project either through an intermediate collector or directly through the Telemetry (OTLP) API. Before any flow starts, the Cloud Logging, Cloud Monitoring, and Cloud Trace APIs must be enabled, which requires serviceusage.services.enable through Owner or Service Usage Admin.
Manual instrumentation is required when automatic capture does not cover a path that must be validated. Some Google Cloud services capture trace data automatically, while other paths leave gaps that hide service interactions. In-process instrumentation runs inside the application process, observes logic, and generates logs, metrics, and traces that complement CPU, memory, and disk signals. This application telemetry adds error messages, stack traces, source locations, and service-to-service calls for one request.
OpenTelemetry is vendor-neutral because it is not tied to one backend and defines its own data model. A vendor-neutral framework lets the destination change without rewriting code and provides consistent approaches across languages, with interoperable libraries for traces and metrics plus custom measurements. Custom traces are built from spans where each span is one unit of work such as a function call. A developer acquires a Tracer with a scope name, starts a span from the current context with an operation name such as subrequests, keeps it active while work runs, and must call End() before exit because only completed spans export.
| Export pattern | How telemetry flows | Vendor dependency |
|---|---|---|
| Collector-based export | SDK in-process OTLP exporter to collector, then collector forwards to project | Code stays vendor-neutral; only collector holds Google Cloud config |
| Direct export | SDK directly to project through Telemetry API, without collector | Code includes vendor-specific Telemetry API dependencies |
Use collector-based export when a separate collector can run, and direct export when it cannot. Existing apps can point at a collector by setting OTEL_EXPORTER_OTLP_ENDPOINT to the collector OTLP endpoint such as in-cluster port 4317. Platform collectors depend on environment: the Google-built collector forwards to Observability and on GKE sends traces via Telemetry API and metrics to Managed Service for Prometheus, the Ops Agent receives OTLP metrics and traces on Compute Engine and sends metrics via Monitoring API and traces via Trace API, and Managed OpenTelemetry for GKE provides a managed in-cluster OTLP endpoint. Sampling controls cost because span collection is free but Trace ingestion is billable, using SDK decisions, W3C sampled propagation, probability, tail, and rate limits. Reading needs roles/cloudtrace.user, writing needs roles/cloudtrace.agent, and both need roles/cloudtrace.admin.
Exam tip: Collector-based export keeps application code vendor-neutral by isolating Google Cloud configuration in the collector, while direct export removes the collector but adds vendor-specific dependencies to the application.
Analyzing trace waterfalls and spans means turning distributed timing records in Cloud Trace into a diagnosis of why a request was slow or failed. A trace represents one end-to-end request composed of spans where each span measures time in one layer such as a database query, API call, or business logic. Analysis reconstructs span order, finds which span determined total latency, and connects timing to logs and metrics. Metrics answer rate and saturation, logs answer discrete failures and state changes, and traces answer component path, bottlenecks, and per-span duration.
The waterfall hierarchy shows how one parent contains multiple children ordered by context propagation. The Cloud Run request trace is the parent that bounds total duration, while database queries, Translation API calls, or business logic appear as nested children. Each bar starts at its start timestamp and extends for duration, so sequential bars add directly to parent duration because the parent cannot finish until each completes. Concurrent bars overlap and the parent is set by the longest branch, while a gap after the last child represents parent time, uninstrumented code, network transfer, or client processing.
Pinpointing latency means finding the blocking span on the critical path, which is the longest dependent chain that determines total duration. To find it, first identify the root Cloud Run span, then compare child start times and durations to separate sequential delays from parallel work, then drill into the longest sequential child or longest overlapping branch. Optimizing off that chain does not reduce end-to-end latency, while shortening on it does. Interpretation must account for sampling because Cloud Run standard sampling captures at most 0.1 requests per second per instance and forced tracing raises it to about 10 per second, and the rate cannot be configured.
Moving between Trace explorer and Logs Explorer pivots through shared trace context in order: select the trace row such as span name /multi, inspect the span Gantt chart for method, status, bytes, and user agent, then open the Logs and Events tab or View Logs to continue in Logging. The reverse pivot starts from a log entry such as handle /multi request, selects Traces, and opens View trace details. Span attributes such as service.name, cloud.provider, and gcp.project_id describe execution context, and in Observability Analytics spans live in the _AllSpans view for 30 days queried with JSON_VALUE, COUNT(*), AVG(duration_nano), and APPROX_QUANTILES for p50, p90, p95, and p99.
Correlating trace IDs with structured logs means carrying the identity of one distributed request across services and embedding it in logs so errors and latency can be reviewed together. Cloud Trace captures end-to-end path and latency as spans, while Cloud Logging stores timestamped entries with event detail. Correlation links those views through a shared trace identifier, so filtering by trace ID isolates every event for one transaction and opening the same ID in Trace shows latency per span. A trace is one end-to-end operation, each trace is composed of spans for one function, and added fields such as severity, service name, trace ID, span ID, and customer ID let Logs Explorer link directly to the matching trace.
| Platform | Default telemetry | Action to enable correlation |
|---|---|---|
| Compute Engine VMs | Basic system metrics and system logs | Install Ops Agent for host, application, and OTLP traces and metrics |
| GKE clusters | System logs and system metrics | Use observability packages and Managed Service for Prometheus |
| Cloud Run services | System metrics and logs | Add Prometheus sidecar or OpenTelemetry sidecar for OTLP and context |
| Cloud Run functions and App Engine | Metrics, logs, and traces | Instrument only for additional spans or enriched fields |
The Ops Agent automatically collects host CPU, GPU, memory, process metrics, syslog or Windows Event Log, third-party integrations, Prometheus metrics, and OTLP traces and metrics, while application logs use logging receivers rather than OTLP. Structuring logs to carry trace IDs turns isolated entries into queryable steps, where applications write to files and forward with the Ops Agent, configure fluentd, Logback, or Winston, or call the Logging API directly. Entries remain correlatable only with valid timestamps, because entries older than retention or more than 24 hours in the future are discarded. Querying uses Logs Explorer for single requests, Trace Explorer for latency, Observability Analytics over log views and _AllSpans for trends, and linked BigQuery datasets only for joins, Studio queries, reserved slots, or alerting.
Employing Gemini Cloud Assist for trace analysis means using chat and automated Investigations to correlate logs, metrics, configurations, and traces into ranked explanations. Chat provides immediate explanations of an error or latency symptom, while Investigations compares baseline behavior against an anomalous period. Data flows from the selected resource and its observability stores to the panel or engine, and results flow back as structured output that must still be validated before changing production.
Configuration starts with project setup, least-privilege IAM roles, and enabling backing APIs so Gemini only analyzes authorized telemetry. An administrator sets up the account and project and waits for propagation, then the user prompts from the resource page so response includes page and project context. The documented pattern pairs Monitoring Viewer, a data reader such as Bigtable Reader, Database Insights Viewer, and Investigation Owner or Creator, with Service Health and Recommender APIs for their domains. As of April 10, 2026, creating, running, and editing investigations additionally requires a Premium Support contract.
| Section | Content | How to use it |
|---|---|---|
| Issue | Description including start and stop time | Confirm scope, service, and time alignment |
| Findings | Observations such as incorrect channel pool size | Cross-check against independent signals |
| Hypotheses | AI-recommended remediation actions | Treat as candidates to validate and measure |
Validation requires that window, resource, cluster, and symptoms match monitoring, with credible findings moving in more than one dimension such as rising client and server latencies with rising CPU. A disciplined rollout then applies one change at a time in order: isolate one hypothesis with expected change, apply to a canary or single cluster while rest serves as control, measure SLIs against baseline, promote broadly only after improvement without regression otherwise roll back, and escalate with context if needed.
Continue with this study guide: Capturing and analyzing distributed traces
Persistent storage, capacity, and network failures share one rule: trace from the failed resource to the blocking dependency before assuming data is lost. Traffic flows from VM instances, containers, or on-premises hosts through Virtual Private Cloud (VPC) routes and firewall enforcement to Persistent Disk volumes, buckets, or databases, while identity, Domain Name System (DNS), and replication services must stay healthy on both sides of every trust boundary. When reads, writes, or scale-out stall, the cause is usually a failed key, route, quota, or replica path rather than destroyed bytes.
Storage dependencies are the encryption, network, platform, and identity services that must stay healthy for a disk, bucket, or database to serve input/output. Persistent Disk I/O depends on lower-level Compute Engine services such as Borg and Colossus, so a fabric problem can stall I/O while the VM appears running. Spanner, Bigtable, and Cloud Storage depend on Cloud Key Management Service (Cloud KMS), Cloud External Key Manager, or Google-owned keys plus logging, auditing, and cross-region replication. All access also depends on DNS, global load balancers, points of presence, and IAM identity planes, so first separate permission and connectivity failures from durability failures.
| Cloud Storage location | Replication scope | Failure coverage |
|---|---|---|
| Regional bucket | Synchronously across zones in one region | Survives zonal failure, not regional loss |
| Dual-region bucket | Asynchronously across two regions, optional turbo replication | Survives loss of one region with lower RPO |
| Multi-region bucket | Asynchronously across regions in a boundary | Survives regional loss inside boundary |
Persistent Disk and Filestore follow the same zonal-versus-regional tradeoff. Zonal disks live in one zone and need snapshots elsewhere, while regional disks replicate to two zones so I/O continues if one fails. Managed instance groups distribute VMs across zones and pair with regional disks, while Filestore Basic and Zonal tiers are zonal Network File System servers without cross-zone replication and Enterprise tier is regional. Managed database continuity depends on Compute Engine and Artifact Registry images plus continuous replication to a standby, where invoke, provision, and reroute via DNS to load-balancer address can be manual or automatic. Avoid split-brain with quorum or by making the old primary inaccessible, and match cold, warm, and hot recovery to large, medium, and small recovery time and point objectives.
Capacity planning forecasts load, sizes resources, adds redundancy, and verifies efficiency in order: forecast users and rate, estimate managed instance group size and disk with Pricing Calculator, plan N+1 redundancy, benchmark under normal and peak, secure quotas and reservations, and monitor with Monitoring and Active Assist. Quotas are per-project zonal, regional, or global limits that block creation, with resource quotas for creatable resources and rate quotas for API requests. Reservations provide assured zonal capacity, while autoscaling adjusts within limits: Compute Engine groups scale VMs, GKE Cluster Autoscaler adds nodes while Horizontal Pod Autoscaler changes Pods and Vertical Pod Autoscaler tunes requests, Cloud Run scales to zero, and Bigtable scales nodes to target utilization.
Connectivity troubleshooting isolates blocked traffic across VPC routes, Cloud Next Generation Firewall, health checks, DNS, and hybrid links. Traffic flows from source through VPC routes and firewall evaluation, then through NAT or Private Service Connect (PSC) endpoints to destination or Google API. Resources without external addresses can still reach Google APIs when Private Google Access is enabled, while PSC provides private consumer endpoints. Firewall rules evaluate by priority where lower numbers win, so specific rules must be numbered lower than general rules, and Firewall Rules Logging must be enabled per rule. Health-check traffic flows from Google probers to backends, so firewalls must allow 35.191.0.0/16 and 130.211.0.0/22 for most load balancers and additional 209.85.152.0/22 and 209.85.204.0/22 for Network Load Balancing, while Identity-Aware Proxy TCP uses 35.235.240.0/20. Hybrid traffic flows from VPC subnets through Cloud Router Border Gateway Protocol routes to VLAN attachments, normally two attachments, then across VPN or Interconnect tunnels.
Exam tip: Use regional persistent disks and Enterprise-tier Filestore to survive zonal failure without restore, and use dual-region Cloud Storage with turbo replication when the requirement is lower RPO across regions.
Continuous integration and delivery stalls usually trace to manifests, connectivity, scan gates, or build identity rather than application code. A release flows from images built by continuous integration through Cloud Deploy rendering and promotion into GKE or Cloud Run targets, while Artifact Registry, Artifact Analysis, and Cloud Build gate each handoff. When promotion stops, first identify whether rendering, target reachability, scanning, or execution identity blocked the chain.
Skaffold configuration tells Cloud Deploy which manifests to render and how to deploy them. A minimal skaffold.yaml must start with a supported apiVersion such as skaffold/v4beta7, declare manifests under manifests.rawYaml, and declare the deployer under deploy.kubectl. Cloud Deploy calls skaffold render to fill templates and bind tags, then skaffold apply to deploy. Release creation moves artifacts through ordered targets in sequence: build images where Cloud Deploy can reference them, create the release with gcloud deploy releases create RELEASE_NAME --delivery-pipeline=PIPELINE_NAME --region=REGION from the Skaffold directory, and advance through the pipeline with rendering before each deployment. The command packages the current directory, so running from home uploads unwanted files.
Target connectivity controls whether the control plane can reach the GKE control plane. For HTTP-proxy-only clusters the target adds proxyUrl to the gke stanza, and deployment traffic flows from Cloud Deploy through that proxy. For private clusters three paths connect to the isolated control plane: DNS-based endpoint, VPC network with private worker pool, or attached clusters with Connect gateway. The DNS endpoint is simplest because nodes stay private while the control plane exposes a DNS name with dnsEndpoint: true. The VPC path keeps render and deploy inside the private network by creating a VPC-native private cluster with internalIp: true, creating a private worker pool with network access, and binding usages in executionConfigs. The private pool is required for RENDER and can also serve DEPLOY and VERIFY.
Artifact Analysis evaluates artifacts after arrival in Artifact Registry, where data flows from push to analysis to Container Analysis metadata. Vulnerability knowledge is stored as a note and each instance as an occurrence, so the gate reads occurrences to allow or block a digest. Scanning needs Artifact Registry and Container Scanning APIs plus a Docker repository, and language scanning for npm and Python in Artifact Registry needs the Analysis API. Scan metadata moves through fresh, stale, and archived states: fresh while pulled within 30 days, stale after 30 days without pull, and archived after more than 90 days stale visible only via API. Only images can be re-scanned by pulling with up to 24-hour refresh, while packages need a new version. Deploy authentication needs both IAM permissions and access scopes, where same-project runtimes are preconfigured but cross-project or custom accounts need manual grants.
Cloud Build failures are traced through logs, worker state, timeouts, and identities. Logs to stdout or stderr appear in console and CLI, and on failure the console links to the workdir in Cloud Storage. Image Builder writes to orchestrator logs, customization agent logs under the build ID, serial console logs for boot failures, and guest journal logs, where data flows from agent to orchestrator to Cloud Storage. Setting debug: true under infrastructureConfig pauses worker deletion for SSH inspection with gcloud compute ssh and --tunnel-through-iap when no external IP exists. The default timeout is 1 hour (3600s) until root-level timeout such as 7200s increases it. The build service account governs resource access, distinct from the service agent service-PROJECT_NUMBER@gcp-sa-cloudbuild.iam.gserviceaccount.com that calls APIs on behalf of the build.
Application latency and runtime failures require separating slow code, saturated infrastructure, and slow dependencies before changing scaling or code. Telemetry flows from users to Cloud Run revisions or App Engine services, then to Cloud Monitoring for aggregate impact, Cloud Trace with Logging for per-request paths, and Cloud Profiler for function cost, while decisions flow back to scaling or code fixes. Adding capacity without that separation can overload a backing database.
| Signal | Primary unit | Choose when |
|---|---|---|
| Cloud Monitoring | Aggregate latency and resources | Question is how many requests are slow and whether CPU or nodes changed |
| Cloud Trace with Logging | Sampled trace correlated to logs | Question is which request is slow and whether time sits in code or dependency |
| Cloud Profiler | Function-level CPU and allocation | Question is which lines consume resources and whether hotspot changed |
Cloud Run exposes a Request latencies dashboard with no setup, while App Engine exposes 50th, 95th, and 99th percentiles where high values on all three mean at least 50% are slow and high only at 99th mean about 1% are slow. Correlated container logs tied to the request log identify the request and its trace, while traceSampled=true links sampled logs to traces. Each Cloud Run request log carries an instanceId, which matters because one instance can handle concurrent requests sharing global state such as one connection pool. Without explicit logging of outbound calls, wait on another service appears as Cloud Run latency. Remediation matches cause: raise minimum instances to avoid cold starts, limit maximum to protect constrained backends, and fix reused globals, oversized pools, missing indexes, or Profiler hotspots.
Container health in GKE correlates live Monitoring signals with historical Logging evidence. Monitoring shows restart_count for crash loops, memory/limit_utilization capped at 1.0 for OutOfMemory risk, used_bytes for leaks, page_fault_count for disk pressure, cpu/limit_utilization for throttling, ephemeral_storage/used_bytes for evictions, and request utilizations for rightsizing. Kubelet logs record startups, probe failures, and mounts, containerd logs record image pulls, app logs from stdout and stderr record crashes, and audit logs record Deployment changes. Diagnose in order: check restarts with utilization, review app logs for the failed Pod, review kubelet and containerd logs on the node, then check audit and node pressure. Empty app logs with a never-starting Pod points to image or scheduling, not code.
Runtime exceptions separate code from dependency failures at trust boundaries. Cloud Error Reporting groups repeated stack traces from App Engine, Cloud Run, Cloud Functions, Compute Engine, and GKE into one issue, where data flows from formatted Logging entries or direct API calls. Reporting needs Error Reporting Writer and cloud-platform scope, with GKE needing scope and service account at creation and Compute Engine needing stop, edit, and restart. Structured tracing joins Logging and Trace via trace, spanId, traceSampled, and request_id, while audits prove the remaining boundary: Admin Activity always enabled, Data Access disabled by default except BigQuery, and System Event generated by Compute Engine. A sink filtering organization SetIamPolicy to Pub/Sub triggering a Cloud Run function gives near-real-time notice of permission changes.
Proactive observability turns telemetry into incidents before users notice degradation. Data flows from metric data in Monitoring or log data in Logging into an alerting policy, then to an incident record, then to each channel such as email, Mobile App, PagerDuty, or Slack. Mature coverage combines threshold checks for known limits, forecast and absence checks for exhaustion and silence, expressive queries for SLO burn, and synthetic probes for external availability. An alerting policy is defined by condition, channels, and documentation with playbook links, evaluates continuously with no business-hours schedule, and moves an open incident to closed automatically when the condition clears. Synthetic uptime checks probe HTTP, HTTPS, and TCP endpoints, while broken-link checkers crawl pages, catching DNS, certificate, and routing failures that internal metrics miss.
| Condition type | What triggers it | Proactive use |
|---|---|---|
| Metric-threshold condition | Value above or below threshold for retest window | Detect saturation such as 500ms latency |
| Metric-absence condition | No data for retest window, up to 24 hours | Detect dead agents or stalled pipelines |
| PromQL condition | Expression true in real time, including ratios | Detect SLO burn spanning over 25 hours |
| Forecasted metric-value condition | Forecast predicts violation in 1 hour to 7 days | Detect disk likely to reach 80% within 24 hours |
Optimizing data means shaping logs, metrics, and traces so failures are found without storing unnecessary telemetry. In-process instrumentation exports to a project where Logging stores logs, Monitoring stores metrics, and Trace stores traces, with OpenTelemetry as the vendor-neutral standard. Structured entries combine message with severity, customer ID, stack trace, and code location, where Error Reporting groups entries and Observability Analytics queries trends such as average latency by URL. A log-based alert fires on a single rare entry, while a log-based metric counts entries and an alert monitors the trend. Cover latency, traffic, error rate, and saturation when defining customs, using Managed Service for Prometheus for GKE exporters, Ops Agent for Compute Engine, and sidecars for Cloud Run.
Diagnosing root causes correlates shared identity across signals: Logging entries carry trace as projects/YOUR-PROJECT/traces/TRACE-ID, spanId, traceSampled, and request_id, Trace stores the same ID, and Monitoring shows the spike for the same window. Server access logs under k8s_container give the server view while client logs under k8s_pod give the client view, and comparing them separates mesh or network problems from handling problems. Cloud Service Mesh (opens in a new tab) control-plane versus data-plane separation uses istiod metrics prefixed istio.io/control and pilot_proxy_convergence_time, where rising convergence with disconnects points to control plane and flat control plane with rising data-plane latency points to application. Missing logs are themselves an anomaly from disabled APIs, quota RESOURCE_EXHAUSTED, exclusion filters, fully buffered stdout, restrictive Explorer filters, retention expiry, or unsupported GKE versions, controlled with organization sinks, BigQuery exports, SQL over buckets, and Metrics Management for billable ingestion and cardinality.
Performance work answers requests as close to the user as possible and matches compute and database capacity to real demand. Traffic flows from users to
Admin Activity logs record control-plane writes such as virtual machine creation, Identity and Access Management change, or cluster deployment and are always written and cannot be disabled or excluded, while Data Access logs record reads of user data such as get, list, or BigQuery select and are disabled by default because volume and cost can be large. System Event logs cover Google-initiated maintenance and lifecycle actions and Policy Denied logs cover access attempts denied by policy checks.
Use a fast-burn alert with a short 1-hour or 2-hour lookback and a starting threshold of 10 times the baseline burn rate to detect a disastrous spike needing immediate response, and use a slow-burn alert with a longer 24-hour lookback and a starting threshold of 2 times the baseline burn rate to detect sustained modest excess and smooth variation. A burn rate greater than 1 means the service will miss its Service Level Objective if the error rate is sustained.
Correlation groups entries that share the same trace field into a parent-child view when the trace field is set to TRACE_ID or projects/PROJECT_ID/traces/TRACE_ID, the value is the same across the group, each entry has a different logName, and the parent timestamp is no later than any child timestamp. If an expanded parent shows no children, no other entries in the time range share that trace identifier, so widening the range or removing a restrictive filter is next.
With collector-based export the software development kit sends OpenTelemetry Protocol data to a collector that forwards it to the project, so application code stays vendor-neutral and only the collector holds Google Cloud configuration. With direct export the software development kit sends telemetry directly to the project through the Telemetry API without a collector, which removes the collector but adds vendor-specific dependencies to the application.
Last updated