1// Copyright 2020 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Code generated by protoc-gen-go_gapic. DO NOT EDIT.
16
17package monitoring
18
19import (
20	"context"
21	"fmt"
22	"math"
23	"net/url"
24	"time"
25
26	"github.com/golang/protobuf/proto"
27	gax "github.com/googleapis/gax-go/v2"
28	"google.golang.org/api/iterator"
29	"google.golang.org/api/option"
30	gtransport "google.golang.org/api/transport/grpc"
31	metricpb "google.golang.org/genproto/googleapis/api/metric"
32	monitoredrespb "google.golang.org/genproto/googleapis/api/monitoredres"
33	monitoringpb "google.golang.org/genproto/googleapis/monitoring/v3"
34	"google.golang.org/grpc"
35	"google.golang.org/grpc/codes"
36	"google.golang.org/grpc/metadata"
37)
38
39var newMetricClientHook clientHook
40
41// MetricCallOptions contains the retry settings for each method of MetricClient.
42type MetricCallOptions struct {
43	ListMonitoredResourceDescriptors []gax.CallOption
44	GetMonitoredResourceDescriptor   []gax.CallOption
45	ListMetricDescriptors            []gax.CallOption
46	GetMetricDescriptor              []gax.CallOption
47	CreateMetricDescriptor           []gax.CallOption
48	DeleteMetricDescriptor           []gax.CallOption
49	ListTimeSeries                   []gax.CallOption
50	CreateTimeSeries                 []gax.CallOption
51}
52
53func defaultMetricClientOptions() []option.ClientOption {
54	return []option.ClientOption{
55		option.WithEndpoint("monitoring.googleapis.com:443"),
56		option.WithGRPCDialOption(grpc.WithDisableServiceConfig()),
57		option.WithScopes(DefaultAuthScopes()...),
58		option.WithGRPCDialOption(grpc.WithDefaultCallOptions(
59			grpc.MaxCallRecvMsgSize(math.MaxInt32))),
60	}
61}
62
63func defaultMetricCallOptions() *MetricCallOptions {
64	return &MetricCallOptions{
65		ListMonitoredResourceDescriptors: []gax.CallOption{
66			gax.WithRetry(func() gax.Retryer {
67				return gax.OnCodes([]codes.Code{
68					codes.DeadlineExceeded,
69					codes.Unavailable,
70				}, gax.Backoff{
71					Initial:    100 * time.Millisecond,
72					Max:        30000 * time.Millisecond,
73					Multiplier: 1.30,
74				})
75			}),
76		},
77		GetMonitoredResourceDescriptor: []gax.CallOption{
78			gax.WithRetry(func() gax.Retryer {
79				return gax.OnCodes([]codes.Code{
80					codes.DeadlineExceeded,
81					codes.Unavailable,
82				}, gax.Backoff{
83					Initial:    100 * time.Millisecond,
84					Max:        30000 * time.Millisecond,
85					Multiplier: 1.30,
86				})
87			}),
88		},
89		ListMetricDescriptors: []gax.CallOption{
90			gax.WithRetry(func() gax.Retryer {
91				return gax.OnCodes([]codes.Code{
92					codes.DeadlineExceeded,
93					codes.Unavailable,
94				}, gax.Backoff{
95					Initial:    100 * time.Millisecond,
96					Max:        30000 * time.Millisecond,
97					Multiplier: 1.30,
98				})
99			}),
100		},
101		GetMetricDescriptor: []gax.CallOption{
102			gax.WithRetry(func() gax.Retryer {
103				return gax.OnCodes([]codes.Code{
104					codes.DeadlineExceeded,
105					codes.Unavailable,
106				}, gax.Backoff{
107					Initial:    100 * time.Millisecond,
108					Max:        30000 * time.Millisecond,
109					Multiplier: 1.30,
110				})
111			}),
112		},
113		CreateMetricDescriptor: []gax.CallOption{},
114		DeleteMetricDescriptor: []gax.CallOption{
115			gax.WithRetry(func() gax.Retryer {
116				return gax.OnCodes([]codes.Code{
117					codes.DeadlineExceeded,
118					codes.Unavailable,
119				}, gax.Backoff{
120					Initial:    100 * time.Millisecond,
121					Max:        30000 * time.Millisecond,
122					Multiplier: 1.30,
123				})
124			}),
125		},
126		ListTimeSeries: []gax.CallOption{
127			gax.WithRetry(func() gax.Retryer {
128				return gax.OnCodes([]codes.Code{
129					codes.DeadlineExceeded,
130					codes.Unavailable,
131				}, gax.Backoff{
132					Initial:    100 * time.Millisecond,
133					Max:        30000 * time.Millisecond,
134					Multiplier: 1.30,
135				})
136			}),
137		},
138		CreateTimeSeries: []gax.CallOption{},
139	}
140}
141
142// MetricClient is a client for interacting with Cloud Monitoring API.
143//
144// Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls.
145type MetricClient struct {
146	// Connection pool of gRPC connections to the service.
147	connPool gtransport.ConnPool
148
149	// The gRPC API client.
150	metricClient monitoringpb.MetricServiceClient
151
152	// The call options for this service.
153	CallOptions *MetricCallOptions
154
155	// The x-goog-* metadata to be sent with each request.
156	xGoogMetadata metadata.MD
157}
158
159// NewMetricClient creates a new metric service client.
160//
161// Manages metric descriptors, monitored resource descriptors, and
162// time series data.
163func NewMetricClient(ctx context.Context, opts ...option.ClientOption) (*MetricClient, error) {
164	clientOpts := defaultMetricClientOptions()
165
166	if newMetricClientHook != nil {
167		hookOpts, err := newMetricClientHook(ctx, clientHookParams{})
168		if err != nil {
169			return nil, err
170		}
171		clientOpts = append(clientOpts, hookOpts...)
172	}
173
174	connPool, err := gtransport.DialPool(ctx, append(clientOpts, opts...)...)
175	if err != nil {
176		return nil, err
177	}
178	c := &MetricClient{
179		connPool:    connPool,
180		CallOptions: defaultMetricCallOptions(),
181
182		metricClient: monitoringpb.NewMetricServiceClient(connPool),
183	}
184	c.setGoogleClientInfo()
185
186	return c, nil
187}
188
189// Connection returns a connection to the API service.
190//
191// Deprecated.
192func (c *MetricClient) Connection() *grpc.ClientConn {
193	return c.connPool.Conn()
194}
195
196// Close closes the connection to the API service. The user should invoke this when
197// the client is no longer required.
198func (c *MetricClient) Close() error {
199	return c.connPool.Close()
200}
201
202// setGoogleClientInfo sets the name and version of the application in
203// the `x-goog-api-client` header passed on each request. Intended for
204// use by Google-written clients.
205func (c *MetricClient) setGoogleClientInfo(keyval ...string) {
206	kv := append([]string{"gl-go", versionGo()}, keyval...)
207	kv = append(kv, "gapic", versionClient, "gax", gax.Version, "grpc", grpc.Version)
208	c.xGoogMetadata = metadata.Pairs("x-goog-api-client", gax.XGoogHeader(kv...))
209}
210
211// ListMonitoredResourceDescriptors lists monitored resource descriptors that match a filter. This method does not require a Workspace.
212func (c *MetricClient) ListMonitoredResourceDescriptors(ctx context.Context, req *monitoringpb.ListMonitoredResourceDescriptorsRequest, opts ...gax.CallOption) *MonitoredResourceDescriptorIterator {
213	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName())))
214	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
215	opts = append(c.CallOptions.ListMonitoredResourceDescriptors[0:len(c.CallOptions.ListMonitoredResourceDescriptors):len(c.CallOptions.ListMonitoredResourceDescriptors)], opts...)
216	it := &MonitoredResourceDescriptorIterator{}
217	req = proto.Clone(req).(*monitoringpb.ListMonitoredResourceDescriptorsRequest)
218	it.InternalFetch = func(pageSize int, pageToken string) ([]*monitoredrespb.MonitoredResourceDescriptor, string, error) {
219		var resp *monitoringpb.ListMonitoredResourceDescriptorsResponse
220		req.PageToken = pageToken
221		if pageSize > math.MaxInt32 {
222			req.PageSize = math.MaxInt32
223		} else {
224			req.PageSize = int32(pageSize)
225		}
226		err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
227			var err error
228			resp, err = c.metricClient.ListMonitoredResourceDescriptors(ctx, req, settings.GRPC...)
229			return err
230		}, opts...)
231		if err != nil {
232			return nil, "", err
233		}
234
235		it.Response = resp
236		return resp.ResourceDescriptors, resp.NextPageToken, nil
237	}
238	fetch := func(pageSize int, pageToken string) (string, error) {
239		items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
240		if err != nil {
241			return "", err
242		}
243		it.items = append(it.items, items...)
244		return nextPageToken, nil
245	}
246	it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
247	it.pageInfo.MaxSize = int(req.PageSize)
248	it.pageInfo.Token = req.PageToken
249	return it
250}
251
252// GetMonitoredResourceDescriptor gets a single monitored resource descriptor. This method does not require a Workspace.
253func (c *MetricClient) GetMonitoredResourceDescriptor(ctx context.Context, req *monitoringpb.GetMonitoredResourceDescriptorRequest, opts ...gax.CallOption) (*monitoredrespb.MonitoredResourceDescriptor, error) {
254	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName())))
255	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
256	opts = append(c.CallOptions.GetMonitoredResourceDescriptor[0:len(c.CallOptions.GetMonitoredResourceDescriptor):len(c.CallOptions.GetMonitoredResourceDescriptor)], opts...)
257	var resp *monitoredrespb.MonitoredResourceDescriptor
258	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
259		var err error
260		resp, err = c.metricClient.GetMonitoredResourceDescriptor(ctx, req, settings.GRPC...)
261		return err
262	}, opts...)
263	if err != nil {
264		return nil, err
265	}
266	return resp, nil
267}
268
269// ListMetricDescriptors lists metric descriptors that match a filter. This method does not require a Workspace.
270func (c *MetricClient) ListMetricDescriptors(ctx context.Context, req *monitoringpb.ListMetricDescriptorsRequest, opts ...gax.CallOption) *MetricDescriptorIterator {
271	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName())))
272	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
273	opts = append(c.CallOptions.ListMetricDescriptors[0:len(c.CallOptions.ListMetricDescriptors):len(c.CallOptions.ListMetricDescriptors)], opts...)
274	it := &MetricDescriptorIterator{}
275	req = proto.Clone(req).(*monitoringpb.ListMetricDescriptorsRequest)
276	it.InternalFetch = func(pageSize int, pageToken string) ([]*metricpb.MetricDescriptor, string, error) {
277		var resp *monitoringpb.ListMetricDescriptorsResponse
278		req.PageToken = pageToken
279		if pageSize > math.MaxInt32 {
280			req.PageSize = math.MaxInt32
281		} else {
282			req.PageSize = int32(pageSize)
283		}
284		err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
285			var err error
286			resp, err = c.metricClient.ListMetricDescriptors(ctx, req, settings.GRPC...)
287			return err
288		}, opts...)
289		if err != nil {
290			return nil, "", err
291		}
292
293		it.Response = resp
294		return resp.MetricDescriptors, resp.NextPageToken, nil
295	}
296	fetch := func(pageSize int, pageToken string) (string, error) {
297		items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
298		if err != nil {
299			return "", err
300		}
301		it.items = append(it.items, items...)
302		return nextPageToken, nil
303	}
304	it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
305	it.pageInfo.MaxSize = int(req.PageSize)
306	it.pageInfo.Token = req.PageToken
307	return it
308}
309
310// GetMetricDescriptor gets a single metric descriptor. This method does not require a Workspace.
311func (c *MetricClient) GetMetricDescriptor(ctx context.Context, req *monitoringpb.GetMetricDescriptorRequest, opts ...gax.CallOption) (*metricpb.MetricDescriptor, error) {
312	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName())))
313	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
314	opts = append(c.CallOptions.GetMetricDescriptor[0:len(c.CallOptions.GetMetricDescriptor):len(c.CallOptions.GetMetricDescriptor)], opts...)
315	var resp *metricpb.MetricDescriptor
316	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
317		var err error
318		resp, err = c.metricClient.GetMetricDescriptor(ctx, req, settings.GRPC...)
319		return err
320	}, opts...)
321	if err != nil {
322		return nil, err
323	}
324	return resp, nil
325}
326
327// CreateMetricDescriptor creates a new metric descriptor.
328// User-created metric descriptors define
329// custom metrics (at https://cloud.google.com/monitoring/custom-metrics).
330func (c *MetricClient) CreateMetricDescriptor(ctx context.Context, req *monitoringpb.CreateMetricDescriptorRequest, opts ...gax.CallOption) (*metricpb.MetricDescriptor, error) {
331	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName())))
332	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
333	opts = append(c.CallOptions.CreateMetricDescriptor[0:len(c.CallOptions.CreateMetricDescriptor):len(c.CallOptions.CreateMetricDescriptor)], opts...)
334	var resp *metricpb.MetricDescriptor
335	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
336		var err error
337		resp, err = c.metricClient.CreateMetricDescriptor(ctx, req, settings.GRPC...)
338		return err
339	}, opts...)
340	if err != nil {
341		return nil, err
342	}
343	return resp, nil
344}
345
346// DeleteMetricDescriptor deletes a metric descriptor. Only user-created
347// custom metrics (at https://cloud.google.com/monitoring/custom-metrics) can be
348// deleted.
349func (c *MetricClient) DeleteMetricDescriptor(ctx context.Context, req *monitoringpb.DeleteMetricDescriptorRequest, opts ...gax.CallOption) error {
350	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName())))
351	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
352	opts = append(c.CallOptions.DeleteMetricDescriptor[0:len(c.CallOptions.DeleteMetricDescriptor):len(c.CallOptions.DeleteMetricDescriptor)], opts...)
353	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
354		var err error
355		_, err = c.metricClient.DeleteMetricDescriptor(ctx, req, settings.GRPC...)
356		return err
357	}, opts...)
358	return err
359}
360
361// ListTimeSeries lists time series that match a filter. This method does not require a Workspace.
362func (c *MetricClient) ListTimeSeries(ctx context.Context, req *monitoringpb.ListTimeSeriesRequest, opts ...gax.CallOption) *TimeSeriesIterator {
363	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName())))
364	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
365	opts = append(c.CallOptions.ListTimeSeries[0:len(c.CallOptions.ListTimeSeries):len(c.CallOptions.ListTimeSeries)], opts...)
366	it := &TimeSeriesIterator{}
367	req = proto.Clone(req).(*monitoringpb.ListTimeSeriesRequest)
368	it.InternalFetch = func(pageSize int, pageToken string) ([]*monitoringpb.TimeSeries, string, error) {
369		var resp *monitoringpb.ListTimeSeriesResponse
370		req.PageToken = pageToken
371		if pageSize > math.MaxInt32 {
372			req.PageSize = math.MaxInt32
373		} else {
374			req.PageSize = int32(pageSize)
375		}
376		err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
377			var err error
378			resp, err = c.metricClient.ListTimeSeries(ctx, req, settings.GRPC...)
379			return err
380		}, opts...)
381		if err != nil {
382			return nil, "", err
383		}
384
385		it.Response = resp
386		return resp.TimeSeries, resp.NextPageToken, nil
387	}
388	fetch := func(pageSize int, pageToken string) (string, error) {
389		items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
390		if err != nil {
391			return "", err
392		}
393		it.items = append(it.items, items...)
394		return nextPageToken, nil
395	}
396	it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
397	it.pageInfo.MaxSize = int(req.PageSize)
398	it.pageInfo.Token = req.PageToken
399	return it
400}
401
402// CreateTimeSeries creates or adds data to one or more time series.
403// The response is empty if all time series in the request were written.
404// If any time series could not be written, a corresponding failure message is
405// included in the error response.
406func (c *MetricClient) CreateTimeSeries(ctx context.Context, req *monitoringpb.CreateTimeSeriesRequest, opts ...gax.CallOption) error {
407	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName())))
408	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
409	opts = append(c.CallOptions.CreateTimeSeries[0:len(c.CallOptions.CreateTimeSeries):len(c.CallOptions.CreateTimeSeries)], opts...)
410	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
411		var err error
412		_, err = c.metricClient.CreateTimeSeries(ctx, req, settings.GRPC...)
413		return err
414	}, opts...)
415	return err
416}
417
418// MetricDescriptorIterator manages a stream of *metricpb.MetricDescriptor.
419type MetricDescriptorIterator struct {
420	items    []*metricpb.MetricDescriptor
421	pageInfo *iterator.PageInfo
422	nextFunc func() error
423
424	// Response is the raw response for the current page.
425	// It must be cast to the RPC response type.
426	// Calling Next() or InternalFetch() updates this value.
427	Response interface{}
428
429	// InternalFetch is for use by the Google Cloud Libraries only.
430	// It is not part of the stable interface of this package.
431	//
432	// InternalFetch returns results from a single call to the underlying RPC.
433	// The number of results is no greater than pageSize.
434	// If there are no more results, nextPageToken is empty and err is nil.
435	InternalFetch func(pageSize int, pageToken string) (results []*metricpb.MetricDescriptor, nextPageToken string, err error)
436}
437
438// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
439func (it *MetricDescriptorIterator) PageInfo() *iterator.PageInfo {
440	return it.pageInfo
441}
442
443// Next returns the next result. Its second return value is iterator.Done if there are no more
444// results. Once Next returns Done, all subsequent calls will return Done.
445func (it *MetricDescriptorIterator) Next() (*metricpb.MetricDescriptor, error) {
446	var item *metricpb.MetricDescriptor
447	if err := it.nextFunc(); err != nil {
448		return item, err
449	}
450	item = it.items[0]
451	it.items = it.items[1:]
452	return item, nil
453}
454
455func (it *MetricDescriptorIterator) bufLen() int {
456	return len(it.items)
457}
458
459func (it *MetricDescriptorIterator) takeBuf() interface{} {
460	b := it.items
461	it.items = nil
462	return b
463}
464
465// MonitoredResourceDescriptorIterator manages a stream of *monitoredrespb.MonitoredResourceDescriptor.
466type MonitoredResourceDescriptorIterator struct {
467	items    []*monitoredrespb.MonitoredResourceDescriptor
468	pageInfo *iterator.PageInfo
469	nextFunc func() error
470
471	// Response is the raw response for the current page.
472	// It must be cast to the RPC response type.
473	// Calling Next() or InternalFetch() updates this value.
474	Response interface{}
475
476	// InternalFetch is for use by the Google Cloud Libraries only.
477	// It is not part of the stable interface of this package.
478	//
479	// InternalFetch returns results from a single call to the underlying RPC.
480	// The number of results is no greater than pageSize.
481	// If there are no more results, nextPageToken is empty and err is nil.
482	InternalFetch func(pageSize int, pageToken string) (results []*monitoredrespb.MonitoredResourceDescriptor, nextPageToken string, err error)
483}
484
485// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
486func (it *MonitoredResourceDescriptorIterator) PageInfo() *iterator.PageInfo {
487	return it.pageInfo
488}
489
490// Next returns the next result. Its second return value is iterator.Done if there are no more
491// results. Once Next returns Done, all subsequent calls will return Done.
492func (it *MonitoredResourceDescriptorIterator) Next() (*monitoredrespb.MonitoredResourceDescriptor, error) {
493	var item *monitoredrespb.MonitoredResourceDescriptor
494	if err := it.nextFunc(); err != nil {
495		return item, err
496	}
497	item = it.items[0]
498	it.items = it.items[1:]
499	return item, nil
500}
501
502func (it *MonitoredResourceDescriptorIterator) bufLen() int {
503	return len(it.items)
504}
505
506func (it *MonitoredResourceDescriptorIterator) takeBuf() interface{} {
507	b := it.items
508	it.items = nil
509	return b
510}
511
512// TimeSeriesIterator manages a stream of *monitoringpb.TimeSeries.
513type TimeSeriesIterator struct {
514	items    []*monitoringpb.TimeSeries
515	pageInfo *iterator.PageInfo
516	nextFunc func() error
517
518	// Response is the raw response for the current page.
519	// It must be cast to the RPC response type.
520	// Calling Next() or InternalFetch() updates this value.
521	Response interface{}
522
523	// InternalFetch is for use by the Google Cloud Libraries only.
524	// It is not part of the stable interface of this package.
525	//
526	// InternalFetch returns results from a single call to the underlying RPC.
527	// The number of results is no greater than pageSize.
528	// If there are no more results, nextPageToken is empty and err is nil.
529	InternalFetch func(pageSize int, pageToken string) (results []*monitoringpb.TimeSeries, nextPageToken string, err error)
530}
531
532// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
533func (it *TimeSeriesIterator) PageInfo() *iterator.PageInfo {
534	return it.pageInfo
535}
536
537// Next returns the next result. Its second return value is iterator.Done if there are no more
538// results. Once Next returns Done, all subsequent calls will return Done.
539func (it *TimeSeriesIterator) Next() (*monitoringpb.TimeSeries, error) {
540	var item *monitoringpb.TimeSeries
541	if err := it.nextFunc(); err != nil {
542		return item, err
543	}
544	item = it.items[0]
545	it.items = it.items[1:]
546	return item, nil
547}
548
549func (it *TimeSeriesIterator) bufLen() int {
550	return len(it.items)
551}
552
553func (it *TimeSeriesIterator) takeBuf() interface{} {
554	b := it.items
555	it.items = nil
556	return b
557}
558