| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| using System; |
| using System.Diagnostics.Metrics; |
| using System.Net.Http; |
| using NLog; |
| using OpenTelemetry; |
| using OpenTelemetry.Exporter; |
| using OpenTelemetry.Metrics; |
| using OpenTelemetry.Resources; |
| |
| namespace Org.Apache.Rocketmq |
| { |
| public class ClientMeterManager |
| { |
| private static readonly Logger Logger = MqLogManager.Instance.GetCurrentClassLogger(); |
| private const string MeterName = "Apache.RocketMQ.Client"; |
| private const string Version = "1.0"; |
| private const int MetricExportPeriodInMillis = 60 * 1000; |
| |
| private readonly Client _client; |
| private volatile ClientMeter _clientMeter; |
| private readonly HttpClient _httpClient; |
| internal readonly Meter Meter; |
| |
| public ClientMeterManager(Client client) |
| { |
| _client = client; |
| var httpDelegatingHandler = new MetricHttpDelegatingHandler(client); |
| _httpClient = new HttpClient(httpDelegatingHandler); |
| _clientMeter = ClientMeter.DisabledInstance(_client.GetClientId()); |
| Meter = new Meter(MeterName, Version); |
| } |
| |
| public void Shutdown() |
| { |
| _clientMeter.Shutdown(); |
| } |
| |
| public void Reset(Metric metric) |
| { |
| lock (this) |
| { |
| var clientId = _client.GetClientId(); |
| if (_clientMeter.Satisfy(metric)) |
| { |
| Logger.Info( |
| $"Metric settings is satisfied by the current message meter, metric={metric}, clientId={clientId}"); |
| return; |
| } |
| |
| if (!metric.On) |
| { |
| Logger.Info($"Metric is off, clientId={clientId}"); |
| _clientMeter.Shutdown(); |
| _clientMeter = ClientMeter.DisabledInstance(clientId); |
| return; |
| } |
| |
| var meterProvider = Sdk.CreateMeterProviderBuilder() |
| .SetResourceBuilder(ResourceBuilder.CreateEmpty()) |
| .AddMeter(MeterName) |
| .AddOtlpExporter(delegate (OtlpExporterOptions options, MetricReaderOptions readerOptions) |
| { |
| options.Protocol = OtlpExportProtocol.Grpc; |
| options.Endpoint = new Uri(metric.Endpoints.GrpcTarget(_client.GetClientConfig().SslEnabled)); |
| options.TimeoutMilliseconds = (int)_client.GetClientConfig().RequestTimeout.TotalMilliseconds; |
| options.HttpClientFactory = () => _httpClient; |
| readerOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = |
| MetricExportPeriodInMillis; |
| }) |
| .AddView(instrument => |
| { |
| if (MeterName != instrument.Meter.Name) |
| { |
| return null; |
| } |
| |
| return instrument.Name switch |
| { |
| MetricConstant.SendCostTimeMetricName => MetricConstant.Instance.SendCostTimeBucket, |
| MetricConstant.DeliveryLatencyMetricName => MetricConstant.Instance.DeliveryLatencyBucket, |
| MetricConstant.AwaitTimeMetricName => MetricConstant.Instance.AwaitTimeBucket, |
| MetricConstant.ProcessTimeMetricName => MetricConstant.Instance.ProcessTimeBucket, |
| _ => null |
| }; |
| }) |
| .Build(); |
| |
| var exist = _clientMeter; |
| _clientMeter = new ClientMeter(metric.Endpoints, meterProvider, clientId); |
| exist.Shutdown(); |
| Logger.Info($"Metric is on, endpoints={metric.Endpoints}, clientId={clientId}"); |
| } |
| } |
| |
| public bool IsEnabled() |
| { |
| return _clientMeter.Enabled; |
| } |
| } |
| } |