새소식

반응형
GCP/운영관련 개발

GCP-stackdriver python api 사용하기(list_time_series)

  • -
반응형

안녕하세요. 

google compute engine(이하 GCE)을 모니터링해야 해서 stackdriver를 적극적으로 활용하려고 하였는데요. 

너무 UI도 별로고 제가 하고싶은데로 변형해서 사용하기에 너무 불편해서 직접 python api를 이용해서 데이터를 읽고 이를 mysql에 넣어서 datastudio로 만드는 방법을 선택하였습니다. (여기서는 API 사용법만 설명합니다..)

그런데 이 python api가 너무 설명도 많이 없고 불친절해서 하면서 겪은 이슈에 대해서 정리하였습니다.

 

우선 제가 참고한 api는 list_time_series라는 google에서 제공하는 phyton api입니다. 아래의 url을 들어가 보면 python뿐만 아니라 다양한 언어를 지원하는 듯합니다.

https://cloud.google.com/monitoring/custom-metrics/reading-metrics

 

측정항목 데이터 읽기  |  Stackdriver Monitoring  |  Google Cloud

이 페이지에서는 Monitoring API의 timeSeries.list 메소드를 사용하여 측정항목 데이터(시계열 데이터라고도 함)를 읽는 방법을 설명합니다. 이 메소드는 여러 가지 방법으로 사용할 수 있습니다. 코드를 작성하지 않고 list 메소드를 실행하기 위해 이 페이지의 프로토콜 탭의 예에서는 양식 기반 API 탐색기를 사용합니다. 이 도구에 대한 자세한 내용은 API 탐색기를 참조하세요. 선택한 프로그래밍 언어로 list 메소드를 사용하는 방법을

cloud.google.com

 

 

1. Stackdriver 수집 API 

위의 링크에서 시계열 데이터를 읽기 정렬해서 읽기 위해서 사용하는 예제 코드가 있는데 다음과 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
client = monitoring_v3.MetricServiceClient()
project_name = client.project_path(project_id)
interval = monitoring_v3.types.TimeInterval()
now = time.time()
interval.end_time.seconds = int(now)
interval.end_time.nanos = int(
    (now - interval.end_time.seconds) * 10**9)
interval.start_time.seconds = int(now - 3600)
interval.start_time.nanos = interval.end_time.nanos
aggregation = monitoring_v3.types.Aggregation()
aggregation.alignment_period.seconds = 300  # 5 minutes
aggregation.per_series_aligner = (
    monitoring_v3.enums.Aggregation.Aligner.ALIGN_MEAN)
 
results = client.list_time_series(
    project_name,
    'metric.type = "compute.googleapis.com/instance/cpu/utilization"',
    interval,
    monitoring_v3.enums.ListTimeSeriesRequest.TimeSeriesView.FULL,
    aggregation)
for result in results:
    print(result)
cs

 

음... 사실 봐도 잘 모르겠습니다. 그냥 돌리면 당연히 오류가 납니다. 

라이브러리를 써야 하는데 선언도 안 했거든요. 그래서 선언을 먼저 해야 합니다. 구글링을 해보면 다음과 같은 라이브러리가 필요합니다.

1
from google.cloud import monitoring_v3
cs

 

위의 라이브러리를 선언하고 돌리면 google 라이브러리가 없다고 하면서 오류가 납니다.

이를 다시 검색해서 다음의 링크를 참고해서 다음의 라이브러리를 설치해야 합니다.

1
pip install --upgrade google-cloud-monitoring
cs

 

위의 라이브러리를 설치하면 실행이 됩니다. 물론 이러한 오류가 날 수 있습니다. 

 

google.auth.exceptions.DefaultCredentialsError: Could not automatically determine credentials. 

Please set GOOGLE_APPLICATION_CREDENTIALS or explicitly create credentials and re-run the application. For more information, please see https://cloud.google.com/docs/authentication/getting-started

다음의 코드를 넣어서 문제를 해결해 주세요. (안 나는 경우는 기본 설정에 키가 잘 설정되어 있어서 그렇습니다.)

1
2
3
import os
 
os.environ["GOOGLE_APPLICATION_CREDENTIALS"]="gogle credentials 위치" 
cs

 

 

2. Metric 리스트 확인 및 필터 걸기

이렇게 할 경우 정상적으로 실행이 됩니다. 그런데 여기서 필요한 게 있습니다. 

api를 호출할 때 다음과 같은 부분이 있습니다. 어떠한 metric을 가져올지 필터를 걸어야 합니다. 여기서 필터는 metric뿐만 아니라 어떠한 인스턴스를 가져올지도 선택할 수 있습니다. 그런데, 이 metric 타입이 무엇이 있는지 알 수가 없습니다... 안 나옵니다.

'metric.type = "compute.googleapis.com/instance/cpu/utilization"'

맨 위에 공유드린 내용을 보면 아래처럼 다양한 방법으로 필터를 걸 수 있습니다. 단, 여러 개의 metric을 한 번에 가져올 순 없습니다. (해봤는데 안돼요...) 저 같은 경우 metric을 가져오면서 특정 인스턴스에서만 가져오도록 or조건을 줬습니다.

'metric.type = "compute.googleapis.com/instance/cpu/utilization" AND (metric.label.instance_name = "server-1" OR metric.label.instance_name = "server-2" OR metric.label.instance_name = "server-3")'

첫 번째로 metric의 type은 다음의 api를 통해서 알 수 있습니다. 링크

 

Stackdriver Monitoring Client — google-cloud 0.28.1.dev1 documentation

Stackdriver Monitoring Client Client for interacting with the Google Stackdriver Monitoring API (V3). Example: >>> from google.cloud import monitoring >>> client = monitoring.Client() >>> query = client.query(minutes=5) >>> print(query.as_dataframe()) # Re

google-cloud-python.readthedocs.io

링크를 클릭하시면 list_metric_descriptors api가 있습니다. 항목이 매우 많기 때문에 저 같은 경우 TEXT 파일로 저장하는 코드를 만들었습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
from google.cloud import monitoring_v3
import os
 
os.environ["GOOGLE_APPLICATION_CREDENTIALS"]="gogle_credentials 위치" 
client = monitoring_v3.MetricServiceClient()
project_name = client.project_path("프로젝트명")
 
= open("저장위치"'w')
 
for descriptor in client.list_metric_descriptors(project_name):
    #print(descriptor.type)
    f.write(descriptor.type+"\n")
 
f.close()
cs

 

위의 내용을 저장하셔서 TEXT를 열어보면 아주 많은 metric이 있습니다. (아래의 내용은 metric타입의 일부입니다.) 또한 metric의 설명을 보시려면 링크를 참고해주세요.

agent.googleapis.com/couchdb/httpd/bulk_request_count
agent.googleapis.com/couchdb/httpd/request_count
agent.googleapis.com/couchdb/httpd/request_method_count
agent.googleapis.com/couchdb/httpd/response_code_count
agent.googleapis.com/couchdb/httpd/temporary_view_read_count
agent.googleapis.com/couchdb/httpd/view_read_count
agent.googleapis.com/couchdb/open_databases
agent.googleapis.com/couchdb/open_files
agent.googleapis.com/couchdb/read_count
agent.googleapis.com/couchdb/write_count
agent.googleapis.com/cpu/load_15m
agent.googleapis.com/cpu/load_1m
agent.googleapis.com/cpu/load_5m
agent.googleapis.com/cpu/usage_time

 

그리고 위의 metric뿐만 아니라 다양한 필터를 걸고 싶은데 어떻게 조건을 줘야 할지 모르실 겁니다. 위에서 처음에 코드를 실행하면 아마도 다음과 같은 형태의 결과를 print 할 겁니다.

metric {
  labels {
    key: "instance_name"
    value: "test-server"
  }
  type: "compute.googleapis.com/instance/memory/balloon/ram_size"
}
resource {
  type: "gce_instance"
  labels {
    key: "instance_id"
    value: "1234"
  }
  labels {
    key: "project_id"
    value: "test-project"
  }
  labels {
    key: "zone"
    value: "us-east1-b"
  }
}


위에서 보는 것을 잘 보시면 필터를 어떻게 걸지 짐작할 수 있습니다. 아래의 내용을 보시면 metric.type에 = 을 걸어서 필터를 사용했습니다. 이를 특정 인스턴스로 한다면 다음과 같이 할 수 있습니다. 이렇게 하면 해당 instance명을 가진 서버만 가져오도록 합니다.

'metric.label.instance_name = "test-server"'

응용하면 여러 가지 조건을 필터 할 수 있습니다.

 

 

3. Stackdriver 결과 값 저장

허접하지만 아래와 같이 함수를 만들어서 각 항목마다 저장하도록 만들었습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    def disk_perf(self,kst_todate_str,kst_HH_str,kst_todate):
        print("DISK SIZE perfmon value insert...")
        results = client.list_time_series(
            project_name,
            'metric.type = "agent.googleapis.com/disk/percent_used" AND metric.label.device = "sda1"',
            interval,
            monitoring_v3.enums.ListTimeSeriesRequest.TimeSeriesView.FULL,
            aggregation)
 
        result_list = []
        mysql = MYSQL_OPERATOR()
 
        for result in results:
            #print(result) #결과를 한번 찍어보세요.
 
            project = result.resource.labels.get("project_id")
            instance_id = result.resource.labels.get("instance_id")
            instance_name = result.metric.labels.get("instance_name")
            mon_type = result.metric.type
            metric_type_details = result.metric.labels.get("state")
            value = (result.points[0].value.double_value)
 
            result_list.append((kst_todate_str,kst_HH_str,project,instance_id,instance_name,mon_type,metric_type_details,value,kst_todate))
 
        mysql.mondb_delete(kst_todate_str,kst_HH_str,mon_type)
        mysql.mondb_insert(result_list)
        
        return "end DISK SIZE crawling process..."
cs

 

 

 

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.