2727from opencensus .common import utils
2828from opencensus .common .monitored_resource import monitored_resource
2929from opencensus .common .version import __version__
30+ from opencensus .metrics import label_key
31+ from opencensus .metrics import label_value
3032from opencensus .metrics import transport
3133from opencensus .metrics .export import metric as metric_module
3234from opencensus .metrics .export import metric_descriptor
6567
6668
6769class Options (object ):
68- """ Options contains options for configuring the exporter.
70+ """Exporter configuration options.
71+
72+ `resource` is an optional field that represents the Stackdriver monitored
73+ resource type. If unset, this defaults to a `MonitoredResource` with type
74+ "global" and no resource labels.
75+
76+ `default_monitoring_labels` are labels added to every metric created by
77+ this exporter. If unset, this defaults to a single label with key
78+ "opencensus_task" and value "py-<pid>@<hostname>". This default ensures
79+ that the set of labels together with the default resource (global) are
80+ unique to this process, as required by stackdriver.
81+
82+ If you set `default_monitoring_labels`, make sure that the `resource`
83+ field together with these labels is unique to the current process. This is
84+ to ensure that there is only a single writer to each time series in
85+ Stackdriver.
86+
87+ Set `default_monitoring_labels` to `{}` to avoid getting the default
88+ "opencensus_task" label. You should only do this if you know that
89+ `resource` uniquely identifies this process.
90+
91+ :type project_id: str
92+ :param project_id: The ID GCP project to export metrics to, fall back to
93+ default application credentials if unset.
94+
95+ :type resource: str
96+ :param resource: The stackdriver monitored resource type, defaults to
97+ global.
98+
99+ :type metric_prefix: str
100+ :param metric_prefix: Custom prefix for metric name and type.
101+
102+ :type default_monitoring_labels: dict(
103+ :class:`opencensus.metrics.label_key.LabelKey`,
104+ :class:`opencensus.metrics.label_value.LabelValue`)
105+ :param default_monitoring_labels: Default labels to be set on each exported
106+ metric.
69107 """
108+
70109 def __init__ (self ,
71110 project_id = "" ,
72111 resource = "" ,
73112 metric_prefix = "" ,
74113 default_monitoring_labels = None ):
75- self ._project_id = project_id
76- self ._resource = resource
77- self ._metric_prefix = metric_prefix
78- self ._default_monitoring_labels = default_monitoring_labels
79-
80- @property
81- def project_id (self ):
82- """ project_id is the identifier of the Stackdriver
83- project the user is uploading the stats data to.
84- If not set, this will default to
85- your "Application Default Credentials".
86- """
87- return self ._project_id
88-
89- @property
90- def resource (self ):
91- """ Resource is an optional field that represents the Stackdriver
92- MonitoredResource type, a resource that can be used for monitoring.
93- If no custom ResourceDescriptor is set, a default MonitoredResource
94- with type global and no resource labels will be used.
95- Optional.
96- """
97- return self ._resource
98-
99- @property
100- def metric_prefix (self ):
101- """ metric_prefix overrides the
102- OpenCensus prefix of a stackdriver metric.
103- Optional.
104- """
105- return self ._metric_prefix
106-
107- @property
108- def default_monitoring_labels (self ):
109- """ default_monitoring_labels are labels added to
110- every metric created by this
111- exporter in Stackdriver Monitoring.
112-
113- If unset, this defaults to a single label
114- with key "opencensus_task" and value "py-<pid>@<hostname>".
115- This default ensures that the set of labels together with
116- the default Resource (global) are unique to this
117- process, as required by Stackdriver Monitoring.
118-
119- If you set default_monitoring_labels,
120- make sure that the Resource field
121- together with these labels is unique to the
122- current process. This is to ensure that
123- there is only a single writer to
124- each TimeSeries in Stackdriver.
125-
126- Set this to Labels to avoid getting the
127- default "opencensus_task" label.
128- You should only do this if you know that
129- the Resource you set uniquely identifies this Python process.
130- """
131- return self ._default_monitoring_labels
114+ self .project_id = project_id
115+ self .resource = resource
116+ self .metric_prefix = metric_prefix
117+
118+ if default_monitoring_labels is None :
119+ self .default_monitoring_labels = {
120+ label_key .LabelKey (OPENCENSUS_TASK ,
121+ OPENCENSUS_TASK_DESCRIPTION ):
122+ label_value .LabelValue (get_task_value ())
123+ }
124+ else :
125+ for key , val in default_monitoring_labels .items ():
126+ if not isinstance (key , label_key .LabelKey ):
127+ raise TypeError
128+ if not isinstance (val , label_value .LabelValue ):
129+ raise TypeError
130+ self .default_monitoring_labels = default_monitoring_labels
132131
133132
134133class StackdriverStatsExporter (object ):
@@ -173,10 +172,10 @@ def create_time_series_list(self, metric):
173172 def _convert_series (self , metric , ts ):
174173 """Convert an OC timeseries to a SD series."""
175174 series = monitoring_v3 .types .TimeSeries ()
176- series .metric .type = namespaced_view_name (
177- metric .descriptor .name , self .options .metric_prefix )
175+ series .metric .type = self .get_metric_type (metric .descriptor )
178176
179- series .metric .labels [OPENCENSUS_TASK ] = get_task_value ()
177+ for lk , lv in self .options .default_monitoring_labels .items ():
178+ series .metric .labels [lk .key ] = lv .value
180179
181180 for key , val in zip (metric .descriptor .label_keys , ts .label_values ):
182181 if val .value is not None :
@@ -252,8 +251,8 @@ def _convert_point(self, metric, ts, point, sd_point):
252251 start_time .seconds = int (timestamp_start )
253252 start_time .nanos = int ((timestamp_start - start_time .seconds ) * 1e9 )
254253
255- def get_descriptor_type (self , oc_md ):
256- """Get a SD descriptor type for an OC metric descriptor."""
254+ def get_metric_type (self , oc_md ):
255+ """Get a SD metric type for an OC metric descriptor."""
257256 return namespaced_view_name (oc_md .name , self .options .metric_prefix )
258257
259258 def get_metric_descriptor (self , oc_md ):
@@ -268,13 +267,11 @@ def get_metric_descriptor(self, oc_md):
268267 else :
269268 display_name_prefix = DEFAULT_DISPLAY_NAME_PREFIX
270269
271- default_labels = self .options .default_monitoring_labels
272- if default_labels is None :
273- default_labels = {}
274- desc_labels = new_label_descriptors (default_labels , oc_md .label_keys )
270+ desc_labels = new_label_descriptors (
271+ self .options .default_monitoring_labels , oc_md .label_keys )
275272
276273 descriptor = monitoring_v3 .types .MetricDescriptor (labels = desc_labels )
277- metric_type = self .get_descriptor_type (oc_md )
274+ metric_type = self .get_metric_type (oc_md )
278275 descriptor .type = metric_type
279276 descriptor .metric_kind = metric_kind
280277 descriptor .value_type = value_type
@@ -289,16 +286,16 @@ def get_metric_descriptor(self, oc_md):
289286
290287 def register_metric_descriptor (self , oc_md ):
291288 """Register a metric descriptor with stackdriver."""
292- descriptor_type = self .get_descriptor_type (oc_md )
289+ metric_type = self .get_metric_type (oc_md )
293290 with self ._md_lock :
294- if descriptor_type in self ._md_cache :
295- return self ._md_cache [descriptor_type ]
291+ if metric_type in self ._md_cache :
292+ return self ._md_cache [metric_type ]
296293
297294 descriptor = self .get_metric_descriptor (oc_md )
298295 project_name = self .client .project_path (self .options .project_id )
299296 sd_md = self .client .create_metric_descriptor (project_name , descriptor )
300297 with self ._md_lock :
301- self ._md_cache [descriptor_type ] = sd_md
298+ self ._md_cache [metric_type ] = sd_md
302299 return sd_md
303300
304301
@@ -424,19 +421,12 @@ def new_label_descriptors(defaults, keys):
424421 that will be sent to Stackdriver Monitoring
425422 """
426423 label_descriptors = []
427- for key , lbl in defaults .items ( ):
424+ for lk in itertools . chain . from_iterable (( defaults .keys (), keys ) ):
428425 label = {}
429- label ["key" ] = sanitize_label (key )
430- label ["description" ] = lbl
426+ label ["key" ] = sanitize_label (lk . key )
427+ label ["description" ] = lk . description
431428 label_descriptors .append (label )
432429
433- for label_key in keys :
434- label = {}
435- label ["key" ] = sanitize_label (label_key .key )
436- label ["description" ] = sanitize_label (label_key .description )
437- label_descriptors .append (label )
438- label_descriptors .append ({"key" : OPENCENSUS_TASK ,
439- "description" : OPENCENSUS_TASK_DESCRIPTION })
440430 return label_descriptors
441431
442432
0 commit comments