Fix code review comments and rename solution
This commit is contained in:
Родитель
64e0a76d88
Коммит
3086686fce
|
@ -1,7 +1,7 @@
|
||||||
PATH
|
PATH
|
||||||
remote: .
|
remote: .
|
||||||
specs:
|
specs:
|
||||||
fluent-plugin-azureactivitylog (0.0.1)
|
fluent-plugin-azuremonitorlog (0.0.2)
|
||||||
azure_mgmt_monitor (~> 0.11.0)
|
azure_mgmt_monitor (~> 0.11.0)
|
||||||
fluentd (>= 0.10.30)
|
fluentd (>= 0.10.30)
|
||||||
|
|
||||||
|
@ -68,9 +68,9 @@ PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
fluent-plugin-azureactivitylog!
|
fluent-plugin-azuremonitorlog!
|
||||||
rake (>= 0.9.2)
|
rake (>= 0.9.2)
|
||||||
test-unit (>= 3.1.0)
|
test-unit (>= 3.1.0)
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.11.2
|
1.15.4
|
||||||
|
|
31
README.md
31
README.md
|
@ -1,37 +1,46 @@
|
||||||
# fluent-plugin-azureactivitylog, a plugin for [Fluentd](http://fluentd.org)
|
# fluent-plugin-azuremonitorlog, a plugin for [Fluentd](http://fluentd.org)
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
***Azure Activity log*** input plugin.
|
***Azure Monitor log*** input plugin.
|
||||||
|
|
||||||
This plugin gets the activity logs from Azure Monitor API to fluentd.
|
This plugin gets the monitor activity logs from Azure Monitor API to fluentd.
|
||||||
|
|
||||||
Installation
|
## Installation
|
||||||
|
|
||||||
$ gem install fluent-plugin-azureactivitylog
|
Install from RubyGems:
|
||||||
|
```
|
||||||
|
$ gem install fluent-plugin-azuremonitorlog
|
||||||
|
```
|
||||||
|
|
||||||
|
To use this plugin, you need to have Azure Service Principal.<br/>
|
||||||
|
Create an Azure Service Principal through [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?toc=%2fazure%2fazure-resource-manager%2ftoc.json) or [Azure portal](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal).
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
```config
|
```config
|
||||||
<source>
|
<source>
|
||||||
@type azureactivitylog
|
@type azuremonitorlog
|
||||||
tag azureactivitylog
|
tag azuremonitorlog
|
||||||
tenant_id [Azure_Tenant_ID]
|
tenant_id [Azure_Tenant_ID]
|
||||||
subscription_id [Azure_Subscription_Id]
|
subscription_id [Azure_Subscription_Id]
|
||||||
client_id [Azure_Client_Id]
|
client_id [Azure_Client_Id]
|
||||||
client_secret [Azure_Client_Secret]
|
client_secret [Azure_Client_Secret]
|
||||||
|
|
||||||
select_filter [selected fields to query]
|
select [selected fields to query]
|
||||||
event_channels [event channles] (default: Admin, Operation)
|
filter [filter the query query] (default: eventChannels eq 'Admin, Operation')
|
||||||
interval [interval in seconds] (default: 300)
|
interval [interval in seconds] (default: 300)
|
||||||
|
api_version [api version] (default: 2015-04-01)
|
||||||
</source>
|
</source>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Documentation for select and filter can be found [here](https://docs.microsoft.com/en-us/rest/api/monitor/ActivityLogs/List#activitylogs_list_uri_parameters)
|
||||||
|
|
||||||
### Example for source config
|
### Example for source config
|
||||||
|
|
||||||
```config
|
```config
|
||||||
<source>
|
<source>
|
||||||
@type azureactivitylog
|
@type azuremonitorlog
|
||||||
tag azureactivitylog
|
tag azuremonitorlog
|
||||||
tenant_id [Azure_Tenant_ID]
|
tenant_id [Azure_Tenant_ID]
|
||||||
subscription_id [Azure_Subscription_Id]
|
subscription_id [Azure_Subscription_Id]
|
||||||
client_id [Azure_Client_Id]
|
client_id [Azure_Client_Id]
|
||||||
|
|
|
@ -3,12 +3,12 @@ lib = File.expand_path('../lib', __FILE__)
|
||||||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
||||||
|
|
||||||
Gem::Specification.new do |gem|
|
Gem::Specification.new do |gem|
|
||||||
gem.name = "fluent-plugin-azureactivitylog"
|
gem.name = "fluent-plugin-azuremonitorlog"
|
||||||
gem.version = "0.0.1"
|
gem.version = "0.0.1"
|
||||||
gem.authors = ["Ilana Kantorov"]
|
gem.authors = ["Ilana Kantorov"]
|
||||||
gem.email = ["ilanak@microsoft.com"]
|
gem.email = ["ilanak@microsoft.com"]
|
||||||
gem.description = %q{Input plugin for Azure Activity logs.}
|
gem.description = %q{Input plugin for Azure Monitor Activity logs.}
|
||||||
gem.homepage = "https://github.com/..."
|
gem.homepage = "https://github.com/Ilanak/fluent-plugin-azureamonitorlog"
|
||||||
gem.summary = gem.description
|
gem.summary = gem.description
|
||||||
gem.files = `git ls-files`.split($\)
|
gem.files = `git ls-files`.split($\)
|
||||||
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
|
@ -2,8 +2,8 @@ require 'fluent/input'
|
||||||
require 'azure_mgmt_monitor'
|
require 'azure_mgmt_monitor'
|
||||||
require 'uri'
|
require 'uri'
|
||||||
|
|
||||||
class Fluent::AzureActivityLogInput < Fluent::Input
|
class Fluent::AzureMonitorLogInput < Fluent::Input
|
||||||
Fluent::Plugin.register_input("azureactivitylog", self)
|
Fluent::Plugin.register_input("azuremonitorlog", self)
|
||||||
|
|
||||||
# To support log_level option implemented by Fluentd v0.10.43
|
# To support log_level option implemented by Fluentd v0.10.43
|
||||||
unless method_defined?(:log)
|
unless method_defined?(:log)
|
||||||
|
@ -21,10 +21,10 @@ class Fluent::AzureActivityLogInput < Fluent::Input
|
||||||
config_param :client_id, :string, :default => nil
|
config_param :client_id, :string, :default => nil
|
||||||
config_param :client_secret, :string, :default => nil, :secret => true
|
config_param :client_secret, :string, :default => nil, :secret => true
|
||||||
|
|
||||||
config_param :select_filter, :string, :default => nil
|
config_param :select, :string, :default => nil
|
||||||
config_param :event_channels, :string, :default => "Admin, Operation"
|
config_param :filter, :string, :default => "eventChannels eq 'Admin, Operation'"
|
||||||
config_param :interval, :integer, :default => 300
|
config_param :interval, :integer,:default => 300
|
||||||
|
config_param :api_version, :string, :default => '2015-04-01'
|
||||||
def initialize
|
def initialize
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
@ -49,11 +49,29 @@ class Fluent::AzureActivityLogInput < Fluent::Input
|
||||||
@watcher.join
|
@watcher.join
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_query_options(filter, custom_headers)
|
||||||
|
fail ArgumentError, 'path is nil' if @client.subscription_id.nil?
|
||||||
|
|
||||||
|
request_headers = {}
|
||||||
|
|
||||||
|
# Set Headers
|
||||||
|
request_headers['x-ms-client-request-id'] = SecureRandom.uuid
|
||||||
|
request_headers['accept-language'] = @client.accept_language unless @client.accept_language.nil?
|
||||||
|
|
||||||
|
{
|
||||||
|
middlewares: [[MsRest::RetryPolicyMiddleware, times: 3, retry: 0.02], [:cookie_jar]],
|
||||||
|
path_params: {'subscriptionId' => @client.subscription_id},
|
||||||
|
query_params: {'api-version' => @api_version, '$filter' => filter, '$select' => @select},
|
||||||
|
headers: request_headers.merge(custom_headers || {}),
|
||||||
|
base_url: @client.base_url
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def watch
|
def watch
|
||||||
while true
|
while true
|
||||||
log.debug "azure activitylog: watch thread starting"
|
log.debug "azure monitorlog: watch thread starting"
|
||||||
output
|
output
|
||||||
sleep @interval
|
sleep @interval
|
||||||
end
|
end
|
||||||
|
@ -66,40 +84,25 @@ class Fluent::AzureActivityLogInput < Fluent::Input
|
||||||
log.debug "start time: #{start_time}, end time: #{end_time}"
|
log.debug "start time: #{start_time}, end time: #{end_time}"
|
||||||
filter = "eventTimestamp ge '#{start_time}' and eventTimestamp le '#{end_time}'"
|
filter = "eventTimestamp ge '#{start_time}' and eventTimestamp le '#{end_time}'"
|
||||||
|
|
||||||
if !@event_channels.empty?
|
if !@filter.empty?
|
||||||
filter += " and eventChannels eq '#{@event_channels}'"
|
filter += " and #{@filter}"
|
||||||
end
|
end
|
||||||
|
|
||||||
activity_logs_promise = get_activity_log_async(filter)
|
monitor_logs_promise = get_monitor_log_async(filter)
|
||||||
activity_logs = activity_logs_promise.value!
|
monitor_logs = monitor_logs_promise.value!
|
||||||
|
|
||||||
if activity_logs.body.values[0].any?
|
if !monitor_logs.body['value'].nil? and monitor_logs.body['value'].any?
|
||||||
activity_logs.body.values[0].each {|val|
|
monitor_logs.body['value'].each {|val|
|
||||||
router.emit(@tag, Time.now.to_i, val.to_json)
|
router.emit(@tag, Time.now.to_i, val)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
log.debug "empty"
|
log.debug "empty"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_activity_log_async(filter = nil, custom_headers = nil)
|
def get_monitor_log_async(filter = nil, custom_headers = nil)
|
||||||
fail ArgumentError, 'path is nil' if @client.subscription_id.nil?
|
options = set_query_options(filter, custom_headers)
|
||||||
api_version = '2015-04-01'
|
|
||||||
|
|
||||||
request_headers = {}
|
|
||||||
|
|
||||||
# Set Headers
|
|
||||||
request_headers['x-ms-client-request-id'] = SecureRandom.uuid
|
|
||||||
request_headers['accept-language'] = @client.accept_language unless @client.accept_language.nil?
|
|
||||||
path_template = '/subscriptions/{subscriptionId}/providers/microsoft.insights/eventtypes/management/values'
|
path_template = '/subscriptions/{subscriptionId}/providers/microsoft.insights/eventtypes/management/values'
|
||||||
|
|
||||||
options = {
|
|
||||||
middlewares: [[MsRest::RetryPolicyMiddleware, times: 3, retry: 0.02], [:cookie_jar]],
|
|
||||||
path_params: {'subscriptionId' => @client.subscription_id},
|
|
||||||
query_params: {'api-version' => api_version, '$filter' => filter, '$select' => @select_filter},
|
|
||||||
headers: request_headers.merge(custom_headers || {}),
|
|
||||||
base_url: @client.base_url
|
|
||||||
}
|
|
||||||
promise = @client.make_request_async(:get, path_template, options)
|
promise = @client.make_request_async(:get, path_template, options)
|
||||||
|
|
||||||
promise = promise.then do |result|
|
promise = promise.then do |result|
|
||||||
|
@ -108,7 +111,7 @@ class Fluent::AzureActivityLogInput < Fluent::Input
|
||||||
response_content = http_response.body
|
response_content = http_response.body
|
||||||
unless status_code == 200
|
unless status_code == 200
|
||||||
error_model = JSON.load(response_content)
|
error_model = JSON.load(response_content)
|
||||||
fail MsRestAzure::AzureOperationError.new(result.request, http_response, error_model)
|
log.error(error_model['error']['message'])
|
||||||
end
|
end
|
||||||
|
|
||||||
result.request_id = http_response['x-ms-request-id'] unless http_response['x-ms-request-id'].nil?
|
result.request_id = http_response['x-ms-request-id'] unless http_response['x-ms-request-id'].nil?
|
||||||
|
@ -117,7 +120,7 @@ class Fluent::AzureActivityLogInput < Fluent::Input
|
||||||
begin
|
begin
|
||||||
result.body = response_content.to_s.empty? ? nil : JSON.load(response_content)
|
result.body = response_content.to_s.empty? ? nil : JSON.load(response_content)
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
fail MsRest::DeserializationError.new('Error occurred in parsing the response', e.message, e.backtrace, result)
|
log.error("Error occurred in parsing the response")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,7 +24,7 @@ unless ENV.has_key?("VERBOSE")
|
||||||
$log = nulllogger
|
$log = nulllogger
|
||||||
end
|
end
|
||||||
|
|
||||||
require "fluent/plugin/in_azureactivitylog"
|
require "fluent/plugin/in_azuremonitorlog"
|
||||||
|
|
||||||
class Test::Unit::TestCase
|
class Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
require 'helper'
|
|
||||||
|
|
||||||
class AzureActivityLogInputTest < Test::Unit::TestCase
|
|
||||||
def setup
|
|
||||||
Fluent::Test.setup
|
|
||||||
end
|
|
||||||
|
|
||||||
### for activity log
|
|
||||||
CONFIG_ACTIVITY_LOG = %[
|
|
||||||
tag azureactivitylog
|
|
||||||
tenant_id test_tenant_id
|
|
||||||
subscription_id test_subscription_id
|
|
||||||
client_id test_client_id
|
|
||||||
client_secret test_client_secret
|
|
||||||
select_filter eventName,id,resourceGroupName,resourceProviderName,operationName,status,eventTimestamp,correlationId
|
|
||||||
event_channels test_event_channels
|
|
||||||
interval 300
|
|
||||||
]
|
|
||||||
|
|
||||||
def create_driver_activity_log(conf = CONFIG_ACTIVITY_LOG)
|
|
||||||
Fluent::Test::InputTestDriver.new(Fluent::AzureActivityLogInput).configure(conf)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_configure_activity_log
|
|
||||||
d = create_driver_activity_log
|
|
||||||
assert_equal 'azureactivitylog', d.instance.tag
|
|
||||||
assert_equal 'test_tenant_id', d.instance.tenant_id
|
|
||||||
assert_equal 'test_subscription_id', d.instance.subscription_id
|
|
||||||
assert_equal 'test_client_id', d.instance.client_id
|
|
||||||
assert_equal 'test_client_secret', d.instance.client_secret
|
|
||||||
assert_equal 'eventName,id,resourceGroupName,resourceProviderName,operationName,status,eventTimestamp,correlationId', d.instance.select_filter
|
|
||||||
assert_equal 'test_event_channels', d.instance.event_channels
|
|
||||||
assert_equal 300, d.instance.interval
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
require 'helper'
|
||||||
|
|
||||||
|
class AzureMonitorLogInputTest < Test::Unit::TestCase
|
||||||
|
def setup
|
||||||
|
Fluent::Test.setup
|
||||||
|
end
|
||||||
|
|
||||||
|
### for monitor log
|
||||||
|
CONFIG_MONITOR_LOG = %[
|
||||||
|
tag azuremonitorlog
|
||||||
|
tenant_id test_tenant_id
|
||||||
|
subscription_id test_subscription_id
|
||||||
|
client_id test_client_id
|
||||||
|
client_secret test_client_secret
|
||||||
|
select eventName,id,resourceGroupName,resourceProviderName,operationName,status,eventTimestamp,correlationId
|
||||||
|
filter eventChannels eq 'Admin, Operation'
|
||||||
|
interval 300
|
||||||
|
api_version 2015-04-01
|
||||||
|
]
|
||||||
|
|
||||||
|
def create_driver_monitor_log(conf = CONFIG_MONITOR_LOG)
|
||||||
|
Fluent::Test::InputTestDriver.new(Fluent::AzureMonitorLogInput).configure(conf)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_configure_monitor_log
|
||||||
|
d = create_driver_monitor_log
|
||||||
|
assert_equal 'azuremonitorlog', d.instance.tag
|
||||||
|
assert_equal 'test_tenant_id', d.instance.tenant_id
|
||||||
|
assert_equal 'test_subscription_id', d.instance.subscription_id
|
||||||
|
assert_equal 'test_client_id', d.instance.client_id
|
||||||
|
assert_equal 'test_client_secret', d.instance.client_secret
|
||||||
|
assert_equal 'eventName,id,resourceGroupName,resourceProviderName,operationName,status,eventTimestamp,correlationId', d.instance.select
|
||||||
|
assert_equal 'eventChannels eq \'Admin, Operation\'', d.instance.filter
|
||||||
|
assert_equal 300, d.instance.interval
|
||||||
|
assert_equal '2015-04-01', d.instance.api_version
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_set_query_options
|
||||||
|
d = create_driver_monitor_log
|
||||||
|
query_options = d.instance.set_query_options(d.instance.filter, {})
|
||||||
|
assert_equal '2015-04-01', query_options[:query_params]['api-version']
|
||||||
|
assert_equal 'eventChannels eq \'Admin, Operation\'', query_options[:query_params]['$filter']
|
||||||
|
assert_equal 'eventName,id,resourceGroupName,resourceProviderName,operationName,status,eventTimestamp,correlationId', query_options[:query_params]['$select']
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Загрузка…
Ссылка в новой задаче