Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/oci-apm-export-data/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ resource "oci_identity_policy" "gtw_policy" {
name = "apm-data-exporter-gtway-policy"
description = "Policy needed to allow ApiGateway to call the function."
statements = [
"ALLOW any-user to use functions-family in compartment ApmTestbed where ALL {request.principal.type= 'ApiGateway'} ",
"ALLOW any-user to use functions-family in compartment ${local.compartment_name} where ALL {request.principal.type= 'ApiGateway'} ",
]
}

Expand Down
Binary file added examples/oci-apm-service-monitoring/.DS_Store
Binary file not shown.
81 changes: 81 additions & 0 deletions examples/oci-apm-service-monitoring/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# OCI APM service monitoring using the APM Log Sender function

This project provides a Terraform-based setup for monitoring Oracle Cloud Infrastructure (OCI) services using Oracle Application Performance Monitoring (APM). It provisions all necessary OCI resources, including:

- Log and log group creation (unless a log is provided)
- OCI Functions application and function
- API Gateway
- Virtual Cloud Network (VCN) and networking components
- Service Connector Hub connection
- Required IAM policies

The solution uses the Log Sender PBF and the OCI Logging service to enable monitoring of your target service.

## Resources Created

When deployed, the following resources will be created (unless existing ones are provided):

- **1 x Log Group and Log** – to enable logging for the monitored service
- **1 x Virtual Cloud Network (VCN)** – named `apm-service-monitoring-vcn` with required networking
- **1 x OCI Application** – named `apm-service-monitoring-app`
- **1 x OCI Function** – named `apm-service-monitoring-function`
- **1 x Service Connector** – named `service-monitoring-connector`
- **IAM Policies** – for the Function and Service Connector to operate properly

> **Note:** If `log_id` is provided, the log and log group will **not** be created, and the specified log will be used instead. Ensure the provided log exists in the correct compartment. (More details below.)

---

## How to Use the Script

This Terraform script uses input variables to determine whether to create a new log resource or use an existing one.

- If `log_id` is **specified**, the script will use the existing log and **skip creating** a new log and log group.
- If `log_id` is **not specified**, then the following variables **must** be provided to create a new log:
- `resource_id`: The OCID of the resource to monitor.
- `log_service`: The service name. *(Default: Oracle Integration Cloud service)*
- `log_category`: The log category. *(Default: Activity Stream)*

Ensure all required variables are provided based on your use case.

---

## Terraform Deployment

### Deploy to OCI with One Click

Click the button below to deploy the function directly to OCI using the Resource Manager. Some values will be prepopulated:

[![Deploy to Oracle Cloud](https://oci-resourcemanager-plugin.plugins.oci.oraclecloud.com/latest/deploy-to-oracle-cloud.svg)](https://cloud.oracle.com/resourcemanager/stacks/create?zipUrl=https://github.com/M-Iliass/oci-observability-and-management/releases/download/v1.0.1/oci-apm-service-monitoring.zip)

---

### Deploy Using Local Development Environment

#### 1. Prepare Your Variable File

Create a file named `terraform.tfvars` and populate it with the required values.

```hcl
tenancy_ocid = "your-tenancy-ocid"
region = "your-region"
apm_domain_id = "your-apm-domain-id"
compartment_ocid = "your-compartment-ocid"
resource_id = "your-resource-id"
log_id = "your-log-id" # Optional
log_service = "your-log-service" # Required if log_id is not provided
log_category = "your-log-category" # Required if log_id is not provided
```

Refer to the How to Use the Script section to determine which variables are required in your scenario.


## Deploying the function:

Apply the changes using the following commands:

```
terraform init
terraform plan
terraform apply
```
113 changes: 113 additions & 0 deletions examples/oci-apm-service-monitoring/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
data "oci_functions_pbf_listings" "log_sender_pbf_listings" {
name = "APM Log Sender"
}

data "oci_logging_log_groups" "test_log_groups" {
#Required
compartment_id = var.compartment_ocid
}

locals {
pbflisting_ocid = data.oci_functions_pbf_listings.log_sender_pbf_listings.pbf_listings_collection[0]["items"][0].id
function_config = { "APM_DOMAIN_ID" : var.apm_domain_id }
log_source_map = {
for log in data.oci_logging_log_groups.test_log_groups.log_groups : log.display_name => log
}
}

data "oci_logging_log" "logs" {
for_each = local.log_source_map

log_group_id = each.value.id
log_id = var.log_id
}

locals {
log_group_id = [
for name, d in data.oci_logging_log.logs : d.log_group_id if d.log_group_id != null
]
}

### Enable logging for the resource if the log_id isn't set
resource "oci_logging_log_group" "service_monitoring_log_group" {
count = var.log_id == "Don't change to enable logging" ? 1 : 0

compartment_id = var.compartment_ocid
display_name = "apm-service-monitoring-log-group"
description = "Log group for service monitoring by APM"
}

resource "oci_logging_log" "service_monitoring_log" {
count = var.log_id == "Don't change to enable logging" ? 1 : 0

display_name = "service-monitoring-log"
log_group_id = oci_logging_log_group.service_monitoring_log_group[count.index].id
log_type = "SERVICE"

configuration {
source {
category = var.log_category
service = var.log_service
resource = var.resource_id
source_type = "OCISERVICE"
}
}
}

### Creates the application that should contain the function
resource "oci_functions_application" "service_monitoring_application" {
compartment_id = var.compartment_ocid
display_name = "apm-service-monitoring-app"
subnet_ids = [module.oci_subnets.subnets.public.id]
shape = "GENERIC_ARM"
}

### Creates the PBF function that sends the logs to the APM collector
resource "oci_functions_function" "service_monitoring_function" {
application_id = oci_functions_application.service_monitoring_application.id
display_name = "apm-service-monitoring-function"
memory_in_mbs = "1024"

timeout_in_seconds = 120
source_details {
pbf_listing_id = local.pbflisting_ocid
source_type = "PRE_BUILT_FUNCTIONS"
}
config = local.function_config
}

### Creates the policies for the connector and PBF
resource "oci_identity_policy" "function_policies" {
provider = oci.home
compartment_id = var.compartment_ocid
description = "Policies for the function for the service monitoring integration"
name = "service-monitoring-integration-policies"
statements = [
"ALLOW any-user TO {APM_DOMAIN_DATA_UPLOAD} in compartment id ${var.compartment_ocid} WHERE ALL { request.principal.id='${oci_functions_function.service_monitoring_function.id}' }",
"ALLOW any-user TO read apm-domains in compartment id ${var.compartment_ocid} WHERE ALL { request.principal.id='${oci_functions_function.service_monitoring_function.id}' }",
"allow any-user to use fn-function in compartment id ${var.compartment_ocid} where all {request.principal.type='serviceconnector', request.principal.compartment.id='${var.compartment_ocid}'}",
"allow any-user to use fn-invocation in compartment id ${var.compartment_ocid} where all {request.principal.type='serviceconnector', request.principal.compartment.id='${var.compartment_ocid}'}"
]
}

### Creates the connector which connects the log and PBF
resource "oci_sch_service_connector" "service_monitoring_connector" {
compartment_id = var.compartment_ocid
display_name = "Service-monitoring-connector"
description = "Connects the Log Sender PBF with the log resource to enable the monitoring."

source {
kind = "logging"

log_sources {
compartment_id = var.compartment_ocid
log_group_id = var.log_id == "Don't change to enable logging" ? oci_logging_log_group.service_monitoring_log_group[0].id : local.log_group_id[0]
log_id = var.log_id == "Don't change to enable logging" ? oci_logging_log.service_monitoring_log[0].id : var.log_id
}
}
target {
kind = "functions"

function_id = oci_functions_function.service_monitoring_function.id
}
}
88 changes: 88 additions & 0 deletions examples/oci-apm-service-monitoring/network.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Copyright (c) 2025 Oracle and/or its affiliates.
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.

locals {
next_hop_ids = {
"igw" = module.oci_network.igw.id
}
anywhere = "0.0.0.0/0"
vcn_cidr = "10.0.0.0/24"
subnet_public_cidr = cidrsubnet(local.vcn_cidr, 2, 0)
subnet_private_cidr = cidrsubnet(local.vcn_cidr, 2, 1)
}

module "oci_network" {
source = "../../oci-core-modules/oci_network"
default_compartment_id = var.compartment_ocid

vcn_options = {
display_name = "apm-service-monitoring-vcn"
cidr = local.vcn_cidr
enable_dns = true
dns_label = "apmmonitor"
compartment_id = null
defined_tags = null
freeform_tags = null
}

svcgw_options = {
display_name = null
compartment_id = null
defined_tags = null
freeform_tags = null
services = [
module.oci_network.svcgw_services.1.id
]
}

create_igw = true
create_svcgw = false
create_natgw = false
create_drg = false

route_tables = {

igw = {
compartment_id = null
defined_tags = null
freeform_tags = null
route_rules = [
{
dst = "0.0.0.0/0"
dst_type = "CIDR_BLOCK"
next_hop_id = local.next_hop_ids["igw"]
}
]
}
}

}

module "oci_subnets" {
source = "../../oci-core-modules/oci_subnets"

default_compartment_id = var.compartment_ocid
vcn_id = module.oci_network.vcn.id
vcn_cidr = module.oci_network.vcn.cidr_block


subnets = {
public = {
compartment_id = null
defined_tags = null
freeform_tags = null
dynamic_cidr = false
cidr = local.subnet_public_cidr
cidr_len = null
cidr_num = null
enable_dns = null
dns_label = "public"
private = false
ad = null
dhcp_options_id = null
route_table_id = module.oci_network.route_tables.igw.id
security_list_ids = null
}
}
}

20 changes: 20 additions & 0 deletions examples/oci-apm-service-monitoring/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright (c) 2025, Oracle and/or its affiliates.
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.


provider "oci" {
tenancy_ocid = var.tenancy_ocid
region = var.region
# config_file_profile = "" # Add this for local runs with your profile name
}

provider "oci" {
alias = "home"
tenancy_ocid = var.tenancy_ocid
region = [for i in data.oci_identity_region_subscriptions.this.region_subscriptions : i.region_name if i.is_home_region == true][0]
# config_file_profile = "" # Add this for local runs with your profile name
}

data "oci_identity_region_subscriptions" "this" {
tenancy_id = var.tenancy_ocid
}
23 changes: 23 additions & 0 deletions examples/oci-apm-service-monitoring/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
variable "tenancy_ocid" {}

variable "region" {}

variable "apm_domain_id" {}

variable "compartment_ocid" {}

variable "resource_id" {
default = "Add this to create a new log for the resource"
}

variable "log_id" {
default = "Don't change to enable logging"
}

variable "log_service" {
default = "integration"
}

variable "log_category" {
default = "activitystream"
}