github.com/netdata/go.d.plugin@v0.58.1/modules/weblog/parser_test.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package weblog
     4  
     5  import (
     6  	"fmt"
     7  	"testing"
     8  
     9  	"github.com/netdata/go.d.plugin/pkg/logs"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  func TestWebLog_guessParser(t *testing.T) {
    16  	type test = struct {
    17  		name           string
    18  		inputs         []string
    19  		wantParserType string
    20  		wantErr        bool
    21  	}
    22  	tests := []test{
    23  		{
    24  			name:           "guessed csv",
    25  			wantParserType: logs.TypeCSV,
    26  			inputs: []string{
    27  				`test.example.com:80 88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674 "-" "-" 8674 0.123 0.123,0.321`,
    28  				`test.example.com:80 88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674 "-" "-" 8674 0.123`,
    29  				`test.example.com:80 88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674 8674 0.123 0.123,0.321`,
    30  				`test.example.com:80 88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674 8674 0.123`,
    31  				`test.example.com:80 88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674`,
    32  				`88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674 "-" "-" 8674 0.123 0.123,0.321`,
    33  				`88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674 "-" "-" 8674 0.123`,
    34  				`88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674 8674 0.123 0.123,0.321`,
    35  				`88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674 8674 0.123`,
    36  				`88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674`,
    37  			},
    38  		},
    39  		{
    40  			name:           "guessed ltsv",
    41  			wantParserType: logs.TypeLTSV,
    42  			inputs: []string{
    43  				`field1:test.example.com:80 field2:88.191.254.20 field3:"GET / HTTP/1.0" 200 8674 field4:8674 field5:0.123`,
    44  			},
    45  		},
    46  		{
    47  			name:           "guessed json",
    48  			wantParserType: logs.TypeJSON,
    49  			inputs: []string{
    50  				`{}`,
    51  				` {}`,
    52  				` {} `,
    53  				`{"host": "example.com"}`,
    54  				`{"host": "example.com","time": "2020-08-04T20:23:27+03:00", "upstream_response_time": "0.776", "remote_addr": "1.2.3.4"}`,
    55  				` {"host": "example.com","time": "2020-08-04T20:23:27+03:00", "upstream_response_time": "0.776", "remote_addr": "1.2.3.4"}	`,
    56  			},
    57  		},
    58  		{
    59  			name:    "unknown",
    60  			wantErr: true,
    61  			inputs: []string{
    62  				`test.example.com 80 88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674`,
    63  				`test.example.com 88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674`,
    64  			},
    65  		},
    66  	}
    67  
    68  	weblog := prepareWebLog()
    69  
    70  	for _, tc := range tests {
    71  		for i, input := range tc.inputs {
    72  			name := fmt.Sprintf("name=%s,input_num=%d", tc.name, i+1)
    73  
    74  			t.Run(name, func(t *testing.T) {
    75  				p, err := weblog.newParser([]byte(input))
    76  
    77  				if tc.wantErr {
    78  					assert.Error(t, err)
    79  				} else {
    80  					require.NoError(t, err)
    81  					switch tc.wantParserType {
    82  					default:
    83  						t.Errorf("unknown parser type: %s", tc.wantParserType)
    84  					case logs.TypeLTSV:
    85  						assert.IsType(t, (*logs.LTSVParser)(nil), p)
    86  					case logs.TypeCSV:
    87  						require.IsType(t, (*logs.CSVParser)(nil), p)
    88  					case logs.TypeJSON:
    89  						require.IsType(t, (*logs.JSONParser)(nil), p)
    90  					}
    91  				}
    92  			})
    93  		}
    94  	}
    95  }
    96  
    97  func TestWebLog_guessCSVParser(t *testing.T) {
    98  	type test = struct {
    99  		name          string
   100  		inputs        []string
   101  		wantCSVFormat string
   102  		wantErr       bool
   103  	}
   104  	tests := []test{
   105  		{
   106  			name:          "guessed vhost custom4",
   107  			wantCSVFormat: csvVhostCustom4,
   108  			inputs: []string{
   109  				`test.example.com:80 88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674 "-" "-" 8674 0.123 0.123,0.321`,
   110  			},
   111  		},
   112  		{
   113  			name:          "guessed vhost custom3",
   114  			wantCSVFormat: csvVhostCustom3,
   115  			inputs: []string{
   116  				`test.example.com:80 88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674 "-" "-" 8674 0.123`,
   117  			},
   118  		},
   119  		{
   120  			name:          "guessed vhost custom2",
   121  			wantCSVFormat: csvVhostCustom2,
   122  			inputs: []string{
   123  				`test.example.com:80 88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674 8674 0.123 0.123,0.321`,
   124  			},
   125  		},
   126  		{
   127  			name:          "guessed vhost custom1",
   128  			wantCSVFormat: csvVhostCustom1,
   129  			inputs: []string{
   130  				`test.example.com:80 88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674 8674 0.123`,
   131  			},
   132  		},
   133  		{
   134  			name:          "guessed vhost common",
   135  			wantCSVFormat: csvVhostCommon,
   136  			inputs: []string{
   137  				`test.example.com:80 88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674`,
   138  			},
   139  		},
   140  		{
   141  			name:          "guessed custom4",
   142  			wantCSVFormat: csvCustom4,
   143  			inputs: []string{
   144  				`88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674 "-" "-" 8674 0.123 0.123,0.321`,
   145  			},
   146  		},
   147  		{
   148  			name:          "guessed custom3",
   149  			wantCSVFormat: csvCustom3,
   150  			inputs: []string{
   151  				`88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674 "-" "-" 8674 0.123`,
   152  			},
   153  		},
   154  		{
   155  			name:          "guessed custom2",
   156  			wantCSVFormat: csvCustom2,
   157  			inputs: []string{
   158  				`88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674 8674 0.123 0.123,0.321`,
   159  			},
   160  		},
   161  		{
   162  			name:          "guessed custom1",
   163  			wantCSVFormat: csvCustom1,
   164  			inputs: []string{
   165  				`88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674 8674 0.123`,
   166  			},
   167  		},
   168  		{
   169  			name:          "guessed common",
   170  			wantCSVFormat: csvCommon,
   171  			inputs: []string{
   172  				`88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674`,
   173  			},
   174  		},
   175  		{
   176  			name:    "unknown",
   177  			wantErr: true,
   178  			inputs: []string{
   179  				`test.example.com 80 88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674`,
   180  				`test.example.com 88.191.254.20 - - [22/Mar/2009:09:30:31 +0100] "GET / HTTP/1.0" 200 8674`,
   181  			},
   182  		},
   183  	}
   184  
   185  	weblog := prepareWebLog()
   186  
   187  	for i, tc := range tests {
   188  		for _, input := range tc.inputs {
   189  			name := fmt.Sprintf("name=%s,input_num=%d", tc.name, i+1)
   190  
   191  			t.Run(name, func(t *testing.T) {
   192  				p, err := weblog.guessCSVParser([]byte(input))
   193  
   194  				if tc.wantErr {
   195  					assert.Error(t, err)
   196  				} else {
   197  					require.NoError(t, err)
   198  					assert.Equal(t, cleanCSVFormat(tc.wantCSVFormat), p.(*logs.CSVParser).Config.Format)
   199  				}
   200  			})
   201  		}
   202  	}
   203  }
   204  
   205  func prepareWebLog() *WebLog {
   206  	cfg := logs.ParserConfig{
   207  		LogType: typeAuto,
   208  		CSV: logs.CSVConfig{
   209  			Delimiter:  " ",
   210  			CheckField: checkCSVFormatField,
   211  		},
   212  		LTSV: logs.LTSVConfig{
   213  			FieldDelimiter: "\t",
   214  			ValueDelimiter: ":",
   215  		},
   216  	}
   217  
   218  	return &WebLog{
   219  		Config: Config{
   220  			GroupRespCodes: false,
   221  			Parser:         cfg,
   222  		},
   223  	}
   224  }