Use Logstash for data streaming
MaxCompute can ingest logs collected by open-source Logstash. Use the logstash-output-maxcompute output plugin to upload data to MaxCompute through the Streaming Tunnel.
Prerequisites
Complete the following prerequisites:
You have installed Logstash for log collection. For more information, see Getting Started with Logstash.
You have created a MaxCompute project.
Background information
Logstash is an open-source, server-side data processing pipeline that can ingest and transform data from multiple data sources simultaneously, and then send it to a destination data store. Use the Logstash logstash-output-maxcompute output plugin to upload log data to MaxCompute using the Streaming Tunnel.
The logstash-output-maxcompute plugin is based on Logstash v7.8.0 and can be used as an output. The plugin provides the following features:
It uses the Streaming Tunnel to prevent concurrency issues and the creation of small files common when importing data with the Batch Data Tunnel.
The plugin can generate partition fields based on parsed log fields and automatically create partitions that do not exist.
The logstash-output-maxcompute plugin is suitable for the following use cases:
The log format of your application is supported by a Logstash input plugin or is easy to parse, such as NGINX logs.
You want to automatically create partitions and import data based on log content.
The logstash-output-maxcompute plugin supports the following data types: STRING, BIGINT, DOUBLE, DATETIME, and BOOLEAN.
The format of DATETIME fields in logs is automatically inferred using the
ruby Time.parsefunction.If a boolean field in a log satisfies the
.to_string().lowercase() == "true"condition, it evaluates to true; otherwise, it evaluates to false.
This topic uses NGINX logs as an example to explain how to configure and use the plugin.
Step 1: Download and install the plugin
You can download a Logstash instance with the logstash-output-maxcompute plugin pre-installed from this Logstash instance download link. If you use this method, you can skip the installation and proceed to the next step. To install the plugin manually:
Download the
logstash-output-maxcomputeplugin from the logstash-output-maxcompute plugin download link and place it in the%logstash%root directory of Logstash.In the
%logstash%root directory, open theGemfileconfiguration file and replacesource "https://rubygems.org"withsource 'https://gems.ruby-china.com'.On a Windows system, open the command-line interface (CLI), navigate to the
%logstash%root directory, and run the following command to install thelogstash-output-maxcomputeoutput plugin.bin\logstash-plugin install logstash-output-maxcompute-1.1.0.gemThe
Installation successfulmessage confirms the installation.D:\logstash> D:\logstash>bin\logstash-plugin install logstash-output-maxcompute-1.1.0.gem Validating logstash-output-maxcompute-1.1.0.gem Installing logstash-output-maxcompute Installation successfulOptional: Run the following command to verify the installation.
bin\logstash-plugin list maxcomputeNoteOn a Linux system, run the command
bin/logstash-plugin list maxcompute.A successful installation returns
logstash-output-maxcompute. If the installation fails, see RubyGems for solutions.D:\logstash>bin\logstash-plugin list maxcompute logstash-output-maxcompute
Step 2: Create a destination table
Use the MaxCompute client or another SQL-compatible tool to run the following command to create a destination table, such as logstash_test_groknginx, in your MaxCompute project. Log data will be imported into this table based on date partitions.
create table logstash_test_groknginx(
clientip string,
remote_user string,
time datetime,
verb string,
uri string,
version string,
response string,
body_bytes bigint,
referrer string,
agent string
) partitioned by (pt string);Step 3: Create a pipeline configuration file
In the %logstash% root directory of Logstash, create a configuration file named pipeline.conf and add the following content:
input { stdin {} }
filter {
grok {
match => {
"message" => "%{IP:clientip} - (%{USER:remote_user}|-) \[%{HTTPDATE:httptimestamp}\] \"%{WORD:verb} %{NOTSPACE:request} HTTP/%{NUMBER:httpversion}\" %{NUMBER:response} %{NUMBER:body_bytes} %{QS:referrer} %{QS:agent}"
}
}
date {
match => [ "httptimestamp" , "dd/MMM/yyyy:HH:mm:ss Z" ]
target => "timestamp"
}
}
output {
maxctunnel {
aliyun_access_id => "<your_accesskey_id>"
aliyun_access_key => "<your_accesskey_secret>"
aliyun_mc_endpoint => "<your_project_endpoint>"
project => "<your_project_name>"
table => "<table_name>"
partition => "pt=$<timestamp.strftime('%F')>"
value_fields => ["clientip", "remote_user", "timestamp", "verb", "request", "httpversion", "response", "body_bytes", "referrer", "agent"]
}
}Parameter | Description |
your_accesskey_id | An AccessKey ID with permissions to access the destination MaxCompute project. |
your_accesskey_secret | The AccessKey Secret that corresponds to the AccessKey ID. |
your_project_endpoint | The region endpoint for your MaxCompute project. For more information about endpoints, see Endpoints and headers. |
your_project_name | The name of the destination MaxCompute project. |
table_name | The name of the destination table that you created in Step 2. |
partition | Specifies how the plugin generates partition information from log fields. If the destination table has multiple partition levels, you must specify values for all partition levels. The following formats are supported:
|
partition_time_format | Optional. Specifies the source format string for a string-type datetime field when it is referenced in the partition information. In this example, the time field Even if you do not use the If you do not use the
|
value_fields | Specifies the log fields that map to the fields in the destination table. The order of the log fields must match the order of the table fields. The fields in the destination table are ordered as |
aliyun_mc_tunnel_endpoint | Optional. You can use this parameter to specify a Tunnel endpoint, which overrides the automatic routing mechanism. |
retry_time | The number of retries after a failed write operation. Default value: 3. |
retry_interval | The minimum retry interval, in seconds. Default value: 1. |
batch_size | The maximum number of log entries to process in a single batch. Default value: 100. |
batch_timeout | The timeout period for writing data to MaxCompute, in seconds. Default value: 5. |
In this configuration file, the specified log input is standard input(input { stdin {} }). In a real-world scenario, you can use the Logstash File input plugin to automatically read NGINX logs from a local hard drive. For more information, see the Logstash documentation.
Step 4: Run and test
On a Windows system, open the CLI, navigate to the
%logstash%root directory, and run the following command to start Logstash.bin\logstash -f pipeline.confAfter the command is successfully executed, the returned message
Successfully started Logstash API endpointindicates that Logstash has started successfully and the API port is 9600.D:\logstash>bin\logstash -f pipeline.conf Sending Logstash logs to D:/logstash/logs which is now configured via log4j2.properties [2021-01-27T17:46:34,347][WARN ][logstash.config.source.multilocal] Ignoring the 'pipelines.yml' file because modules or command line options are specified [2021-01-27T17:46:34,679][INFO ][logstash.runner ] Starting Logstash {"logstash.version"=>"7.8.0", "jruby.version"=>"jruby 9.2.11.1 (2.5.7) 2020-03-25 b1f55b1a40 Java HotSpot(TM) 64-Bit Server VM 25.131-b11 on 1.8.0_131-b11 +indy +jit [mswin32-x86_64]"} [2021-01-27T17:46:40,972][INFO ][org.reflections.Reflections] Reflections took 241 ms to scan 1 urls, producing 21 keys and 41 values [2021-01-27T17:46:44,030][INFO ][logstash.javapipeline ][main] Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>4, "pipeline.batch.size"=>125, "pipeline.batch.delay"=>50, "pipeline.max_inflight"=>500, "pipeline.sources"=>["D:/logstash/pipeline.conf"], :thread=>"#<Thread:0x37536680 run>"} [2021-01-27T17:46:46,947][INFO ][logstash.javapipeline ][main] Pipeline started {"pipeline.id"=>"main"} The stdin plugin is now waiting for input: [2021-01-27T17:46:47,174][INFO ][logstash.agent ] Pipelines running {:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]} [2021-01-27T17:46:48,185][INFO ][logstash.agent ] Successfully started Logstash API endpoint {:port=>9600}In the CLI, paste the following sample logs and press Enter.
1.1.1.1 - - [09/Jul/2020:01:02:03 +0800] "GET /masked/request/uri/1 HTTP/1.1" 200 143363 "-" "Masked UserAgent" - 0.095 0.071 2.2.2.2 - - [09/Jul/2020:04:05:06 +0800] "GET /masked/request/uri/2 HTTP/1.1" 200 143388 "-" "Masked UserAgent 2" - 0.095 0.072After a successful execution, the terminal returns
write .. records on partition .. completed. This indicates that Logstash has started successfully and written the Nginx logs to the MaxCompute table.[2021-01-27T18:00:47,196][INFO ][logstash.javapipeline ][main] Pipeline started {"pipeline.id"=>"main"} The stdin plugin is now waiting for input: [2021-01-27T18:00:47,388][INFO ][logstash.agent ] Pipelines running {:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]} [2021-01-27T18:00:48,323][INFO ][logstash.agent ] Successfully started Logstash API endpoint {:port=>9600} 1.1.1.1 - - [09/Jul/2020:01:02:03 +0800] "GET /masked/request/uri/1 HTTP/1.1" 200 143363 "-" "Masked UserAgent" - 0.095 0.071 2.2.2.2 - - [09/Jul/2020:04:05:06 +0800] "GET /masked/request/uri/2 HTTP/1.1" 200 143388 "-" "Masked UserAgent 2" - 0.095 0.072 [2021-01-27T18:00:56,757][INFO ][logstash.outputs.maxtunnel][main][691d6be762308ae955883c0cf0719e0a71754924lbe162d0d309f79690c9e2448] write 1 records on table doc_test_dev.logstash_test_groknginx partition pt='2020-07-08' completed. TraceId: 20210127180041e230f60b00012894 [2021-01-27T18:01:00,093][INFO ][logstash.outputs.maxtunnel][main] write 1 records on table doc_test_dev.logstash_test_groknginx partition pt='2020-07-08' completed. TraceId: 20210127180044b31f60b0001369eUse the MaxCompute client or another SQL-compatible tool to run the following command to query the data and verify the result.
set odps.sql.allow.fullscan=true; select * from logstash_test_groknginx;The following output is returned:
+--------+------------+-------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+ | clientip | remote_user | time | verb | uri | version | response | body_bytes | referrer | agent | pt | +------------+-------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+ | 1.1.1.1 | - | 2020-07-09 01:02:03 | GET | /masked/request/uri/1 | 1.1 | 200 | 0 | "-" | "Masked UserAgent" | 2020-07-08 | | 2.2.2.2 | - | 2020-07-09 04:05:06 | GET | /masked/request/uri/2 | 1.1 | 200 | 0 | "-" | "Masked UserAgent 2" | 2020-07-08 | +------------+-------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+ 2 records (at most 10000 supported) fetched by instance tunnel.