├── config ├── README.md ├── LICENCE └── ngx_http_fluentd_module.c /config: -------------------------------------------------------------------------------- 1 | ngx_addon_name=ngx_http_fluentd_module 2 | 3 | if test -n "$ngx_module_link"; then 4 | ngx_module_type=HTTP 5 | ngx_module_name=ngx_http_fluentd_module 6 | ngx_module_srcs="$ngx_addon_dir/ngx_http_fluentd_module.c" 7 | 8 | . auto/module 9 | else 10 | HTTP_MODULES="$HTTP_MODULES ngx_http_fluentd_module" 11 | NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_fluentd_module.c" 12 | fi -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nginx Fluentd Module 2 | 3 | ##Installation 4 | 5 | $ ./configure --add-module=/path/to/nginx-fluentd-module 6 | 7 | ##Synopsis 8 | 9 | server { 10 | 11 | [...] 12 | 13 | log_format fluentd '"ra":"$remote_addr", "uri":"$request_uri", "st":$status, "ref":"$http_referer", "ua":"$http_user_agent","rt":$request_time, "bs":$bytes_sent'; 14 | 15 | fluentd_tag $host; 16 | access_fluentd 127.0.0.1:8000 fluentd; 17 | 18 | [...] 19 | } 20 | 21 | ## Description 22 | 23 | This module send access logs to [fluentd][1] via [fluent-udp-plugin][2] 24 | Log format is important and required because output is in JSON format. 25 | 26 | ## Directives 27 | 28 | fluentd_tag 29 | syntax: *fluentd_tag tag 30 | 31 | default: *fluentd_tag nginx* 32 | 33 | context: *main, server, location* 34 | 35 | description: Set tag for fluentd match directive 36 | 37 | fluentd_collector_max 38 | syntax: *fluentd_collector_max count 39 | 40 | default: 16 41 | 42 | context: *main 43 | 44 | description: Set count of fluentd collector 45 | 46 | access_fluentd 47 | syntax: *access_fluentd address:port log_format | off* 48 | 49 | default: *access_fluentd off* 50 | 51 | context: *main, server, location, if, limit_access* 52 | 53 | description: Enable logging to fluentd 54 | 55 | ## Authors 56 | Yasar Semih Alev *semihalev at gmail dot com* 57 | 58 | 59 | [1]: http://fluentd.org 60 | [2]: https://github.com/parolkar/fluent-plugin-udp 61 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2011-2018 Fluentd Authors 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /ngx_http_fluentd_module.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Yasar Semih Alev 3 | * 4 | */ 5 | 6 | 7 | /* 8 | * NOTE: Some functions copied from nginx-udplog-module. 9 | * Copyright (C) 2010 Valery Kholodkov 10 | * 11 | */ 12 | 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #if defined nginx_version && nginx_version >= 8021 20 | typedef ngx_addr_t ngx_fluentd_addr_t; 21 | #else 22 | typedef ngx_peer_addr_t ngx_fluentd_addr_t; 23 | #endif 24 | 25 | typedef struct ngx_http_log_op_s ngx_http_log_op_t; 26 | 27 | typedef u_char *(*ngx_http_log_op_run_pt) (ngx_http_request_t *r, u_char *buf, 28 | ngx_http_log_op_t *op); 29 | 30 | typedef size_t (*ngx_http_log_op_getlen_pt) (ngx_http_request_t *r, 31 | uintptr_t data); 32 | 33 | 34 | struct ngx_http_log_op_s { 35 | size_t len; 36 | ngx_http_log_op_getlen_pt getlen; 37 | ngx_http_log_op_run_pt run; 38 | uintptr_t data; 39 | }; 40 | 41 | typedef struct { 42 | ngx_str_t name; 43 | #if defined nginx_version && nginx_version >= 7018 44 | ngx_array_t *flushes; 45 | #endif 46 | ngx_array_t *ops; /* array of ngx_http_log_op_t */ 47 | } ngx_http_log_fmt_t; 48 | 49 | typedef struct { 50 | ngx_str_t value; 51 | ngx_array_t *lengths; 52 | ngx_array_t *values; 53 | } ngx_http_log_tag_template_t; 54 | 55 | typedef struct { 56 | ngx_array_t formats; /* array of ngx_http_log_fmt_t */ 57 | ngx_uint_t combined_used; /* unsigned combined_used:1 */ 58 | } ngx_http_log_main_conf_t; 59 | 60 | typedef struct { 61 | ngx_fluentd_addr_t peer_addr; 62 | ngx_resolver_connection_t *udp_connection; 63 | } ngx_udp_endpoint_t; 64 | 65 | typedef struct { 66 | ngx_udp_endpoint_t *endpoint; 67 | ngx_http_log_fmt_t *format; 68 | } ngx_http_fluentd_t; 69 | 70 | typedef struct { 71 | ngx_array_t *endpoints; 72 | ngx_uint_t collector_max; 73 | } ngx_http_fluentd_main_conf_t; 74 | 75 | typedef struct { 76 | ngx_array_t *logs; /* array of ngx_http_fluentd_t */ 77 | unsigned off; 78 | ngx_http_log_tag_template_t *tag; 79 | } ngx_http_fluentd_conf_t; 80 | 81 | ngx_int_t ngx_udp_connect(ngx_resolver_connection_t *uc); 82 | 83 | static void ngx_fluentd_cleanup(void *data); 84 | static ngx_int_t ngx_http_fluentd_send(ngx_udp_endpoint_t *l, u_char *buf, size_t len); 85 | 86 | static void *ngx_http_fluentd_create_main_conf(ngx_conf_t *cf); 87 | static char *ngx_http_fluentd_init_main_conf(ngx_conf_t *cf, void *conf); 88 | static void *ngx_http_fluentd_create_loc_conf(ngx_conf_t *cf); 89 | static char *ngx_http_fluentd_merge_loc_conf(ngx_conf_t *cf, void *parent, 90 | void *child); 91 | 92 | static char *ngx_http_fluentd_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 93 | static char *ngx_http_fluentd_set_tag(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 94 | 95 | static ngx_int_t ngx_http_fluentd_init(ngx_conf_t *cf); 96 | 97 | 98 | static ngx_command_t ngx_http_fluentd_commands[] = { 99 | 100 | { ngx_string("access_fluentd"), 101 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF 102 | |NGX_HTTP_LMT_CONF|NGX_CONF_TAKE123, 103 | ngx_http_fluentd_set_log, 104 | NGX_HTTP_LOC_CONF_OFFSET, 105 | 0, 106 | NULL }, 107 | 108 | { ngx_string("fluentd_collector_max"), 109 | NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, 110 | ngx_conf_set_num_slot, 111 | NGX_HTTP_MAIN_CONF_OFFSET, 112 | offsetof(ngx_http_fluentd_main_conf_t, collector_max), 113 | NULL }, 114 | 115 | { ngx_string("fluentd_tag"), 116 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, 117 | ngx_http_fluentd_set_tag, 118 | NGX_HTTP_LOC_CONF_OFFSET, 119 | offsetof(ngx_http_fluentd_conf_t, tag), 120 | NULL }, 121 | 122 | ngx_null_command 123 | }; 124 | 125 | 126 | static ngx_http_module_t ngx_http_fluentd_module_ctx = { 127 | NULL, /* preconfiguration */ 128 | ngx_http_fluentd_init, /* postconfiguration */ 129 | 130 | ngx_http_fluentd_create_main_conf, /* create main configuration */ 131 | ngx_http_fluentd_init_main_conf, /* init main configuration */ 132 | 133 | NULL, /* create server configuration */ 134 | NULL, /* merge server configuration */ 135 | 136 | ngx_http_fluentd_create_loc_conf, /* create location configration */ 137 | ngx_http_fluentd_merge_loc_conf /* merge location configration */ 138 | }; 139 | 140 | extern ngx_module_t ngx_http_log_module; 141 | 142 | ngx_module_t ngx_http_fluentd_module = { 143 | NGX_MODULE_V1, 144 | &ngx_http_fluentd_module_ctx, /* module context */ 145 | ngx_http_fluentd_commands, /* module directives */ 146 | NGX_HTTP_MODULE, /* module type */ 147 | NULL, /* init master */ 148 | NULL, /* init module */ 149 | NULL, /* init process */ 150 | NULL, /* init thread */ 151 | NULL, /* exit thread */ 152 | NULL, /* exit process */ 153 | NULL, /* exit master */ 154 | NGX_MODULE_V1_PADDING 155 | }; 156 | 157 | ngx_int_t 158 | ngx_http_fluentd_handler(ngx_http_request_t *r) 159 | { 160 | u_char *line, *p; 161 | size_t len; 162 | ngx_uint_t i, l; 163 | ngx_str_t tag; 164 | ngx_http_fluentd_t *log; 165 | ngx_http_log_op_t *op; 166 | ngx_http_fluentd_conf_t *flcf; 167 | 168 | ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 169 | "http fluentd handler"); 170 | 171 | flcf = ngx_http_get_module_loc_conf(r, ngx_http_fluentd_module); 172 | 173 | if(flcf->off || flcf->logs == NULL) { 174 | return NGX_OK; 175 | } 176 | 177 | if(flcf->tag != NULL) 178 | { 179 | if(flcf->tag->lengths == NULL) { 180 | tag = flcf->tag->value; 181 | } 182 | else{ 183 | if (ngx_http_script_run(r, &tag, flcf->tag->lengths->elts, 0, flcf->tag->values->elts) 184 | == NULL) 185 | { 186 | return NGX_ERROR; 187 | } 188 | } 189 | } 190 | else { 191 | ngx_str_set(&tag, "nginx"); 192 | } 193 | 194 | log = flcf->logs->elts; 195 | 196 | for (l = 0; l < flcf->logs->nelts; l++) { 197 | 198 | #if defined nginx_version && nginx_version >= 7018 199 | ngx_http_script_flush_no_cacheable_variables(r, log[l].format->flushes); 200 | #endif 201 | 202 | len = 0; 203 | op = log[l].format->ops->elts; 204 | for (i = 0; i < log[l].format->ops->nelts; i++) { 205 | if (op[i].len == 0) { 206 | len += op[i].getlen(r, op[i].data); 207 | 208 | } else { 209 | len += op[i].len; 210 | } 211 | } 212 | 213 | len += 1 + sizeof("\"tag\":") - 1 + 1 + tag.len + 1 + 1 + 1 + 1; /* '{"tag":"value", }' */ 214 | 215 | #if defined nginx_version && nginx_version >= 7003 216 | line = ngx_pnalloc(r->pool, len); 217 | #else 218 | line = ngx_palloc(r->pool, len); 219 | #endif 220 | if (line == NULL) { 221 | return NGX_ERROR; 222 | } 223 | 224 | /* 225 | * JSON Style message 226 | */ 227 | p = ngx_sprintf(line, "{\"tag\":\"%V\", ", &tag); 228 | 229 | for (i = 0; i < log[l].format->ops->nelts; i++) { 230 | p = op[i].run(r, p, &op[i]); 231 | } 232 | 233 | *p++ = '}'; 234 | 235 | ngx_http_fluentd_send(log[l].endpoint, line, p - line); 236 | } 237 | 238 | return NGX_OK; 239 | } 240 | 241 | static ngx_int_t ngx_fluentd_init_endpoint(ngx_conf_t *cf, ngx_udp_endpoint_t *endpoint) { 242 | ngx_pool_cleanup_t *cln; 243 | ngx_resolver_connection_t *uc; 244 | 245 | cln = ngx_pool_cleanup_add(cf->pool, 0); 246 | if(cln == NULL) { 247 | return NGX_ERROR; 248 | } 249 | 250 | cln->handler = ngx_fluentd_cleanup; 251 | cln->data = endpoint; 252 | 253 | uc = ngx_calloc(sizeof(ngx_resolver_connection_t), cf->log); 254 | if (uc == NULL) { 255 | return NGX_ERROR; 256 | } 257 | 258 | endpoint->udp_connection = uc; 259 | 260 | uc->sockaddr = endpoint->peer_addr.sockaddr; 261 | uc->socklen = endpoint->peer_addr.socklen; 262 | uc->server = endpoint->peer_addr.name; 263 | #if defined nginx_version && ( nginx_version >= 7054 && nginx_version < 8055 ) 264 | uc->log = cf->cycle->new_log; 265 | #else 266 | uc->log = cf->cycle->new_log; 267 | #if defined nginx_version && nginx_version >= 8032 268 | uc->log.handler = NULL; 269 | uc->log.data = NULL; 270 | uc->log.action = "logging"; 271 | #endif 272 | #endif 273 | 274 | return NGX_OK; 275 | } 276 | 277 | static void 278 | ngx_fluentd_cleanup(void *data) 279 | { 280 | ngx_udp_endpoint_t *e = data; 281 | 282 | ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, 283 | "cleanup fluentd"); 284 | 285 | if(e->udp_connection) { 286 | if(e->udp_connection->udp) { 287 | ngx_close_connection(e->udp_connection->udp); 288 | } 289 | 290 | ngx_free(e->udp_connection); 291 | } 292 | } 293 | 294 | static void ngx_http_fluentd_dummy_handler(ngx_event_t *ev) 295 | { 296 | } 297 | 298 | static ngx_int_t 299 | ngx_http_fluentd_send(ngx_udp_endpoint_t *l, u_char *buf, size_t len) 300 | { 301 | ssize_t n; 302 | ngx_resolver_connection_t *uc; 303 | 304 | uc = l->udp_connection; 305 | 306 | if (uc->udp == NULL) { 307 | if(ngx_udp_connect(uc) != NGX_OK) { 308 | if(uc->udp != NULL) { 309 | ngx_free_connection(uc->udp); 310 | uc->udp = NULL; 311 | } 312 | 313 | return NGX_ERROR; 314 | } 315 | 316 | uc->udp->data = l; 317 | uc->udp->read->handler = ngx_http_fluentd_dummy_handler; 318 | uc->udp->read->resolver = 0; 319 | } 320 | 321 | n = ngx_send(uc->udp, buf, len); 322 | 323 | if (n == -1) { 324 | return NGX_ERROR; 325 | } 326 | 327 | if ((size_t) n != (size_t) len) { 328 | #if defined nginx_version && nginx_version >= 8032 329 | ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete"); 330 | #else 331 | ngx_log_error(NGX_LOG_CRIT, uc->log, 0, "send() incomplete"); 332 | #endif 333 | return NGX_ERROR; 334 | } 335 | 336 | return NGX_OK; 337 | } 338 | 339 | static void * 340 | ngx_http_fluentd_create_main_conf(ngx_conf_t *cf) 341 | { 342 | ngx_http_fluentd_main_conf_t *fmcf; 343 | 344 | fmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_fluentd_main_conf_t)); 345 | if (fmcf == NULL) { 346 | return NULL; 347 | } 348 | 349 | fmcf->collector_max = NGX_CONF_UNSET_UINT; 350 | 351 | return fmcf; 352 | } 353 | 354 | static char * 355 | ngx_http_fluentd_init_main_conf(ngx_conf_t *cf, void *conf) 356 | { 357 | ngx_http_fluentd_main_conf_t *fmcf = conf; 358 | 359 | if (fmcf->collector_max == NGX_CONF_UNSET_UINT) { 360 | fmcf->collector_max = 16; 361 | } 362 | 363 | return NGX_CONF_OK; 364 | } 365 | 366 | static void * 367 | ngx_http_fluentd_create_loc_conf(ngx_conf_t *cf) 368 | { 369 | ngx_http_fluentd_conf_t *conf; 370 | 371 | conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_fluentd_conf_t)); 372 | if (conf == NULL) { 373 | return NULL; 374 | } 375 | 376 | return conf; 377 | } 378 | 379 | static char * 380 | ngx_http_fluentd_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) 381 | { 382 | ngx_http_fluentd_conf_t *prev = parent; 383 | ngx_http_fluentd_conf_t *conf = child; 384 | 385 | if(conf->tag == NULL) { 386 | conf->tag = prev->tag; 387 | } 388 | 389 | if(conf->logs || conf->off) { 390 | return NGX_CONF_OK; 391 | } 392 | 393 | conf->logs = prev->logs; 394 | conf->off = prev->off; 395 | 396 | return NGX_CONF_OK; 397 | } 398 | 399 | static ngx_udp_endpoint_t * 400 | ngx_http_fluentd_add_endpoint(ngx_conf_t *cf, ngx_fluentd_addr_t *peer_addr) 401 | { 402 | ngx_http_fluentd_main_conf_t *fmcf; 403 | ngx_udp_endpoint_t *endpoint; 404 | 405 | fmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_fluentd_module); 406 | 407 | if (fmcf->endpoints == NULL) { 408 | fmcf->endpoints = ngx_array_create(cf->pool, fmcf->collector_max, sizeof(ngx_udp_endpoint_t)); 409 | if (fmcf->endpoints == NULL) { 410 | return NULL; 411 | } 412 | } 413 | 414 | if (fmcf->endpoints->nelts > fmcf->collector_max) { 415 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 416 | "fluentd collector count out of range, increase the fluentd_collector_max"); 417 | return NULL; 418 | } 419 | 420 | endpoint = ngx_array_push(fmcf->endpoints); 421 | if (endpoint == NULL) { 422 | return NULL; 423 | } 424 | 425 | endpoint->peer_addr = *peer_addr; 426 | 427 | return endpoint; 428 | } 429 | 430 | static char * 431 | ngx_http_fluentd_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 432 | { 433 | ngx_http_fluentd_conf_t *flcf = conf; 434 | 435 | ngx_uint_t i; 436 | ngx_str_t *value, name; 437 | ngx_http_fluentd_t *log; 438 | ngx_http_log_fmt_t *fmt; 439 | ngx_http_log_main_conf_t *lmcf; 440 | ngx_http_fluentd_main_conf_t *fmcf; 441 | ngx_url_t u; 442 | 443 | value = cf->args->elts; 444 | 445 | if (ngx_strcmp(value[1].data, "off") == 0) { 446 | flcf->off = 1; 447 | return NGX_CONF_OK; 448 | } 449 | 450 | fmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_fluentd_module); 451 | 452 | if (fmcf->collector_max == NGX_CONF_UNSET_UINT) { 453 | fmcf->collector_max = 16; 454 | } 455 | 456 | if (flcf->logs == NULL) { 457 | flcf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_fluentd_t)); 458 | if (flcf->logs == NULL) { 459 | return NGX_CONF_ERROR; 460 | } 461 | } 462 | 463 | lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module); 464 | 465 | if(lmcf == NULL) { 466 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 467 | "fluentd module requires log module to be compiled in"); 468 | return NGX_CONF_ERROR; 469 | } 470 | 471 | log = ngx_array_push(flcf->logs); 472 | if (log == NULL) { 473 | return NGX_CONF_ERROR; 474 | } 475 | 476 | ngx_memzero(log, sizeof(ngx_http_fluentd_t)); 477 | 478 | ngx_memzero(&u, sizeof(ngx_url_t)); 479 | 480 | u.url = value[1]; 481 | u.default_port = 8765; 482 | u.no_resolve = 0; 483 | 484 | if(ngx_parse_url(cf->pool, &u) != NGX_OK) { 485 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V: %s", &u.host, u.err); 486 | return NGX_CONF_ERROR; 487 | } 488 | 489 | log->endpoint = ngx_http_fluentd_add_endpoint(cf, &u.addrs[0]); 490 | 491 | if(log->endpoint == NULL) { 492 | return NGX_CONF_ERROR; 493 | } 494 | 495 | if (cf->args->nelts >= 3) { 496 | name = value[2]; 497 | 498 | if (ngx_strcmp(name.data, "combined") == 0) { 499 | lmcf->combined_used = 1; 500 | } 501 | } else { 502 | ngx_str_set(&name, "combined"); 503 | lmcf->combined_used = 1; 504 | } 505 | 506 | fmt = lmcf->formats.elts; 507 | for (i = 0; i < lmcf->formats.nelts; i++) { 508 | if (fmt[i].name.len == name.len 509 | && ngx_strcasecmp(fmt[i].name.data, name.data) == 0) 510 | { 511 | log->format = &fmt[i]; 512 | goto done; 513 | } 514 | } 515 | 516 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 517 | "unknown log format \"%V\"", &name); 518 | return NGX_CONF_ERROR; 519 | 520 | done: 521 | 522 | return NGX_CONF_OK; 523 | } 524 | 525 | static char * 526 | ngx_http_fluentd_set_tag(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 527 | { 528 | ngx_int_t n; 529 | ngx_str_t *value; 530 | ngx_http_script_compile_t sc; 531 | ngx_http_log_tag_template_t **field, *h; 532 | 533 | field = (ngx_http_log_tag_template_t**) (((u_char*)conf) + cmd->offset); 534 | 535 | value = cf->args->elts; 536 | 537 | if (*field == NULL) { 538 | *field = ngx_palloc(cf->pool, sizeof(ngx_http_log_tag_template_t)); 539 | if (*field == NULL) { 540 | return NGX_CONF_ERROR; 541 | } 542 | } 543 | 544 | h = *field; 545 | 546 | h->value = value[1]; 547 | h->lengths = NULL; 548 | h->values = NULL; 549 | 550 | /* 551 | * Compile field name 552 | */ 553 | n = ngx_http_script_variables_count(&value[1]); 554 | 555 | if (n > 0) { 556 | ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); 557 | 558 | sc.cf = cf; 559 | sc.source = &value[1]; 560 | sc.lengths = &h->lengths; 561 | sc.values = &h->values; 562 | sc.variables = n; 563 | sc.complete_lengths = 1; 564 | sc.complete_values = 1; 565 | 566 | if (ngx_http_script_compile(&sc) != NGX_OK) { 567 | return NGX_CONF_ERROR; 568 | } 569 | } 570 | 571 | return NGX_CONF_OK; 572 | } 573 | 574 | static ngx_int_t 575 | ngx_http_fluentd_init(ngx_conf_t *cf) 576 | { 577 | ngx_int_t rc; 578 | ngx_uint_t i; 579 | ngx_http_core_main_conf_t *cmcf; 580 | ngx_http_fluentd_main_conf_t *fmcf; 581 | ngx_http_handler_pt *h; 582 | ngx_udp_endpoint_t *e; 583 | 584 | fmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_fluentd_module); 585 | 586 | if(fmcf->endpoints != NULL) { 587 | e = fmcf->endpoints->elts; 588 | for(i = 0;i < fmcf->endpoints->nelts;i++) { 589 | rc = ngx_fluentd_init_endpoint(cf, e + i); 590 | 591 | if(rc != NGX_OK) { 592 | return NGX_ERROR; 593 | } 594 | } 595 | 596 | cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); 597 | 598 | h = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers); 599 | if (h == NULL) { 600 | return NGX_ERROR; 601 | } 602 | 603 | *h = ngx_http_fluentd_handler; 604 | } 605 | 606 | return NGX_OK; 607 | } 608 | --------------------------------------------------------------------------------