다음을 통해 공유


Logic Apps를 사용하여 Log Analytics 작업 영역의 데이터를 스토리지 계정으로 내보내기

이 문서에서는 Azure Logic Apps를 사용하여 Azure Monitor의 Log Analytics 작업 영역에서 데이터를 쿼리하고 Azure Storage로 보내는 방법을 설명합니다. 감사 및 규정 준수 시나리오를 위해 Azure Monitor 로그 데이터를 내보내거나 다른 서비스가 이 데이터를 검색하도록 허용해야 하는 경우 이 프로세스를 사용합니다.

기타 내보내기 메서드

이 문서에서는 논리 앱을 사용하여 로그 쿼리에서 예약된 내보내기를 수행하는 방법을 설명합니다. 특정 시나리오용 데이터를 내보내는 다른 옵션은 다음과 같습니다.

개요

이 프로시저에서는 논리 앱에서 로그 쿼리를 실행하고 워크플로의 다른 작업에서 해당 출력을 사용할 수 있는 Azure Monitor 로그 커넥터를 사용합니다. 이 절차에서는 Azure Blob Storage 커넥터를 사용하여 쿼리 출력을 스토리지로 보냅니다.

Logic Apps 개요를 보여 주는 스크린샷.

Log Analytics 작업 영역에서 데이터를 내보낼 경우 Logic Apps 워크플로가 처리하는 데이터 양을 제한하세요. 쿼리에서 로그 데이터를 필터링하고 집계하여 필요한 데이터를 줄입니다. 예를 들어, 로그인 이벤트를 보관해야 하는 경우 필수 이벤트를 필터링하여 필요한 필드만 표시합니다. 예시:

SecurityEvent
| where EventID == 4624 or EventID == 4625
| project TimeGenerated , Account , AccountType , Computer

일정에 따라 데이터를 내보낼 때 쿼리에서 ingestion_time() 함수를 사용하여 늦게 도착하는 데이터를 놓치지 않도록 합니다. 네트워크 또는 플랫폼 문제로 인해 데이터가 지연되는 경우 수집 시간을 사용하면 다음번에 Logic Apps가 실행될 때 데이터가 포함됩니다. Logic Apps 프로시저 섹션의 "Azure Monitor 로그 추가 작업" 단계를 한 예로 참조하세요.

필수 조건

이 프로시저를 시작하기 전에 다음 필수 조건을 완료해야 합니다.

  • Log Analytics 작업 영역: 논리 앱을 만드는 사용자는 작업 영역에 대한 읽기 권한이 있어야 합니다.
  • 스토리지 계정: 스토리지 계정은 Log Analytics 작업 영역과 동일한 구독에 있을 필요가 없습니다. 논리 앱을 만드는 사용자는 스토리지 계정에 대한 쓰기 권한이 있어야 합니다.

커넥터 제한

Azure Monitor의 Log Analytics 작업 영역 및 로그 쿼리는 고객을 보호 및 격리하고 서비스 품질을 유지하기 위한 제한을 포함하는 다중 테넌트 서비스입니다. 많은 양의 데이터를 쿼리할 때는 Logic Apps 되풀이 및 로그 쿼리를 구성하는 방법에 영향을 줄 수 있는 다음 제한 사항을 고려합니다.

  • 로그 쿼리는 500,000개 이상의 행을 반환할 수 없습니다.
  • 로그 쿼리는 64,000,000 바이트 이상을 반환할 수 없습니다.
  • 로그 쿼리는 10분 이상 실행할 수 없습니다.
  • Log Analytics 커넥터는 분당 100개 호출로 제한됩니다.

Logic Apps 프로시저

다음 섹션에서 이 프로시저를 안내합니다.

스토리지 계정에 컨테이너 만들기

컨테이너 만들기의 프로시저를 사용하여 내보낸 데이터를 저장할 컨테이너를 스토리지 계정에 추가합니다. 이 문서의 컨테이너에 사용되는 이름은 loganalytics-data이지만 모든 이름을 사용할 수 있습니다.

논리 앱 워크플로 만들기

  1. Azure Portal에서 Logic Apps로 이동하고 추가를 선택합니다. 구독, 리소스 그룹지역을 선택하여 새 논리 앱을 저장합니다. 그런 다음 고유한 이름을 지정합니다. Azure Monitor 로그 설정 및 Azure Logic Apps에 대한 진단 데이터 수집에 설명된 대로 Log Analytics 설정을 켜서 런타임 데이터 및 이벤트에 대한 정보를 수집할 수 있습니다. 이 설정은 Azure Monitor Logs 커넥터를 사용하는 데 필요하지 않습니다.

    논리 앱을 만드는 방법을 보여 주는 스크린샷.

  2. 검토 + 생성를 선택한 다음, 생성를 선택합니다. 배포가 완료되면 리소스로 이동을 선택하여 Logic Apps 디자이너를 엽니다.

워크플로에 대한 트리거 만들기

공통 트리거로 시작에서 반복을 선택합니다. 이 설정은 정기적으로 자동 실행되는 논리 앱 워크플로를 만듭니다. 작업의 빈도 상자에서 을 선택합니다. 간격 상자에 1을 입력하여 워크플로를 하루 1회 실행합니다.

되풀이 작업을 보여 주는 스크린샷.

Azure Monitor 로그 작업 추가

Azure Monitor 로그 작업을 사용하면 실행할 쿼리를 지정할 수 있습니다. 이 예에서 사용되는 로그 쿼리는 시간별 되풀이에 맞게 최적화된 것입니다. 특정 실행 시간 동안 수집된 데이터를 수집합니다. 예를 들어 워크플로가 4:35에 실행되는 경우 시간 범위는 3:00~4:00입니다. 다른 빈도로 실행되도록 논리 앱을 변경하는 경우 쿼리도 변경해야 합니다. 예를 들어, 매일 실행하도록 되풀이를 설정할 경우 쿼리에 있는 startTimestartofday(make_datetime(year,month,day,0,0))로 설정합니다.

워크플로가 쿼리를 실행하는 데 사용할 계정으로 Log Analytics 작업 영역에 대한 액세스 권한을 부여하라는 테넌트 선택 메시지가 표시됩니다.

  1. + 새 단계를 선택하여 반복 작업 후에 실행되는 작업을 추가합니다. 작업 선택에서 Azure Monitor를 입력합니다. 그런 다음 Azure Monitor 로그를 선택합니다.

    Azure Monitor 로그 작업을 보여 주는 스크린샷.

  2. Azure Log Analytics - 쿼리 실행 및 결과 표시를 선택합니다.

    Azure Monitor 로그가 작업 선택에서 강조 표시된 것을 보여 주는 스크린샷.

  3. Log Analytics 작업 영역에 대한 구독리소스 그룹을 선택합니다. 리소스 종류Log Analytics 작업 영역을 선택합니다. 그런 다음 리소스 이름 아래에서 작업 영역 이름을 선택합니다.

  4. 다음 로그 쿼리를 쿼리 창에 추가합니다.

    let dt = now();
    let year = datetime_part('year', dt);
    let month = datetime_part('month', dt);
    let day = datetime_part('day', dt);
     let hour = datetime_part('hour', dt);
    let startTime = make_datetime(year,month,day,hour,0)-1h;
    let endTime = startTime + 1h - 1tick;
    AzureActivity
    | where ingestion_time() between(startTime .. endTime)
    | project 
        TimeGenerated,
        BlobTime = startTime, 
        OperationName ,
        OperationNameValue ,
        Level ,
        ActivityStatus ,
        ResourceGroup ,
        SubscriptionId ,
        Category ,
        EventSubmissionTimestamp ,
        ClientIpAddress = parse_json(HTTPRequest).clientIpAddress ,
        ResourceId = _ResourceId 
    
  5. 시간 범위TimeGenerated 열을 기반으로 쿼리에 포함될 레코드를 지정합니다. 이 값은 쿼리에서 선택한 시간 범위보다 커야 합니다. 이 쿼리는 TimeGenerated 열을 사용하지 않으므로 쿼리에서 설정 옵션을 사용할 수 없습니다. 시간 범위에 대한 자세한 내용은 쿼리 범위를 참조하세요. 시간 범위에서 지난 4시간을 선택합니다. 이렇게 설정하면 수집 시간이 TimeGenerated보다 큰 레코드가 결과에 포함됩니다.

    쿼리 실행 및 결과 시각화라는 새 Azure Monitor 로그 작업에 대한 설정을 보여 주는 스크린샷.

JSON 구문 분석 작업 추가(선택 사항)

쿼리 실행 및 결과 표시 작업의 출력은 JSON 형식으로 지정됩니다. 이 데이터를 구문 분석하고 작성 작업 준비의 일부로 조작할 수 있습니다.

받을 것으로 예상되는 페이로드를 설명하는 JSON 스키마를 제공할 수 있습니다. 이 디자이너는 이 스키마를 사용하여 JSON 콘텐츠를 구문 분석하고 JSON 콘텐츠의 속성을 나타내는 친숙한 토큰을 생성합니다. 그 후 이러한 속성을 논리 앱 워크플로 전체에서 간편하게 참조하고 사용할 수 있습니다.

쿼리를 실행하고 결과를 나열 단계의 샘플 출력을 사용할 수 있습니다.

  1. Logic Apps 리본에서 트리거 실행을 선택합니다. 그런 다음 실행을 선택하고 출력 레코드를 다운로드하여 저장합니다. 이전 계통의 샘플 쿼리의 경우 다음 샘플 출력을 사용할 수 있습니다.

    {
        "TimeGenerated": "2020-09-29T23:11:02.578Z",
        "BlobTime": "2020-09-29T23:00:00Z",
        "OperationName": "Returns Storage Account SAS Token",
        "OperationNameValue": "MICROSOFT.RESOURCES/DEPLOYMENTS/WRITE",
        "Level": "Informational",
        "ActivityStatus": "Started",
        "ResourceGroup": "monitoring",
        "SubscriptionId": "aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e",
        "Category": "Administrative",
        "EventSubmissionTimestamp": "2020-09-29T23:11:02Z",
        "ClientIpAddress": "192.168.1.100",
        "ResourceId": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/monitoring/providers/microsoft.storage/storageaccounts/my-storage-account"
    }
    
  2. +새 단계를 선택한 다음 +작업 추가를 선택합니다. 작업 선택에서 json을 입력한 다음 JSON 구문 분석을 선택합니다.

    Parse JSON 연산자를 선택하는 방법을 보여 주는 스크린샷.

  3. 콘텐츠 상자를 선택하여 이전 활동의 값 목록을 표시합니다. 쿼리 실행 및 결과 표시에서 본문을 선택합니다. 이 출력의 출처는 로그 쿼리입니다.

    본문을 선택하는 모습을 보여 주는 스크린샷.

  4. 앞에서 저장한 샘플 레코드를 복사합니다. 샘플 페이로드를 사용하여 스키마 생성을 선택하고 붙여 넣습니다.

    JSON 페이로드를 구문 분석하는 방법을 보여 주는 스크린샷.

작성 작업 추가

작성 작업은 구문 분석된 JSON 출력을 사용하고 Blob에 저장해야 하는 개체를 만듭니다.

  1. +새 단계를 선택한 다음 +작업 추가를 선택합니다. 작업 선택에서 comopose를 입력합니다. 그런 다음 작성 작업을 선택합니다.

    작성 작업을 선택하는 모습을 보여 주는 스크린샷.

  2. 입력 상자를 선택하면 이전 작업의 값 목록이 표시됩니다. JSON 구문 분석 작업에서 본문을 선택합니다. 이 구문 분석 출력의 출처는 로그 쿼리입니다.

    작성 작업을 위해 본문을 선택하는 모습을 보여 주는 스크린샷.

Blob 만들기 작업 추가

Blob 만들기 작업은 작성된 JSON을 스토리지에 씁니다.

  1. +새 단계를 선택한 다음 +작업 추가를 선택합니다. 작업 선택에서 blob를 입력합니다. 그런 다음 Blob 만들기 작업을 선택합니다.

    Blob 만들기 작업을 선택하는 모습을 보여 주는 스크린샷.

  2. 연결 이름에 스토리지 계정에 연결할 이름을 입력합니다. 그런 다음 폴더 경로 상자에서 폴더 아이콘을 선택하여 스토리지 계정의 컨테이너를 선택합니다. Blob 이름을 선택하여 이전 활동의 값 목록을 확인합니다. 을 선택하고 시간 간격과 일치하는 식을 입력합니다. 매시간 실행되는 이 쿼리의 경우 다음 식은 이전 시간별로 Blob 이름을 설정합니다.

    subtractFromTime(formatDateTime(utcNow(),'yyyy-MM-ddTHH:00:00'), 1,'Hour')
    

    Blob 식을 보여 주는 스크린샷.

  3. Blob 콘텐츠 상자를 선택하여 이전 활동의 값 목록을 표시합니다. 그런 다음 작성 섹션에서 출력을 선택합니다.

    Blob 식을 만드는 방법을 보여 주는 스크린샷.

워크플로 테스트

워크플로를 테스트하려면 실행을 선택합니다. 워크플로에 오류가 있는 경우 문제가 있는 단계에 오류가 표시됩니다. 실행을 보고 각 단계로 드릴인하여 입력과 출력을 보고 실패를 조사할 수 있습니다. 필요한 경우 Azure Logic Apps에서 워크플로 오류를 진단하고 해결을 참조합니다.

실행 기록을 보여 주는 스크린샷.

스토리지에서 로그 보기

Azure Portal의 스토리지 계정 메뉴로 이동하여 스토리지 계정을 선택합니다. Blob 타일을 선택합니다. 그런 다음 Blob 만들기 작업에서 지정한 컨테이너를 선택합니다. Blob 중 하나를 선택한 다음 Blob 편집을 선택합니다.

Blob 데이터를 보여 주는 스크린샷.

논리 앱 템플릿

선택적 JSON 구문 분석 단계는 템플릿에 포함되지 않습니다.

{
    "definition": {
        "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
        "actions": {
            "Compose": {
                "inputs": "@body('Run_query_and_list_results')",
                "runAfter": {
                    "Run_query_and_list_results": [
                        "Succeeded"
                    ]
                },
                "type": "Compose"
            },
            "Create_blob_(V2)": {
                "inputs": {
                    "body": "@outputs('Compose')",
                    "headers": {
                        "ReadFileMetadataFromServer": true
                    },
                    "host": {
                        "connection": {
                            "name": "@parameters('$connections')['azureblob']['connectionId']"
                        }
                    },
                    "method": "post",
                    "path": "/v2/datasets/@{encodeURIComponent(encodeURIComponent('AccountNameFromSettings'))}/files",
                    "queries": {
                        "folderPath": "/logicappexport",
                        "name": "@{utcNow()}",
                        "queryParametersSingleEncoded": true
                    }
                },
                "runAfter": {
                    "Compose": [
                        "Succeeded"
                    ]
                },
                "runtimeConfiguration": {
                    "contentTransfer": {
                        "transferMode": "Chunked"
                    }
                },
                "type": "ApiConnection"
            },
            "Run_query_and_list_results": {
                "inputs": {
                    "body": "let dt = now();\nlet year = datetime_part('year', dt);\nlet month = datetime_part('month', dt);\nlet day = datetime_part('day', dt);\n let hour = datetime_part('hour', dt);\nlet startTime = make_datetime(year,month,day,hour,0)-1h;\nlet endTime = startTime + 1h - 1tick;\nAzureActivity\n| where ingestion_time() between(startTime .. endTime)\n| project \n    TimeGenerated,\n    BlobTime = startTime, \n    OperationName ,\n    OperationNameValue ,\n    Level ,\n    ActivityStatus ,\n    ResourceGroup ,\n    SubscriptionId ,\n    Category ,\n    EventSubmissionTimestamp ,\n    ClientIpAddress = parse_json(HTTPRequest).clientIpAddress ,\n    ResourceId = _ResourceId ",
                    "host": {
                        "connection": {
                            "name": "@parameters('$connections')['azuremonitorlogs']['connectionId']"
                        }
                    },
                    "method": "post",
                    "path": "/queryData",
                    "queries": {
                        "resourcegroups": "resource-group-name",
                        "resourcename": "workspace-name",
                        "resourcetype": "Log Analytics Workspace",
                        "subscriptions": "workspace-subscription-id",
                        "timerange": "Set in query"
                    }
                },
                "runAfter": {},
                "type": "ApiConnection"
            }
        },
        "contentVersion": "1.0.0.0",
        "outputs": {},
        "parameters": {
            "$connections": {
                "defaultValue": {},
                "type": "Object"
            }
        },
        "triggers": {
            "Recurrence": {
                "evaluatedRecurrence": {
                    "frequency": "Day",
                    "interval": 1
                },
                "recurrence": {
                    "frequency": "Day",
                    "interval": 1
                },
                "type": "Recurrence"
            }
        }
    },
    "parameters": {
        "$connections": {
            "value": {
                "azureblob": {
                    "connectionId": "/subscriptions/logic-app-subscription-id/resourceGroups/logic-app-resource-group-name/providers/Microsoft.Web/connections/blob-connection-name",
                    "connectionName": "blob-connection-name",
                    "id": "/subscriptions/logic-app-subscription-id/providers/Microsoft.Web/locations/canadacentral/managedApis/azureblob"
                },
                "azuremonitorlogs": {
                    "connectionId": "/subscriptions/blob-connection-name/resourceGroups/logic-app-resource-group-name/providers/Microsoft.Web/connections/azure-monitor-logs-connection-name",
                    "connectionName": "azure-monitor-logs-connection-name",
                    "id": "/subscriptions/blob-connection-name/providers/Microsoft.Web/locations/canadacentral/managedApis/azuremonitorlogs"
                }
            }
        }
    }
}

다음 단계